From 90648977361bd7997f6cd5856db41532fb0fed9b Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:24:08 -0500 Subject: [PATCH 001/300] fix compatibility nightly.link in README.md (#3768) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ef96bd8e4..ad80f7f2f 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ If you want to playtest a continuous integration build, you can find them at the * [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip) * [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip) * [Linux (performance)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-performance.zip) _(requires `glibc 2.35` or newer, but will be more performant than the compatibility build.)_ -* [Linux (compatibility)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatiblity.zip) _(compatible with most Linux distributions, but may not be as performant as the performance build.)_ +* [Linux (compatibility)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatibility.zip) _(compatible with most Linux distributions, but may not be as performant as the performance build.)_ * [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip) * [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip) From 6cb3a830bdbfb09e228c073cdf61f8dc8f7b28d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaro=20Mart=C3=ADnez?= Date: Fri, 5 Jan 2024 18:41:09 -0500 Subject: [PATCH 002/300] Restore previous Boost download URL (#3809) This reverts commit 96abadd904d6f5eaa2bd947c2d0fbe43bdba5f8c. --- soh/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 9bf8b973d..fd0c6ac25 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -328,7 +328,7 @@ endif() include(FetchContent) FetchContent_Declare( Boost - URL https://sourceforge.net/projects/boost/files/boost/1.81.0/boost_1_81_0.tar.gz + URL https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6 SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it) DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change From 37b2fc0745a149d039b0944ce4e35c0bddc6d1e8 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 6 Jan 2024 01:51:48 +0000 Subject: [PATCH 003/300] Make noclip only effect player (#3788) --- soh/src/code/z_bgcheck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 4acc68e55..7c99e7ca2 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -1902,7 +1902,7 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul s32 bgId2; f32 nx, ny, nz; // unit normal of polygon - if (CVarGetInteger("gNoClip", 0) != 0) { + if (CVarGetInteger("gNoClip", 0) && actor != NULL && actor->id == ACTOR_PLAYER) { return false; } From 02938cfba20911dc95f68d60ff66b85901ecef44 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 5 Jan 2024 18:53:18 -0700 Subject: [PATCH 004/300] Fix Starting Triforce Piece Count (#3797) * Move zeroing of triforcePiecesCollected to the beginning of `Randomizer_InitSaveFile()` to fix starting TFP count issues. --- soh/soh/Enhancements/randomizer/savefile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 33278d0b7..fb04eca0c 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -207,6 +207,9 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.randomizerInf[i] = 0; } + // Reset triforce pieces collected + gSaveContext.triforcePiecesCollected = 0; + gSaveContext.cutsceneIndex = 0; // no intro cutscene // Starts pending ice traps out at 0 before potentially incrementing them down the line. gSaveContext.pendingIceTrapCount = 0; @@ -442,8 +445,5 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth } - // Reset triforce pieces collected - gSaveContext.triforcePiecesCollected = 0; - SetStartingItems(); } From 321c258d6912f8bac7ad04be8cd6a9f947aa4024 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sat, 6 Jan 2024 01:55:09 +0000 Subject: [PATCH 005/300] Fix Fire Temple Boss Door Logic (#3774) * Fix Fire Temple Boss Door Logic * Update soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp Co-authored-by: Adam Bird --------- Co-authored-by: Adam Bird --- .../randomizer/3drando/location_access/locacc_fire_temple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index 440483af6..ff2fb885c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -40,7 +40,7 @@ void AreaTable_Init_FireTemple() { }, { //Exits Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}), - Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));}}), + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && (LogicFireBossDoorJump || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}))) || CanUse(HOVER_BOOTS));}}), }); areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { From a0258f0fca8def02c3ea3e723d359b139525c146 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:21:18 -0500 Subject: [PATCH 006/300] Add Invert Y-Axis and Apply Right-Stick Aiming to Z-Weapon Aiming (#3304) * Add right-stick aiming to third-person aim * Add Z-aiming CVar and inversion to Z-aiming * Create calculation for rel.right_stick and apply it in Z-aiming * Move option to First-Person section to match shield * Fix max/min aiming heights * Expand min/max + comment * block out vanilla + comments * block vanilla code better * Remove extra space * new documentation formatting * rewrite ==0 and !=0 --- soh/include/functions.h | 8 +++ .../controls/GameControlEditor.cpp | 2 + soh/src/code/padmgr.c | 10 ++++ soh/src/code/padutils.c | 57 +++++++++++++++++++ .../actors/ovl_player_actor/z_player.c | 38 +++++++++++-- 5 files changed, 111 insertions(+), 4 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 6f188a842..3898ea63d 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2210,6 +2210,14 @@ s8 PadUtils_GetRelYImpl(Input* input); s8 PadUtils_GetRelX(Input* input); s8 PadUtils_GetRelY(Input* input); void PadUtils_UpdateRelXY(Input* input); +s8 PadUtils_GetCurRX(Input* input); +s8 PadUtils_GetCurRY(Input* input); +void PadUtils_SetRelRXY(Input* input, s32 x, s32 y); +s8 PadUtils_GetRelRXImpl(Input* input); +s8 PadUtils_GetRelRYImpl(Input* input); +s8 PadUtils_GetRelRX(Input* input); +s8 PadUtils_GetRelRY(Input* input); +void PadUtils_UpdateRelRXY(Input* input); s32 PadSetup_Init(OSMesgQueue* mq, u8* outMask, OSContStatus* status); f32 Math_FTanF(f32 x); f32 Math_FFloorF(f32 x); diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index 98de43f34..c9cab6ba4 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -240,6 +240,8 @@ namespace GameControlEditor { DrawHelpIcon("Inverts the Shield Aiming Y Axis"); UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis"); DrawHelpIcon("Inverts the Shield Aiming X Axis"); + UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + DrawHelpIcon("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"); UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson"); DrawHelpIcon("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false)) { diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index 4735a259c..3315a9fe8 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -297,6 +297,11 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) { PadUtils_UpdateRelXY(input); input->press.stick_x += (s8)(input->cur.stick_x - input->prev.stick_x); input->press.stick_y += (s8)(input->cur.stick_y - input->prev.stick_y); + // #region SOH [Enhancement] + PadUtils_UpdateRelRXY(input); + input->press.right_stick_x += (s8)(input->cur.right_stick_x - input->prev.right_stick_x); + input->press.right_stick_y += (s8)(input->cur.right_stick_y - input->prev.right_stick_y); + // #endregion } uint8_t rumble = (padMgr->rumbleEnable[0] > 0); @@ -389,6 +394,11 @@ void PadMgr_RequestPadData(PadMgr* padMgr, Input* inputs, s32 mode) { PadUtils_UpdateRelXY(newInput); newInput->press.stick_x += (s8)(newInput->cur.stick_x - newInput->prev.stick_x); newInput->press.stick_y += (s8)(newInput->cur.stick_y - newInput->prev.stick_y); + // #region SOH [Enhancement] + PadUtils_UpdateRelRXY(newInput); + newInput->press.right_stick_x += (s8)(newInput->cur.right_stick_x - newInput->prev.right_stick_x); + newInput->press.right_stick_y += (s8)(newInput->cur.right_stick_y - newInput->prev.right_stick_y); + // #endregion } ogInput++; newInput++; diff --git a/soh/src/code/padutils.c b/soh/src/code/padutils.c index 6a58b14f6..c4548ae32 100644 --- a/soh/src/code/padutils.c +++ b/soh/src/code/padutils.c @@ -92,3 +92,60 @@ void PadUtils_UpdateRelXY(Input* input) { PadUtils_SetRelXY(input, relX, relY); } + +// #region SOH [Enhancement] +s8 PadUtils_GetCurRX(Input* input) { + return input->cur.right_stick_x; +} + +s8 PadUtils_GetCurRY(Input* input) { + return input->cur.right_stick_y; +} + +void PadUtils_SetRelRXY(Input* input, s32 x, s32 y) { + input->rel.right_stick_x = x; + input->rel.right_stick_y = y; +} + +s8 PadUtils_GetRelRXImpl(Input* input) { + return input->rel.right_stick_x; +} + +s8 PadUtils_GetRelRYImpl(Input* input) { + return input->rel.right_stick_y; +} + +s8 PadUtils_GetRelRX(Input* input) { + return PadUtils_GetRelRXImpl(input); +} + +s8 PadUtils_GetRelRY(Input* input) { + return PadUtils_GetRelRYImpl(input); +} + +void PadUtils_UpdateRelRXY(Input* input) { + s32 curX = PadUtils_GetCurRX(input); + s32 curY = PadUtils_GetCurRY(input); + s32 relX; + s32 relY; + + if (curX > 7) { + relX = (curX < 0x43) ? curX - 7 : 0x43 - 7; + } else if (curX < -7) { + relX = (curX > -0x43) ? curX + 7 : -0x43 + 7; + } else { + relX = 0; + } + + if (curY > 7) { + relY = (curY < 0x43) ? curY - 7 : 0x43 - 7; + + } else if (curY < -7) { + relY = (curY > -0x43) ? curY + 7 : -0x43 + 7; + } else { + relY = 0; + } + + PadUtils_SetRelRXY(input, relX, relY); +} +// #endregion diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 82a600bee..523e7cf11 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7235,11 +7235,41 @@ s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) { *arg2 = this->actor.shape.rot.y; } - if (this->unk_664 != NULL) { - func_8083DB98(this, 1); + // #region SOH [Enhancement] + if (CVarGetInteger("gRightStickAiming", 0) || !CVarGetInteger("gInvertZAimingYAxis", 1)) { + + if (this->unk_664 != NULL) { + func_8083DB98(this, 1); + } else { + int8_t relStickY; + + // preserves simultaneous left/right-stick aiming + if (CVarGetInteger("gRightStickAiming", 0)) { + if ((sControlInput->rel.stick_y + sControlInput->rel.right_stick_y) >= 0) { + relStickY = (((sControlInput->rel.stick_y) > (sControlInput->rel.right_stick_y)) + ? (sControlInput->rel.stick_y) + : (sControlInput->rel.right_stick_y)); + } else { + relStickY = (((sControlInput->rel.stick_y) < (sControlInput->rel.right_stick_y)) + ? (sControlInput->rel.stick_y) + : (sControlInput->rel.right_stick_y)); + } + } else { + relStickY = sControlInput->rel.stick_y; + } + + Math_SmoothStepToS(&this->actor.focus.rot.x, + relStickY * (CVarGetInteger("gInvertZAimingYAxis", 1) ? 1 : -1) * 240.0f, 14, 4000, 30); + func_80836AB8(this, 1); + } + // #endregion } else { - Math_SmoothStepToS(&this->actor.focus.rot.x, sControlInput->rel.stick_y * 240.0f, 14, 4000, 30); - func_80836AB8(this, 1); + if (this->unk_664 != NULL) { + func_8083DB98(this, 1); + } else { + Math_SmoothStepToS(&this->actor.focus.rot.x, sControlInput->rel.stick_y * 240.0f, 14, 4000, 30); + func_80836AB8(this, 1); + } } } else { if (this->unk_664 != NULL) { From 21796367a0fcde197d94dcfa5d72f50c54192770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaro=20Mart=C3=ADnez?= Date: Mon, 8 Jan 2024 13:39:49 -0500 Subject: [PATCH 007/300] Use temporary mirror for Boost download URL (#3822) --- soh/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index fd0c6ac25..5c239ae13 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -328,7 +328,7 @@ endif() include(FetchContent) FetchContent_Declare( Boost - URL https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz + URL https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6 SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it) DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change From 01529126badfae208d9e999cf820676c36c2192c Mon Sep 17 00:00:00 2001 From: Josh Bodner <30329717+jbodner09@users.noreply.github.com> Date: Mon, 15 Jan 2024 07:22:56 -0800 Subject: [PATCH 008/300] Imgui polish (#3481) * Rearrange menus for better layout on smaller screens. * Automatically calculate +/- increments for float sliders * Add needed header * Use stringstream instead of format since apparently most platforms don't actually support all of c++20 yet boooooo * Add header that only Mac complained about for some reason * Theoretical performance improvement * Actual performance improvement --- soh/soh/Enhancements/audio/AudioEditor.cpp | 4 +- .../controls/GameControlEditor.cpp | 12 +- .../controls/SohInputEditorWindow.cpp | 2 +- .../cosmetics/CosmeticsEditor.cpp | 22 +- soh/soh/SohMenuBar.cpp | 453 ++++++++++-------- soh/soh/UIWidgets.cpp | 64 ++- soh/soh/UIWidgets.hpp | 1 + 7 files changed, 312 insertions(+), 246 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index 8b0615a83..654446005 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -422,8 +422,8 @@ void AudioEditor::DrawElement() { ImGui::PopItemWidth(); ImGui::NewLine(); ImGui::PopItemWidth(); - UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %f", "##linkVoiceFreqMultiplier", - "gLinkVoiceFreqMultiplier", 0.4, 2.5, "", 1.0, false, false); + UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier", + "gLinkVoiceFreqMultiplier", 0.4, 2.5, "", 1.0, true, true); ImGui::SameLine(); const std::string resetButton = "Reset##linkVoiceFreqMultiplier"; if (ImGui::Button(resetButton.c_str())) { diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index c9cab6ba4..46366135f 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -251,9 +251,9 @@ namespace GameControlEditor { } } if (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { - UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %d %%", "##FirstPersonSensitivity Horizontal", + UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal", "gFirstPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true); - UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %d %%", "##FirstPersonSensitivity Vertical", + UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical", "gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true); } UIWidgets::Spacer(0); @@ -270,9 +270,9 @@ namespace GameControlEditor { UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera"); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %d %%", "##ThirdPersonSensitivity Horizontal", + UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal", "gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %d %%", "##ThirdPersonSensitivity Vertical", + UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical", "gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist", "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); @@ -322,8 +322,8 @@ namespace GameControlEditor { window->BeginGroupPanelPublic("Walk Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); - UIWidgets::PaddedEnhancementSliderFloat("Modifier 1: %d %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %d %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); window->EndGroupPanelPublic(0); } ImGui::EndDisabled(); diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 4d0b6b64d..a5ecc39dc 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1085,7 +1085,7 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { ImGui::SameLine(); ImGui::Text("Custom Color"); } - UIWidgets::PaddedEnhancementSliderFloat("Brightness: %d%%", "##LED_Brightness", "gLedBrightness", 0.0f, + UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", "gLedBrightness", 0.0f, 1.0f, "", 1.0f, true, true); DrawHelpIcon("Sets the brightness of controller LEDs. 0% brightness = LEDs off."); UIWidgets::PaddedEnhancementCheckbox( diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 378197bcd..50b5c5b27 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1491,7 +1491,7 @@ void DrawSillyTab() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } - if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %f", "##Link_BodyScale", "gCosmetics.Link_BodyScale.Value", 0.001f, 0.025f, "", 0.01f, true)) { + if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %.3fx", "##Link_BodyScale", "gCosmetics.Link_BodyScale.Value", 0.001f, 0.025f, "", 0.01f, true)) { CVarSetInteger("gCosmetics.Link_BodyScale.Changed", 1); } ImGui::SameLine(); @@ -1506,7 +1506,7 @@ void DrawSillyTab() { player->actor.scale.z = 0.01f; } } - if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %f", "##Link_HeadScale", "gCosmetics.Link_HeadScale.Value", 0.4f, 4.0f, "", 1.0f, false)) { + if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", "gCosmetics.Link_HeadScale.Value", 0.4f, 4.0f, "", 1.0f, false)) { CVarSetInteger("gCosmetics.Link_HeadScale.Changed", 1); } ImGui::SameLine(); @@ -1515,7 +1515,7 @@ void DrawSillyTab() { CVarClear("gCosmetics.Link_HeadScale.Changed"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) { + if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %.3fx", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) { CVarSetInteger("gCosmetics.Link_SwordScale.Changed", 1); } ImGui::SameLine(); @@ -1524,44 +1524,44 @@ void DrawSillyTab() { CVarClear("gCosmetics.Link_SwordScale.Changed"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false); + UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %.0f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false); ImGui::SameLine(); if (ImGui::Button("Reset##BunnyHood_EarLength")) { CVarClear("gCosmetics.BunnyHood_EarLength"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false); + UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %.0f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false); ImGui::SameLine(); if (ImGui::Button("Reset##BunnyHood_EarSpread")) { CVarClear("gCosmetics.BunnyHood_EarSpread"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 5000.0f, "", 0.0f, false); + UIWidgets::EnhancementSliderFloat("Goron Neck Length: %.0f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 5000.0f, "", 0.0f, false); ImGui::SameLine(); if (ImGui::Button("Reset##Goron_NeckLength")) { CVarClear("gCosmetics.Goron_NeckLength"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } UIWidgets::EnhancementCheckbox("Unfix Goron Spin", "gUnfixGoronSpin"); - UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false); + UIWidgets::EnhancementSliderFloat("Fairies Size: %.2fx", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false); ImGui::SameLine(); if (ImGui::Button("Reset##Fairies_Size")) { CVarClear("gCosmetics.Fairies_Size"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false); + UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %.2fx", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false); ImGui::SameLine(); if (ImGui::Button("Reset##N64Logo_SpinSpeed")) { CVarClear("gCosmetics.N64Logo_SpinSpeed"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, false); + UIWidgets::EnhancementSliderFloat("Moon Size: %.1f %%", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, true); ImGui::SameLine(); if (ImGui::Button("Reset##Moon_Size")) { CVarClear("gCosmetics.Moon_Size"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) { + if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %.0f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) { CVarSetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 1); } ImGui::SameLine(); @@ -1793,7 +1793,7 @@ void CosmeticsEditorWindow::DrawElement() { } } UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync"); - UIWidgets::EnhancementSliderFloat("Rainbow Speed: %f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false); + UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false, true); if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0))) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 7c1f51cf1..97bc012b6 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -187,17 +187,17 @@ void DrawSettingsMenu() { if (ImGui::BeginMenu("Settings")) { if (ImGui::BeginMenu("Audio")) { - UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true); - if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %d %%", "##Main_Music_Vol", "gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %.1f %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true); + if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %.1f %%", "##Main_Music_Vol", "gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { Audio_SetGameVolume(SEQ_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %d %%", "##Sub_Music_Vol", "gSubMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %.1f %%", "##Sub_Music_Vol", "gSubMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { Audio_SetGameVolume(SEQ_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %d %%", "##Sound_Effect_Vol", "gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %.1f %%", "##Sound_Effect_Vol", "gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { Audio_SetGameVolume(SEQ_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %d %%", "##Fanfare_Vol", "gFanfareVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %.1f %%", "##Fanfare_Vol", "gFanfareVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { Audio_SetGameVolume(SEQ_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); } @@ -255,7 +255,7 @@ void DrawSettingsMenu() { #endif UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false, true, true, false); + UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.2f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false, true, true, false); UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, true, true, false); UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later"); @@ -269,7 +269,7 @@ void DrawSettingsMenu() { #ifndef __APPLE__ const bool disabled_resolutionSlider = CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && CVarGetInteger("gAdvancedResolution.Enabled", 0); - if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, + if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); } @@ -527,22 +527,58 @@ void DrawEnhancementsMenu() { { if (ImGui::BeginMenu("Time Savers")) { + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8.0f); + ImGui::BeginTable("##timeSaversMenu", 2, ImGuiTableFlags_SizingFixedFit); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableNextColumn(); + UIWidgets::Spacer(0); + ImGui::Text("Speed-ups:"); + UIWidgets::PaddedSeparator(); + UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true); UIWidgets::Tooltip("Holding down B skips text"); UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); - UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, true, false, true); - UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", true, false); + UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); - UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); - UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); + UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); + UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); + UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); + bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); + static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, + forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); + UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); + UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); + UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); + UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false); + UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); + UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false); + UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); + + ImGui::TableNextColumn(); + UIWidgets::Spacer(0); + ImGui::Text("Changes:"); + UIWidgets::PaddedSeparator(); + + UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); + UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); + UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); + UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" + "This doesn't work if the save was made in a grotto."); UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); UIWidgets::Tooltip("Prevent forced Navi conversations"); UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); + UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); + UIWidgets::Tooltip("Nighttime Skulltulas will spawn during both day and night."); + UIWidgets::PaddedEnhancementCheckbox("Dampe Appears All Night", "gDampeAllNight", true, false); + UIWidgets::Tooltip("Makes Dampe appear anytime during the night, not just his usual working hours."); UIWidgets::PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); UIWidgets::Tooltip("Kick open every chest"); UIWidgets::PaddedText("Chest size & texture matches contents", true, false); @@ -566,36 +602,14 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Chests of Agony", "gChestSizeDependsStoneOfAgony", true, false); UIWidgets::Tooltip("Only change the size/texture of chests if you have the Stone of Agony."); } - UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); - UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); UIWidgets::PaddedEnhancementCheckbox("Ask to Equip New Items", "gAskToEquip", true, false); UIWidgets::Tooltip("Adds a prompt to equip newly-obtained swords, shields and tunics"); UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); - UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); - bool forceSkipScarecrow = IS_RANDO && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); - static const char* forceSkipScarecrowText = - "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; - UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, - forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); - UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); - UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" - "This doesn't work if the save was made in a grotto."); - UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); - UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); - UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", "gMarketSneak", true, false); - UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking " - "to the guard next to the gate."); - UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false); - UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); - UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); - UIWidgets::Tooltip("Nighttime Skulltulas will spawn during both day and night."); - UIWidgets::PaddedEnhancementCheckbox("Dampe Appears All Night", "gDampeAllNight", true, false); - UIWidgets::Tooltip("Makes Dampe appear anytime during the night, not just his usual working hours."); + UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate."); + UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); + UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); UIWidgets::PaddedText("Time Travel with the Song of Time", true, false); UIWidgets::EnhancementCombobox("gTimeTravel", timeTravelOptions, 0); UIWidgets::Tooltip("Allows Link to freely change age by playing the Song of Time.\n" @@ -606,8 +620,8 @@ void DrawEnhancementsMenu() { "- Obtained the Master Sword\n" "- Not within range of Time Block\n" "- Not within range of Ocarina playing spots"); - UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false); - UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); + + ImGui::EndTable(); ImGui::EndMenu(); } @@ -660,83 +674,6 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Difficulty Options")) { - UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", "gDeleteFileOnDeath", true, false); - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); - UIWidgets::Tooltip("Dying will delete your file\n\n " ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSABLE\nUSE AT YOUR OWN RISK!"); - ImGui::PopStyleColor(); - if (UIWidgets::PaddedEnhancementCheckbox("Permanent heart loss", "gPermanentHeartLoss", true, false)) { - UpdatePermanentHeartLossState(); - } - UIWidgets::Tooltip("When you lose 4 quarters of a heart you will permanently lose that heart container.\n\nDisabling this after the fact will restore your heart containers."); - ImGui::Text("Damage Multiplier"); - UIWidgets::EnhancementCombobox("gDamageMul", allPowers, 0); - UIWidgets::Tooltip( - "Modifies all sources of damage not affected by other sliders\n" - "2x: Can survive all common attacks from the start of the game\n" - "4x: Dies in 1 hit to any substantial attack from the start of the game\n" - "8x: Can only survive trivial damage from the start of the game\n" - "16x: Can survive all common attacks with max health without double defense\n" - "32x: Can survive all common attacks with max health and double defense\n" - "64x: Can survive trivial damage with max health without double defense\n" - "128x: Can survive trivial damage with max health and double defense\n" - "256x: Cannot survive damage" - ); - UIWidgets::PaddedText("Fall Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gFallDamageMul", subPowers, 0); - UIWidgets::Tooltip( - "Modifies all fall damage\n" - "2x: Can survive all fall damage from the start of the game\n" - "4x: Can only survive short fall damage from the start of the game\n" - "8x: Cannot survive any fall damage from the start of the game\n" - "16x: Can survive all fall damage with max health without double defense\n" - "32x: Can survive all fall damage with max health and double defense\n" - "64x: Can survive short fall damage with double defense\n" - "128x: Cannot survive fall damage" - ); - UIWidgets::PaddedText("Void Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gVoidDamageMul", subSubPowers, 0); - UIWidgets::Tooltip( - "Modifies damage taken after falling into a void\n" - "2x: Can survive void damage from the start of the game\n" - "4x: Cannot survive void damage from the start of the game\n" - "8x: Can survive void damage twice with max health without double defense\n" - "16x: Can survive void damage with max health without double defense\n" - "32x: Can survive void damage with max health and double defense\n" - "64x: Cannot survive void damage" - ); - UIWidgets::PaddedText("Bonk Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gBonkDamageMul", bonkDamageValues, BONK_DAMAGE_NONE); - UIWidgets::Tooltip("Modifies damage taken after bonking."); - UIWidgets::PaddedEnhancementCheckbox("Spawn with full health", "gFullHealthSpawn", true, false); - UIWidgets::Tooltip("Respawn with full health instead of 3 Hearts"); - UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); - UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); - bool forceEnableBombchuDrops = IS_RANDO && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1; - static const char* forceEnableBombchuDropsText = - "This setting is forcefully enabled because a savefile\nwith \"Enable Bombchu Drops\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false, - forceEnableBombchuDrops, forceEnableBombchuDropsText, UIWidgets::CheckboxGraphics::Checkmark); - UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); - UIWidgets::PaddedEnhancementCheckbox("Trees Drop Sticks", "gTreeStickDrops", true, false); - UIWidgets::Tooltip("Bonking into trees will have a chance to drop up to 3 sticks. Must already have obtained sticks."); - UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); - UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); - UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false); - UIWidgets::Tooltip("All major bosses move and act twice as fast."); - UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false); - UIWidgets::Tooltip("All regular enemies and mini-bosses move and act twice as fast."); - UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); - UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); - UIWidgets::PaddedEnhancementCheckbox("Always Win Dampe Digging Game", "gDampeWin", true, false, SaveManager::Instance->IsRandoFile(), - "This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark); - UIWidgets::Tooltip("Always win the heart piece/purple rupee on the first dig in Dampe's grave digging game, just like in rando\nIn a rando file, this is unconditionally enabled"); - UIWidgets::PaddedEnhancementCheckbox("All Dogs are Richard", "gAllDogsRichard", true, false); - UIWidgets::Tooltip("All dogs can be traded in and will count as Richard."); - UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", "gCuccoStayDurationMultiplier", 1, 5, "", 1, true, true, false); - UIWidgets::Tooltip("Cuccos will stay in place longer after putting them down, by a multiple of the value of the slider."); - UIWidgets::Spacer(0); - if (ImGui::BeginMenu("Potion Values")) { UIWidgets::EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); @@ -878,6 +815,84 @@ void DrawEnhancementsMenu() { ImGui::EndMenu(); } + UIWidgets::Spacer(0); + + UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", "gDeleteFileOnDeath", true, false); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); + UIWidgets::Tooltip("Dying will delete your file\n\n " ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSABLE\nUSE AT YOUR OWN RISK!"); + ImGui::PopStyleColor(); + if (UIWidgets::PaddedEnhancementCheckbox("Permanent heart loss", "gPermanentHeartLoss", true, false)) { + UpdatePermanentHeartLossState(); + } + UIWidgets::Tooltip("When you lose 4 quarters of a heart you will permanently lose that heart container.\n\nDisabling this after the fact will restore your heart containers."); + ImGui::Text("Damage Multiplier"); + UIWidgets::EnhancementCombobox("gDamageMul", allPowers, 0); + UIWidgets::Tooltip( + "Modifies all sources of damage not affected by other sliders\n" + "2x: Can survive all common attacks from the start of the game\n" + "4x: Dies in 1 hit to any substantial attack from the start of the game\n" + "8x: Can only survive trivial damage from the start of the game\n" + "16x: Can survive all common attacks with max health without double defense\n" + "32x: Can survive all common attacks with max health and double defense\n" + "64x: Can survive trivial damage with max health without double defense\n" + "128x: Can survive trivial damage with max health and double defense\n" + "256x: Cannot survive damage" + ); + UIWidgets::PaddedText("Fall Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gFallDamageMul", subPowers, 0); + UIWidgets::Tooltip( + "Modifies all fall damage\n" + "2x: Can survive all fall damage from the start of the game\n" + "4x: Can only survive short fall damage from the start of the game\n" + "8x: Cannot survive any fall damage from the start of the game\n" + "16x: Can survive all fall damage with max health without double defense\n" + "32x: Can survive all fall damage with max health and double defense\n" + "64x: Can survive short fall damage with double defense\n" + "128x: Cannot survive fall damage" + ); + UIWidgets::PaddedText("Void Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gVoidDamageMul", subSubPowers, 0); + UIWidgets::Tooltip( + "Modifies damage taken after falling into a void\n" + "2x: Can survive void damage from the start of the game\n" + "4x: Cannot survive void damage from the start of the game\n" + "8x: Can survive void damage twice with max health without double defense\n" + "16x: Can survive void damage with max health without double defense\n" + "32x: Can survive void damage with max health and double defense\n" + "64x: Cannot survive void damage" + ); + UIWidgets::PaddedText("Bonk Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gBonkDamageMul", bonkDamageValues, BONK_DAMAGE_NONE); + UIWidgets::Tooltip("Modifies damage taken after bonking."); + UIWidgets::PaddedEnhancementCheckbox("Spawn with full health", "gFullHealthSpawn", true, false); + UIWidgets::Tooltip("Respawn with full health instead of 3 Hearts"); + UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); + UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); + bool forceEnableBombchuDrops = IS_RANDO && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1; + static const char* forceEnableBombchuDropsText = + "This setting is forcefully enabled because a savefile\nwith \"Enable Bombchu Drops\" is loaded."; + UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false, + forceEnableBombchuDrops, forceEnableBombchuDropsText, UIWidgets::CheckboxGraphics::Checkmark); + UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); + UIWidgets::PaddedEnhancementCheckbox("Trees Drop Sticks", "gTreeStickDrops", true, false); + UIWidgets::Tooltip("Bonking into trees will have a chance to drop up to 3 sticks. Must already have obtained sticks."); + UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); + UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); + UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false); + UIWidgets::Tooltip("All major bosses move and act twice as fast."); + UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false); + UIWidgets::Tooltip("All regular enemies and mini-bosses move and act twice as fast."); + UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); + UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); + UIWidgets::PaddedEnhancementCheckbox("Always Win Dampe Digging Game", "gDampeWin", true, false, SaveManager::Instance->IsRandoFile(), + "This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark); + UIWidgets::Tooltip("Always win the heart piece/purple rupee on the first dig in Dampe's grave digging game, just like in rando\nIn a rando file, this is unconditionally enabled"); + UIWidgets::PaddedEnhancementCheckbox("All Dogs are Richard", "gAllDogsRichard", true, false); + UIWidgets::Tooltip("All dogs can be traded in and will count as Richard."); + UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", "gCuccoStayDurationMultiplier", 1, 5, "", 1, true, true, false); + UIWidgets::Tooltip("Cuccos will stay in place longer after putting them down, by a multiple of the value of the slider."); + ImGui::EndMenu(); } @@ -970,37 +985,9 @@ void DrawEnhancementsMenu() { ImGui::EndMenu(); } - UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false); - UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) { - if (CVarGetInteger("gDisableDrawDistance", 0) == 0) { - CVarSetInteger("gDisableKokiriDrawDistance", 0); - } - } - UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVarGetInteger("gDisableDrawDistance", 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); - UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); - } - UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); - UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); - UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); - UIWidgets::Tooltip("Displays a tick in the top center of the screen to help with glitch line-ups in SoH, as traditional UI based line-ups do not work outside of 4:3"); - UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); - UIWidgets::Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); - UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); - UIWidgets::Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); - UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); - UIWidgets::Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); - UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); - UIWidgets::Tooltip("Always shows dungeon entrance icons on the minimap"); - UIWidgets::PaddedEnhancementCheckbox("Show Gauntlets in First Person", "gFPSGauntlets", true, false); - UIWidgets::Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OOT3D"); - if (UIWidgets::PaddedEnhancementCheckbox("Color Temple of Time's Medallions", "gToTMedallionsColors", true, false)) { - PatchToTMedallions(); - } - UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored"); + UIWidgets::Spacer(0); + if (ImGui::BeginMenu("Animated Link in Pause Menu")) { ImGui::Text("Rotation"); UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); @@ -1044,6 +1031,39 @@ void DrawEnhancementsMenu() { ImGui::EndMenu(); } + + UIWidgets::Spacer(0); + + UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false); + UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); + if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) { + if (CVarGetInteger("gDisableDrawDistance", 0) == 0) { + CVarSetInteger("gDisableKokiriDrawDistance", 0); + } + } + UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); + if (CVarGetInteger("gDisableDrawDistance", 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); + UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); + } + UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); + UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); + UIWidgets::Tooltip("Displays a tick in the top center of the screen to help with glitch line-ups in SoH, as traditional UI based line-ups do not work outside of 4:3"); + UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); + UIWidgets::Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); + UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); + UIWidgets::Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); + UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); + UIWidgets::Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); + UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); + UIWidgets::Tooltip("Always shows dungeon entrance icons on the minimap"); + UIWidgets::PaddedEnhancementCheckbox("Show Gauntlets in First Person", "gFPSGauntlets", true, false); + UIWidgets::Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OOT3D"); + if (UIWidgets::PaddedEnhancementCheckbox("Color Temple of Time's Medallions", "gToTMedallionsColors", true, false)) { + PatchToTMedallions(); + } + UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored"); UIWidgets::PaddedText("Fix Vanishing Paths", true, false); if (UIWidgets::EnhancementCombobox("gSceneSpecificDirtPathFix", zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) { UpdateDirtPathFixState(gPlayState->sceneNum); @@ -1205,8 +1225,6 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Shadow Tag Mode", "gShadowTag", true, false); UIWidgets::Tooltip("A wallmaster follows Link everywhere, don't get caught!"); - UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Additional Traps", "gAddTraps.enabled", true, false); UIWidgets::Tooltip("Enables additional Trap variants."); @@ -1295,6 +1313,51 @@ void DrawCheatsMenu() { if (ImGui::BeginMenu("Cheats")) { ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8.0f); + ImGui::BeginTable("##cheatsMenu", 2, ImGuiTableFlags_SizingFixedFit); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableNextColumn(); + UIWidgets::Spacer(2.0f); + ImGui::Text("Inventory:"); + UIWidgets::PaddedSeparator(); + + UIWidgets::PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); + UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); + UIWidgets::PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); + UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); + UIWidgets::PaddedEnhancementCheckbox("Easy QPA", "gEzQPA", true, false); + UIWidgets::Tooltip("Gives you the glitched damage value of the quick put away glitch."); + UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", "gTimelessEquipment", true, false); + UIWidgets::Tooltip("Allows any item to be equipped, regardless of age\nAlso allows Child to use Adult strength upgrades"); + UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); + UIWidgets::Tooltip("Allows you to use any item at any location"); + UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); + UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); + UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); + UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); + UIWidgets::Spacer(2.0f); + ImGui::Text("Deku Sticks:"); + UIWidgets::EnhancementCombobox("gDekuStickCheat", DekuStickCheat, DEKU_STICK_NORMAL); + UIWidgets::Spacer(2.0f); + UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.2fx", "##gBombTimerMultiplier", "gBombTimerMultiplier", 0.1f, 5.0f, "", 1.0f, false); + UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", "gHookshotEverything", true, false); + UIWidgets::Tooltip("Makes every surface in the game hookshot-able"); + UIWidgets::Spacer(0); + UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", "gCheatHookshotReachMultiplier", 1.0f, 5.0f, "", 1.0f, false); + UIWidgets::Spacer(2.0f); + if (ImGui::Button("Change Age")) { + CVarSetInteger("gSwitchAge", 1); + } + UIWidgets::Tooltip("Switches Link's age and reloads the area."); + UIWidgets::Spacer(2.0f); + if (ImGui::Button("Clear Cutscene Pointer")) { + GameInteractor::RawAction::ClearCutscenePointer(); + } + UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); + + ImGui::TableNextColumn(); + UIWidgets::Spacer(2.0f); if (ImGui::BeginMenu("Infinite...")) { UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney"); @@ -1307,51 +1370,8 @@ void DrawCheatsMenu() { ImGui::EndMenu(); } - UIWidgets::PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); - UIWidgets::Tooltip("Allows you to walk through walls"); - UIWidgets::PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); - UIWidgets::Tooltip("Makes every surface in the game climbable"); - UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", "gHookshotEverything", true, false); - UIWidgets::Tooltip("Makes every surface in the game hookshot-able"); - UIWidgets::Spacer(2.0f); - UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.1fx", "##gCheatHookshotReachMultiplier", "gCheatHookshotReachMultiplier", 1.0f, 5.0f, "", 1.0f, false); - UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.1fx", "##gBombTimerMultiplier", "gBombTimerMultiplier", 0.1f, 5.0f, "", 1.0f, false); - UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); - UIWidgets::Tooltip("Holding L makes you float into the air"); - UIWidgets::PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); - UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); - UIWidgets::PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); - UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); - UIWidgets::PaddedEnhancementCheckbox("Easy QPA", "gEzQPA", true, false); - UIWidgets::Tooltip("Gives you the glitched damage value of the quick put away glitch."); - UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", "gTimelessEquipment", true, false); - UIWidgets::Tooltip("Allows any item to be equipped, regardless of age\nAlso allows Child to use Adult strength upgrades"); - UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", "gCheatEasyPauseBufferEnabled", true, false); - UIWidgets::Tooltip("Continue holding START button when unpausing to only advance a single frame and then re-pause"); - const bool bEasyFrameAdvanceEnabled = CVarGetInteger("gCheatEasyPauseBufferEnabled", 0); - UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", "gCheatEasyInputBufferingEnabled", true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled"); - UIWidgets::Tooltip("Inputs that are held down while the Subscreen is closing will be pressed when the game is resumed"); - UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); - UIWidgets::Tooltip("Allows you to use any item at any location"); - UIWidgets::PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); - UIWidgets::Tooltip("Freezes the time of day"); - UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); - UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); - UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", "gNoFishDespawn", true, false); - UIWidgets::Tooltip("Prevents fish from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", "gNoBugsDespawn", true, false); - UIWidgets::Tooltip("Prevents bugs from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); - UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); - UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); - UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); - UIWidgets::PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); - UIWidgets::Tooltip("This syncs the ingame time with the real world time"); - ImGui::Text("Deku Sticks:"); - UIWidgets::EnhancementCombobox("gDekuStickCheat", DekuStickCheat, DEKU_STICK_NORMAL); - UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", "gNoRedeadFreeze", true, false); - UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream"); - UIWidgets::Spacer(2.0f); + UIWidgets::Spacer(0); + if (ImGui::BeginMenu("Save States")) { ImGui::TextColored({ 0.85f, 0.85f, 0.0f, 1.0f }, " " ICON_FA_EXCLAMATION_TRIANGLE); ImGui::SameLine(); @@ -1363,19 +1383,47 @@ void DrawCheatsMenu() { UIWidgets::PaddedText("they WILL break across transitions and", true, false); UIWidgets::PaddedText("load zones (like doors). Support for", true, false); UIWidgets::PaddedText("related issues will not be provided.", true, false); - if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", "gSaveStatePromise", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", "gSaveStatePromise", true, + false)) { CVarSetInteger("gSaveStatesEnabled", 0); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (CVarGetInteger("gSaveStatePromise", 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", "gSaveStatesEnabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", "gSaveStatesEnabled", true, + false); UIWidgets::Tooltip("F5 to save, F6 to change slots, F7 to load"); } ImGui::EndMenu(); } - UIWidgets::Spacer(2.0f); + UIWidgets::Spacer(2.0f); + ImGui::Text("Behavior:"); + UIWidgets::PaddedSeparator(); + + UIWidgets::PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); + UIWidgets::Tooltip("Allows you to walk through walls"); + UIWidgets::PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); + UIWidgets::Tooltip("Makes every surface in the game climbable"); + UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); + UIWidgets::Tooltip("Holding L makes you float into the air"); + UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", "gCheatEasyPauseBufferEnabled", true, false); + UIWidgets::Tooltip("Continue holding START button when unpausing to only advance a single frame and then re-pause"); + const bool bEasyFrameAdvanceEnabled = CVarGetInteger("gCheatEasyPauseBufferEnabled", 0); + UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", "gCheatEasyInputBufferingEnabled", true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled"); + UIWidgets::Tooltip("Inputs that are held down while the Subscreen is closing will be pressed when the game is resumed"); + UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); + UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); + UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", "gNoFishDespawn", true, false); + UIWidgets::Tooltip("Prevents fish from automatically despawning after a while when dropped"); + UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", "gNoBugsDespawn", true, false); + UIWidgets::Tooltip("Prevents bugs from automatically despawning after a while when dropped"); + UIWidgets::PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); + UIWidgets::Tooltip("Freezes the time of day"); + UIWidgets::PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); + UIWidgets::Tooltip("This syncs the ingame time with the real world time"); + UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", "gNoRedeadFreeze", true, false); + UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream"); { static int32_t betaQuestEnabled = CVarGetInteger("gEnableBetaQuest", 0); static int32_t lastBetaQuestEnabled = betaQuestEnabled; @@ -1439,19 +1487,8 @@ void DrawCheatsMenu() { } } - UIWidgets::Spacer(2.0f); - if (ImGui::Button("Change Age")) { - CVarSetInteger("gSwitchAge", 1); - } - UIWidgets::Tooltip("Switches Link's age and reloads the area."); - - if (ImGui::Button("Clear Cutscene Pointer")) { - GameInteractor::RawAction::ClearCutscenePointer(); - } - UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); - + ImGui::EndTable(); ImGui::EndDisabled(); - ImGui::EndMenu(); } } diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index be8edf1c4..ca104f945 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -297,6 +297,7 @@ namespace UIWidgets { bool EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) { bool changed = false; int val = CVarGetInteger(cvarName, defaultValue); + const int oldVal = val; if (disabled) { DisableComponent(ImGui::GetStyle().Alpha * 0.5f); @@ -348,9 +349,11 @@ namespace UIWidgets { changed = true; } - if (changed) { + if (changed && (oldVal != val)) { CVarSetInteger(cvarName, val); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } else { + changed = false; } return changed; @@ -359,15 +362,46 @@ namespace UIWidgets { bool EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton, bool disabled, const char* disabledTooltipText) { bool changed = false; float val = CVarGetFloat(cvarName, defaultValue); - + const float oldVal = val; if (disabled) { DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } + // Calculate how much precision to save based on the given range of the slider, limited to 6 decimal places + // Precision is also used when adding/subtracting using the +/- buttons + const float sliderWidth = std::min((ImGui::GetContentRegionAvail().x - 2.0f * (PlusMinusButton ? sliderButtonWidth : 0.0f)), maxSliderWidth); + const float diff = (max - min) / sliderWidth; + int ticks = 0; + float increment = 1.0f; + if (diff < 1.0f) { + ticks++; + increment = 0.1f; + } + if (diff < 0.1f) { + ticks++; + increment = 0.01f; + } + if (diff < 0.01f) { + ticks++; + increment = 0.001f; + } + if (diff < 0.001f) { + ticks++; + increment = 0.0001f; + } + if (diff < 0.0001f) { + ticks++; + increment = 0.00001f; + } + if (diff < 0.00001f) { + ticks++; + increment = 0.000001f; + } + if (!isPercentage) { ImGui::Text(text, val); } else { - ImGui::Text(text, static_cast(100 * val)); + ImGui::Text(text, val * 100.0f); } Spacer(0); @@ -375,22 +409,15 @@ namespace UIWidgets { if (PlusMinusButton) { std::string MinusBTNName = " - ##" + std::string(cvarName); if (ImGui::Button(MinusBTNName.c_str())) { - if (isPercentage) { - val -= 0.01f; - } else { - val -= 0.1f; - } + val -= increment; changed = true; } ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); } - ImGui::PushItemWidth(std::min((ImGui::GetContentRegionAvail().x - (PlusMinusButton ? sliderButtonWidth : 0.0f)), maxSliderWidth)); + ImGui::PushItemWidth(sliderWidth); if (ImGui::SliderFloat(id, &val, min, max, format, ImGuiSliderFlags_AlwaysClamp)) { - if (isPercentage) { - val = roundf(val * 100) / 100; - } changed = true; } ImGui::PopItemWidth(); @@ -400,11 +427,7 @@ namespace UIWidgets { ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); if (ImGui::Button(PlusBTNName.c_str())) { - if (isPercentage) { - val += 0.01f; - } else { - val += 0.1f; - } + val += increment; changed = true; } } @@ -424,9 +447,14 @@ namespace UIWidgets { changed = true; } - if (changed) { + if (changed && !(abs(oldVal - val) < 0.000001f)) { + std::stringstream ss; + ss << std::setprecision(ticks) << val; + val = std::stof(ss.str()); CVarSetFloat(cvarName, val); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } else { + changed = false; } return changed; diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 031a46991..f1086a944 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -9,6 +9,7 @@ #define UIWidgets_hpp #include +#include #include #include #include From bfe2f58feb17d181ded857d67d9cf9296d43fcef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaro=20Mart=C3=ADnez?= Date: Mon, 15 Jan 2024 10:24:08 -0500 Subject: [PATCH 009/300] Custom message loading (#3713) * Add custom text message loading * Use "override" folder for text mods * Replace only existing messages * Use std::find_if to check for existing messages --- soh/soh/z_message_OTR.cpp | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 6bbd1eca9..10e6b0cfe 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -15,7 +15,34 @@ extern "C" MessageTableEntry* sFraMessageEntryTablePtr; extern "C" MessageTableEntry* sStaffMessageEntryTablePtr; //extern "C" MessageTableEntry* _message_0xFFFC_nes; -MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) { +static void SetMessageEntry(MessageTableEntry& entry, const LUS::MessageEntry& msgEntry) { + entry.textId = msgEntry.id; + entry.typePos = (msgEntry.textboxType << 4) | msgEntry.textboxYPos; + entry.segment = msgEntry.msg.c_str(); + entry.msgSize = msgEntry.msg.size(); +} + +static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEntry*& table, size_t tableSize) { + auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles(folderPath).get(); + + for (auto& tPath : lst) { + auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); + + for (size_t j = 0; j < file->messages.size(); ++j) { + // Check if same text ID exists already + auto existingEntry = std::find_if(table, table + tableSize, [id = file->messages[j].id](const auto& entry) { + return entry.textId == id; + }); + + if (existingEntry != table + tableSize) { + // Replace existing message + SetMessageEntry(*existingEntry, file->messages[j]); + } + } + } +} + +MessageTableEntry* OTRMessage_LoadTable(const std::string& filePath, bool isNES) { auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); if (file == nullptr) @@ -63,14 +90,12 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) { table[file->messages.size()].msgSize = kaeporaMsgSize; } - table[i].textId = file->messages[i].id; - table[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos; - table[i].segment = file->messages[i].msg.c_str(); - table[i].msgSize = file->messages[i].msg.size(); + SetMessageEntry(table[i], file->messages[i]); if (isNES && file->messages[i].id == 0xFFFC) _message_0xFFFC_nes = (char*)file->messages[i].msg.c_str(); } + OTRMessage_LoadCustom("override/" + filePath.substr(0, filePath.find_last_of('/')) + "/*", table, file->messages.size() + 1); // Assert that the first message starts at the first text ID assert(table[0].textId == 0x0001); @@ -101,12 +126,9 @@ extern "C" void OTRMessage_Init() sStaffMessageEntryTablePtr = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file2->messages.size()); for (size_t i = 0; i < file2->messages.size(); i++) { - sStaffMessageEntryTablePtr[i].textId = file2->messages[i].id; - sStaffMessageEntryTablePtr[i].typePos = - (file2->messages[i].textboxType << 4) | file2->messages[i].textboxYPos; - sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str(); - sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size(); + SetMessageEntry(sStaffMessageEntryTablePtr[i], file2->messages[i]); } + OTRMessage_LoadCustom("override/text/staff_message_data_static/*", sStaffMessageEntryTablePtr, file2->messages.size()); // Assert staff credits start at the first credits ID assert(sStaffMessageEntryTablePtr[0].textId == 0x0500); From 31623a93ab300db898c0a1af0c2d08c8994de8f8 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:24:57 -0500 Subject: [PATCH 010/300] Remove OpenMenu Bar Check (#3817) Having it set to just -6 makes the Glitch Tick stay in the same spot in game. when the F1 menu bar is open. At least on Windows --- soh/src/code/z_parameter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 46a87d649..f9a54eb2c 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3583,7 +3583,7 @@ void Interface_DrawLineupTick(PlayState* play) { s16 width = 32; s16 height = 32; s16 x = -8 + (SCREEN_WIDTH / 2); - s16 y = CVarGetInteger("gOpenMenuBar", 0) ? -4 : -6; + s16 y = -6; OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gEmptyCDownArrowTex, width, height, x, y, width, height, 2 << 10, 2 << 10); From 8426cc93e597a734160460544c6b1f8869d637ad Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 15 Jan 2024 10:25:57 -0500 Subject: [PATCH 011/300] Fix: Tektite texture not loading for death animation (#3808) * fix tektite death texture loading * add string header --- soh/src/overlays/actors/ovl_En_Part/z_en_part.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Part/z_en_part.c b/soh/src/overlays/actors/ovl_En_Part/z_en_part.c index e1b65efca..be1143ff1 100644 --- a/soh/src/overlays/actors/ovl_En_Part/z_en_part.c +++ b/soh/src/overlays/actors/ovl_En_Part/z_en_part.c @@ -8,6 +8,8 @@ #include "objects/object_tite/object_tite.h" #include "objects/object_ik/object_ik.h" +#include // strcmp + #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED void EnPart_Init(Actor* thisx, PlayState* play); @@ -297,11 +299,11 @@ void EnPart_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x08, func_80ACEAC0(play->state.gfxCtx, 255, 255, 255, 180, 180, 180)); gSPSegment(POLY_OPA_DISP++, 0x09, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); gSPSegment(POLY_OPA_DISP++, 0x0A, func_80ACEAC0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); - } else if ((thisx->params == 9) && (this->displayList == ResourceMgr_LoadGfxByName(object_tite_DL_002FF0))) { + } else if ((thisx->params == 9) && (strcmp((const char*)this->displayList, object_tite_DL_002FF0) == 0)) { gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001300); gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001700); gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_001900); - } else if ((thisx->params == 10) && (this->displayList == ResourceMgr_LoadGfxByName(object_tite_DL_002FF0))) { + } else if ((thisx->params == 10) && (strcmp((const char*)this->displayList, object_tite_DL_002FF0) == 0)) { gSPSegment(POLY_OPA_DISP++, 0x08, object_tite_Tex_001B00); gSPSegment(POLY_OPA_DISP++, 0x09, object_tite_Tex_001F00); gSPSegment(POLY_OPA_DISP++, 0x0A, object_tite_Tex_002100); From 861bd09848b7653e747105f26d532fb57c2ca9c2 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 15 Jan 2024 08:26:19 -0700 Subject: [PATCH 012/300] Adds a log statement to show the SoH version at startup, in case crashes don't produce a stack trace from which to glean that information. (#3786) --- soh/soh/OTRGlobals.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4c564afde..4f2e4ee7e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -297,6 +297,7 @@ OTRGlobals::OTRGlobals() { }; // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) context = LUS::Context::CreateInstance("Ship of Harkinian", appShortName, "shipofharkinian.json", OTRFiles, {}, 3); + SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared()); context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_PlayerAnimation, "PlayerAnimation", std::make_shared()); From ecdf74161b77a7d8966e04e27cc362e2b0ce8a02 Mon Sep 17 00:00:00 2001 From: "Tina H. (sheepytina)" <99330992+sheepytina@users.noreply.github.com> Date: Tue, 16 Jan 2024 02:28:59 +1100 Subject: [PATCH 013/300] Add a tooltip to "Restore old Gold Skulltula cutscene" enhancement. (#3849) --- soh/soh/SohMenuBar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 97bc012b6..04c053f5c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1163,6 +1163,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Quick Putaway", "gQuickPutaway", true, false); UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows putting away an item without an animation and performing Putaway Ocarina Items"); UIWidgets::PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); + UIWidgets::Tooltip("Restore pre-release behavior where defeating a Gold Skulltula will play a cutscene showing it die."); UIWidgets::PaddedEnhancementCheckbox("Quick Bongo Kill", "gQuickBongoKill", true, false); UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows bypassing Bongo Bongo's intro cutscene to quickly kill him"); UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", "gRestoreRBAValues", true, false); From db02870a05461a09159a6b9e302056211f1ac625 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:30:20 +0000 Subject: [PATCH 014/300] Restore Original Scene Command Object List Behaviour (MacReady) (#3827) * Restore Original Scene_CommandObjectList Behaviour * remove some vrom stuff * add some comments --- soh/soh/z_scene_otr.cpp | 50 ++++++++++++++++------------------------- soh/src/code/z_actor.c | 6 +++-- soh/src/code/z_scene.c | 7 ++++-- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index ef98a4b3a..54065e27e 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -149,6 +149,13 @@ bool Scene_CommandMeshHeader(PlayState* play, LUS::ISceneCommand* cmd) { extern "C" void* func_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId); +bool OTRfunc_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId) { + + objectCtx->status[bankIndex].id = -objectId; + + return false; +} + bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { // LUS::SetObjectList* cmdObj = static_pointer_cast(cmd); LUS::SetObjectList* cmdObj = (LUS::SetObjectList*)cmd; @@ -164,49 +171,30 @@ bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { void* nextPtr; k = 0; - // i = play->objectCtx.unk_09; - i = 0; + i = play->objectCtx.unk_09; firstStatus = &play->objectCtx.status[0]; status = &play->objectCtx.status[i]; - for (int i = 0; i < cmdObj->objects.size(); i++) { - bool alreadyIncluded = false; - - for (int j = 0; j < play->objectCtx.num; j++) { - if (play->objectCtx.status[j].id == cmdObj->objects[i]) { - alreadyIncluded = true; - break; + // Loop until a mismatch in the object lists + // Then clear all object ids past that in the context object list and kill actors for those objects + for (i = play->objectCtx.unk_09, k = 0; i < play->objectCtx.num; i++, k++) { + if (play->objectCtx.status[i].id != cmdObj->objects[k]) { + for (j = i; j < play->objectCtx.num; j++) { + play->objectCtx.status[j].id = OBJECT_INVALID; } - } - - if (!alreadyIncluded) { - play->objectCtx.status[play->objectCtx.num++].id = cmdObj->objects[i]; func_80031A28(play, &play->actorCtx); + break; } } - /* - while (i < play->objectCtx.num) { - if (status->id != *objectEntry) { - status2 = &play->objectCtx.status[i]; - for (j = i; j < play->objectCtx.num; j++) { - status2->id = OBJECT_INVALID; - status2++; - } - play->objectCtx.num = i; - func_80031A28(play, &play->actorCtx); - - continue; + // Continuing from the last index, add the remaining object ids from the command object list + for (; k < cmdObj->objects.size(); k++, i++) { + if (i < OBJECT_EXCHANGE_BANK_MAX - 1) { + OTRfunc_800982FC(&play->objectCtx, i, cmdObj->objects[k]); } - - i++; - k++; - objectEntry++; - status++; } play->objectCtx.num = i; - */ return false; } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 79a3c8ace..dfb3e4407 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1219,8 +1219,7 @@ void Actor_Init(Actor* actor, PlayState* play) { CollisionCheck_InitInfo(&actor->colChkInfo); actor->floorBgId = BGCHECK_SCENE; ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); - //if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) - { + if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { //Actor_SetObjectDependency(play, actor); actor->init(actor, play); actor->init = NULL; @@ -3129,6 +3128,9 @@ void Actor_FreeOverlay(ActorDBEntry* dbEntry) { osSyncPrintf(VT_RST); } +// SoH: Flag to check if actors are being spawned from the actor entry list +// This flag is checked against to allow actors which dont have an objectBankIndex in the objectCtx slot/status array to spawn +// An example of what this fixes, is that it allows hookshot to be used as child int gMapLoading = 0; Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, diff --git a/soh/src/code/z_scene.c b/soh/src/code/z_scene.c index 2a0a5d5d7..579e84eda 100644 --- a/soh/src/code/z_scene.c +++ b/soh/src/code/z_scene.c @@ -83,9 +83,10 @@ void Object_UpdateBank(ObjectContext* objectCtx) { RomFile* objectFile; size_t size; - /* + for (i = 0; i < objectCtx->num; i++) { if (status->id < 0) { + /* if (status->dmaRequest.vromAddr == 0) { osCreateMesgQueue(&status->loadQueue, &status->loadMsg, 1); objectFile = &gObjectTable[-status->id]; @@ -96,10 +97,12 @@ void Object_UpdateBank(ObjectContext* objectCtx) { } else if (!osRecvMesg(&status->loadQueue, NULL, OS_MESG_NOBLOCK)) { status->id = -status->id; } + */ + status->id = -status->id; } status++; } - */ + } s32 Object_GetIndex(ObjectContext* objectCtx, s16 objectId) { From db2ccd95b76031ef8842b515b805ad8232ddf1bd Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:33:21 +0100 Subject: [PATCH 015/300] Add Collision Header XML parser (#3396) * Add Collision Header XML parser * Update CollisionHeaderFactory.cpp * Remove "Num" attributes * Fix crashes Prevent crash when the camera setting is negative Change some IntAttributes to UnsignedAttributes --- .../importer/CollisionHeaderFactory.cpp | 136 ++++++++++++++++++ .../importer/CollisionHeaderFactory.h | 3 + soh/src/code/z_camera.c | 3 +- 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.cpp b/soh/soh/resource/importer/CollisionHeaderFactory.cpp index 3707229e3..9300efdf0 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/CollisionHeaderFactory.cpp @@ -24,6 +24,27 @@ CollisionHeaderFactory::ReadResource(std::shared_ptr initData, return resource; } +std::shared_ptr +CollisionHeaderFactory::ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) { + auto resource = std::make_shared(initData); + std::shared_ptr factory = nullptr; + + switch (resource->GetInitData()->ResourceVersion) { + case 0: + factory = std::make_shared(); + break; + } + + if (factory == nullptr) { + SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion); + return nullptr; + } + + factory->ParseFileXML(reader, resource); + + return resource; +} + void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) { @@ -139,4 +160,119 @@ void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptrcollisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data(); } + +void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) { + std::shared_ptr collisionHeader = std::static_pointer_cast(resource); + + collisionHeader->collisionHeaderData.minBounds.x = reader->IntAttribute("MinBoundsX"); + collisionHeader->collisionHeaderData.minBounds.y = reader->IntAttribute("MinBoundsY"); + collisionHeader->collisionHeaderData.minBounds.z = reader->IntAttribute("MinBoundsZ"); + + collisionHeader->collisionHeaderData.maxBounds.x = reader->IntAttribute("MaxBoundsX"); + collisionHeader->collisionHeaderData.maxBounds.y = reader->IntAttribute("MaxBoundsY"); + collisionHeader->collisionHeaderData.maxBounds.z = reader->IntAttribute("MaxBoundsZ"); + + Vec3s zero; + zero.x = 0; + zero.y = 0; + zero.z = 0; + collisionHeader->camPosDataZero = zero; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "Vertex") { + Vec3s vtx; + vtx.x = child->IntAttribute("X"); + vtx.y = child->IntAttribute("Y"); + vtx.z = child->IntAttribute("Z"); + collisionHeader->vertices.push_back(vtx); + } else if (childName == "Polygon") { + CollisionPoly polygon; + + polygon.type = child->UnsignedAttribute("Type"); + + polygon.flags_vIA = child->UnsignedAttribute("VertexA"); + polygon.flags_vIB = child->UnsignedAttribute("VertexB"); + polygon.vIC = child->UnsignedAttribute("VertexC"); + + polygon.normal.x = child->IntAttribute("NormalX"); + polygon.normal.y = child->IntAttribute("NormalY"); + polygon.normal.z = child->IntAttribute("NormalZ"); + + polygon.dist = child->IntAttribute("Dist"); + + collisionHeader->polygons.push_back(polygon); + } else if (childName == "PolygonType") { + SurfaceType surfaceType; + + surfaceType.data[0] = child->UnsignedAttribute("Data1"); + surfaceType.data[1] = child->UnsignedAttribute("Data2"); + + collisionHeader->surfaceTypes.push_back(surfaceType); + } else if (childName == "CameraData") { + CamData camDataEntry; + camDataEntry.cameraSType = child->UnsignedAttribute("SType"); + camDataEntry.numCameras = child->IntAttribute("NumData"); + collisionHeader->camData.push_back(camDataEntry); + + int32_t camPosDataIdx = child->IntAttribute("CameraPosDataSeg"); + collisionHeader->camPosDataIndices.push_back(camPosDataIdx); + } else if (childName == "CameraPositionData") { + //each camera position data is made up of 3 Vec3s + Vec3s pos; + pos.x = child->IntAttribute("PosX"); + pos.y = child->IntAttribute("PosY"); + pos.z = child->IntAttribute("PosZ"); + collisionHeader->camPosData.push_back(pos); + Vec3s rot; + rot.x = child->IntAttribute("RotX"); + rot.y = child->IntAttribute("RotY"); + rot.z = child->IntAttribute("RotZ"); + collisionHeader->camPosData.push_back(rot); + Vec3s other; + other.x = child->IntAttribute("FOV"); + other.y = child->IntAttribute("JfifID"); + other.z = child->IntAttribute("Unknown"); + collisionHeader->camPosData.push_back(other); + } else if (childName == "WaterBox") { + WaterBox waterBox; + waterBox.xMin = child->IntAttribute("XMin"); + waterBox.ySurface = child->IntAttribute("Ysurface"); + waterBox.zMin = child->IntAttribute("ZMin"); + waterBox.xLength = child->IntAttribute("XLength"); + waterBox.zLength = child->IntAttribute("ZLength"); + waterBox.properties = child->IntAttribute("Properties"); + + collisionHeader->waterBoxes.push_back(waterBox); + } + + child = child->NextSiblingElement(); + } + + for (size_t i = 0; i < collisionHeader->camData.size(); i++) { + int32_t idx = collisionHeader->camPosDataIndices[i]; + + if (collisionHeader->camPosData.size() > 0) { + collisionHeader->camData[i].camPosData = &collisionHeader->camPosData[idx]; + } else { + collisionHeader->camData[i].camPosData = &collisionHeader->camPosDataZero; + } + } + + collisionHeader->collisionHeaderData.numVertices = collisionHeader->vertices.size(); + collisionHeader->collisionHeaderData.numPolygons = collisionHeader->polygons.size(); + collisionHeader->surfaceTypesCount = collisionHeader->surfaceTypes.size(); + collisionHeader->camDataCount = collisionHeader->camData.size(); + collisionHeader->camPosCount = collisionHeader->camPosData.size(); + collisionHeader->collisionHeaderData.numWaterBoxes = collisionHeader->waterBoxes.size(); + + collisionHeader->collisionHeaderData.vtxList = collisionHeader->vertices.data(); + collisionHeader->collisionHeaderData.polyList = collisionHeader->polygons.data(); + collisionHeader->collisionHeaderData.surfaceTypeList = collisionHeader->surfaceTypes.data(); + collisionHeader->collisionHeaderData.cameraDataList = collisionHeader->camData.data(); + collisionHeader->collisionHeaderData.cameraDataListLen = collisionHeader->camDataCount; + collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data(); } +} \ No newline at end of file diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.h b/soh/soh/resource/importer/CollisionHeaderFactory.h index 09d6ba4c5..e0276b38f 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.h +++ b/soh/soh/resource/importer/CollisionHeaderFactory.h @@ -8,10 +8,13 @@ class CollisionHeaderFactory : public ResourceFactory { public: std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) override; }; class CollisionHeaderFactoryV0 : public ResourceVersionFactory { public: void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; + void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) override; }; }; // namespace LUS diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index ed8b9c8f4..2b5281037 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -7933,7 +7933,8 @@ s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags) { return -5; } - if (setting == CAM_SET_NONE || setting >= CAM_SET_MAX) { + //modified from "==" to "<=" to not crash when "setting" is a negative value + if (setting <= CAM_SET_NONE || setting >= CAM_SET_MAX) { osSyncPrintf(VT_COL(RED, WHITE) "camera: error: illegal camera set (%d) !!!!\n" VT_RST, setting); return -99; } From 1da1b1a2bb5b453a111ea42512d1c9869c0b0541 Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 15 Jan 2024 10:39:54 -0500 Subject: [PATCH 016/300] Tweak: Improve pause menu dungeon map performance (#3773) * add map palettes per pulse to leverage shader caching * use unregister blended with kaleido maps * use Gfx_TextureCacheDelete for KD lava * bump lus * add miss tex clears for KD --- libultraship | 2 +- soh/include/z64.h | 5 ++- soh/soh/OTRGlobals.cpp | 18 ++++++++++ soh/soh/OTRGlobals.h | 2 ++ soh/src/code/z_map_exp.c | 1 - .../actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 33 +++++++++---------- .../ovl_kaleido_scope/z_kaleido_map_PAL.c | 13 +++++--- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 32 +++++++++--------- 8 files changed, 66 insertions(+), 40 deletions(-) diff --git a/libultraship b/libultraship index b4abd7c36..96c8a8929 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b4abd7c366b1fb38b2cd80ffb91e129035bee0ea +Subproject commit 96c8a8929c18c1bffd7d92a35a589f74cf16fc59 diff --git a/soh/include/z64.h b/soh/include/z64.h index 23ffcfb17..f790dddc7 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -744,7 +744,6 @@ typedef struct { /* 0x0134 */ char** doActionSegment; /* 0x0138 */ u8* iconItemSegment; /* 0x013C */ char** mapSegment; - char** mapSegmentName; /* 0x0140 */ u8 mapPalette[32]; /* 0x0160 */ DmaRequest dmaRequest_160; /* 0x0180 */ DmaRequest dmaRequest_180; @@ -815,6 +814,10 @@ typedef struct { /* 0x026C */ u8 dinsNayrus; // "m_magic"; din's fire and nayru's love /* 0x026D */ u8 all; // "another"; enables all item restrictions } restrictions; + // #region SOH [General] + /* */ char* mapSegmentName[2]; // Tracks the map segment texture by OTR sig name + /* */ u8 mapPalettesPulse[40][32]; // Used to have unique pointers per map pulse color for the shader backend. 40 for map pulse timer x2 + // #endregion } InterfaceContext; // size = 0x270 typedef struct { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4f2e4ee7e..6543c5b8c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2598,6 +2598,24 @@ extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* repla gfx_register_blended_texture(name, mask, replacement); } +extern "C" void Gfx_UnregisterBlendedTexture(const char* name) { + gfx_unregister_blended_texture(name); +} + +extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) { + char* imgName = (char*)texAddr; + + if (texAddr == nullptr) { + return; + } + + if (ResourceMgr_OTRSigCheck(imgName)) { + texAddr = (const uint8_t*)GetResourceDataByNameHandlingMQ(imgName); + } + + gfx_texture_cache_delete(texAddr); +} + void SoH_ProcessDroppedFiles(std::string filePath) { try { std::ifstream configStream(filePath); diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 9b42e6895..a93df7efb 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -173,6 +173,8 @@ void Entrance_InitEntranceTrackingData(void); void EntranceTracker_SetCurrentGrottoID(s16 entranceIndex); void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex); void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement); +void Gfx_UnregisterBlendedTexture(const char* name); +void Gfx_TextureCacheDelete(const uint8_t* addr); void SaveManager_ThreadPoolWait(); void CheckTracker_OnMessageClose(); diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index c4db0098b..213ee018d 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -524,7 +524,6 @@ void Map_Init(PlayState* play) { interfaceCtx->unk_25A = -1; interfaceCtx->mapSegment = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*)); - interfaceCtx->mapSegmentName = GAMESTATE_ALLOC_MC(&play->state, 2 * sizeof(char*)); // "MAP texture initialization scene_data_ID=%d mapSegment=%x" osSyncPrintf("\n\n\nMAP テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum, interfaceCtx->mapSegment, play); diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index deb761641..1f2791540 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -10,10 +10,6 @@ #include // malloc #include // memcpy -// OTRTODO: Replace usage of this method when we can clear the cache -// for a single texture without the need of a DL opcode in the render code -void gfx_texture_cache_clear(); - #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define LAVA_TEX_WIDTH 32 @@ -123,7 +119,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() { sMaskTexLava[i] = maskVal; } } + Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL); + Gfx_TextureCacheDelete(sMaskTexLava); return; } @@ -165,7 +163,9 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() { } } - gfx_texture_cache_clear(); + Gfx_TextureCacheDelete(sMaskTexLava); + Gfx_TextureCacheDelete(sLavaWavyTex); + Gfx_TextureCacheDelete(sLavaFloorModifiedTex); } void func_808C12C4(u8* arg1, s16 arg2) { @@ -228,6 +228,7 @@ void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) { } free(sp54); + Gfx_TextureCacheDelete(sLavaWavyTexRaw); } // Modified to support CPU modified texture with the resource system @@ -255,6 +256,8 @@ void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) { temp_s3[i + temp2] = sp54[i + i2]; } } + + Gfx_TextureCacheDelete(sLavaWavyTex); } void func_808C17C8(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, s16 arg5) { @@ -373,6 +376,13 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) { Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016990, sMaskTex32x16, NULL); Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_016E10, sMaskTex32x16, NULL); + // Clear cache for masks + Gfx_TextureCacheDelete(sMaskTex8x16); + Gfx_TextureCacheDelete(sMaskTex8x32); + Gfx_TextureCacheDelete(sMaskTex16x16); + Gfx_TextureCacheDelete(sMaskTex16x32); + Gfx_TextureCacheDelete(sMaskTex32x16); + BossDodongo_RegisterBlendedLavaTextureUpdate(); // Register alt listener to update the blended lava for the replacement texture based on alt path @@ -1206,6 +1216,7 @@ void BossDodongo_Update(Actor* thisx, PlayState* play2) { } } else { sMaskTexLava[new_var] = 1; + Gfx_TextureCacheDelete(sMaskTexLava); } this->unk_1C2 += 37; @@ -1345,18 +1356,6 @@ void BossDodongo_Draw(Actor* thisx, PlayState* play) { gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16); } - gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava); - - // Using WORK_DISP to invalidate these textures as they are used in drawing the scene textures which happens - // before actors are drawn. WORK_DISP comes before POLAY_OPA_DISP. It is probably not meant for this, but it - // at least works for now. - // Alternatively, having a way to invalidate just these pointers from the Update func should be sufficient. - if (sLavaFloorModifiedTexRaw != NULL) { - gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTexRaw); - } else { - gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTex); - } - if ((this->unk_1C0 >= 2) && (this->unk_1C0 & 1)) { POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 255, 255, 0, 900, 1099); } else { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index 28723d3d0..34dc47aa9 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -312,6 +312,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { KaleidoScope_DrawQuadTextureRGBA32(gfxCtx, gQuestIconGoldSkulltulaTex, 24, 24, 8); } + // Unique index for both pulse phases + uint8_t palettePulseIdx = (mapBgPulseStage ? 40 : 20) - mapBgPulseTimer; + if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) { stepR = (mapBgPulseR - mapBgPulseColors[mapBgPulseStage][0]) / mapBgPulseTimer; stepG = (mapBgPulseG - mapBgPulseColors[mapBgPulseStage][1]) / mapBgPulseTimer; @@ -324,6 +327,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { interfaceCtx->mapPalette[28] = (rgba16 & 0xFF00) >> 8; interfaceCtx->mapPalette[29] = rgba16 & 0xFF; + interfaceCtx->mapPalettesPulse[palettePulseIdx][28] = (rgba16 & 0xFF00) >> 8; + interfaceCtx->mapPalettesPulse[palettePulseIdx][29] = rgba16 & 0xFF; + mapBgPulseTimer--; if (mapBgPulseTimer == 0) { mapBgPulseStage ^= 1; @@ -335,7 +341,8 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { gDPSetTextureFilter(POLY_KAL_DISP++, G_TF_POINT); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalette); + // Use a unique palette address per frame so the renderer/shader can cache all variations + gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalettesPulse[palettePulseIdx]); gDPSetTextureLUT(POLY_KAL_DISP++, G_TT_RGBA16); u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0); @@ -349,10 +356,6 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->mapPageVtx[60], 8, 0); - // The dungeon map textures are recreated each frame, so always invalidate them - gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[0]); - gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[1]); - gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH, MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 877ea7e6f..1475472a9 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1205,8 +1205,6 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, void** textures) { return gfx; } -static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT]; - void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { static Color_RGB8 D_8082ACF4[12] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 }, @@ -1375,10 +1373,6 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { } } - // Need to invalidate the blend mask every frame. Ideally this would be done in KaleidoScope_DrawDungeonMap - // but the reference is not shared between files - gSPInvalidateTexCache(POLY_KAL_DISP++, mapBlendMask); - if (pauseCtx->pageIndex) { // pageIndex != PAUSE_ITEM gDPPipeSync(OVERLAY_DISP++); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA); @@ -3326,6 +3320,7 @@ static uint8_t mapLeftTexModified[MAP_48x85_TEX_SIZE]; static uint8_t mapRightTexModified[MAP_48x85_TEX_SIZE]; static uint8_t* mapLeftTexModifiedRaw = NULL; static uint8_t* mapRightTexModifiedRaw = NULL; +static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT]; // Load dungeon maps into the interface context // SoH [General] - Modified to account for our resource system and HD textures @@ -3357,19 +3352,16 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) { size_t size = (width * height) / 2; // account for CI4 size // Resource size being larger than the calculated CI size means it is most likely not a CI4 texture - // Abort early end undo the blended effect by clearing the mask to avoid crashing + // Abort early and unregister the blended effect to avoid crashing if (size < ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0])) { - if (mapBlendMask[0] != 0) { - for (size_t i = 0; i < ARRAY_COUNT(mapBlendMask); i++) { - mapBlendMask[i] = 0; - } - } - interfaceCtx->mapSegment[0] = NULL; interfaceCtx->mapSegment[1] = NULL; - Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, NULL); - Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, NULL); + Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[0]); + Gfx_UnregisterBlendedTexture(interfaceCtx->mapSegmentName[1]); + + Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]); + Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]); return; } @@ -3404,6 +3396,11 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) { Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, interfaceCtx->mapSegment[0]); Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, interfaceCtx->mapSegment[1]); + + Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[0]); + Gfx_TextureCacheDelete(interfaceCtx->mapSegmentName[1]); + Gfx_TextureCacheDelete(interfaceCtx->mapSegment[0]); + Gfx_TextureCacheDelete(interfaceCtx->mapSegment[1]); } static uint8_t registeredDungeonMapTextureHook = false; @@ -3444,6 +3441,11 @@ void KaleidoScope_UpdateDungeonMap(PlayState* play) { KaleidoScope_LoadDungeonMap(play); Map_SetFloorPalettesData(play, pauseCtx->dungeonMapSlot - 3); + // Copy the map palette values to all pulse palettes + for (uint8_t i = 0; i < ARRAY_COUNT(interfaceCtx->mapPalettesPulse); i++) { + memcpy(interfaceCtx->mapPalettesPulse[i], interfaceCtx->mapPalette, sizeof(interfaceCtx->mapPalette)); + } + s32 size = MAP_48x85_TEX_SIZE; if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) { From dd5d8088f6b7fcf545459454ae29bd51119c7343 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:31:06 +0000 Subject: [PATCH 017/300] Revert actor uncullZone related checks back to match decomp (#3828) --- soh/src/code/z_actor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index dfb3e4407..df9b6c758 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -2860,9 +2860,9 @@ s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) { var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3; - if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 2.0f) && - (((arg2->y + actor->uncullZoneDownward) * var) > -2.0f) && - (((arg2->y - actor->uncullZoneScale) * var) < 2.0f)) { + if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) && + (((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) && + (((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) { return true; } } From 63cf3610e5f2483b9da25be3858ac05f671174dc Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 15 Jan 2024 11:31:33 -0500 Subject: [PATCH 018/300] Fix: Move Ruto earring fix to graphic patch and fix Ganon fight rubble DL reference (#3810) * move ruto earing fix to real patch * use stringpath for ganon rubble --- .../cosmetics/authenticGfxPatches.cpp | 16 ++++++++++++++++ soh/src/overlays/actors/ovl_Demo_Gj/z_demo_gj.c | 6 +++--- soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c | 13 ------------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp index de97f3840..709854c35 100644 --- a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp +++ b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp @@ -8,6 +8,7 @@ extern "C" { #include "objects/object_gi_soldout/object_gi_soldout.h" #include "objects/object_ik/object_ik.h" #include "objects/object_link_child/object_link_child.h" +#include "objects/object_ru2/object_ru2.h" uint32_t ResourceMgr_GameHasMasterQuest(); uint32_t ResourceMgr_GameHasOriginal(); @@ -187,10 +188,25 @@ void PatchIronKnuckleTextureOverflow() { } } +void PatchPrincessRutoEaring() { + // FAST3D: This is a hack for the issue of both TEXEL0 and TEXEL1 using the same texture with different settings. + // Ruto's earring uses both TEXEL0 and TEXEL1 to render. The issue is that it never loads anything into TEXEL1, so + // it reuses whatever happens to be there, which is the water temple brick texture. It just so happens that the + // earring texture loads into the same place in TMEM as the brick texture, so when it comes to rendering, TEXEL1 + // uses the earring texture with different clamp settings, and it displays without noticeable error. However, both + // texel samplers are not intended to be used for the same texture with different settings, so this misuse confuses + // our texture cache, and we load the wrong settings for the earrings texture. This patch is a hack that replaces + // TEXEL1 with TEXEL0, which is most likely the original intention, and all is well. + ResourceMgr_PatchGfxByName(gAdultRutoHeadDL, "RutoEaringTileFix", 162, + gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED, + TEXEL0, 0, PRIM_LOD_FRAC, COMBINED)); +} + void ApplyAuthenticGfxPatches() { PatchDekuStickTextureOverflow(); PatchFreezardTextureOverflow(); PatchIronKnuckleTextureOverflow(); + PatchPrincessRutoEaring(); } // Patches the Sold Out GI DL to render the texture in the mirror boundary diff --git a/soh/src/overlays/actors/ovl_Demo_Gj/z_demo_gj.c b/soh/src/overlays/actors/ovl_Demo_Gj/z_demo_gj.c index 5f3737b44..357b2c0ca 100644 --- a/soh/src/overlays/actors/ovl_Demo_Gj/z_demo_gj.c +++ b/soh/src/overlays/actors/ovl_Demo_Gj/z_demo_gj.c @@ -192,11 +192,11 @@ void DemoGj_Explode(DemoGj* this, PlayState* play, Vec3f* initialPos, Vec3f* dir phi_s0 = 0x21; } - Gfx* gfx = ResourceMgr_LoadGfxByName(gGanonRubbleDL); - + // SoH [Port] Changed from &gGanonsCastleRubbleAroundArenaDL[28] to gGanonRubbleDL as it seems this was an error in the original rom/decomp + // Other calls to EffectSsKakera_Spawn with OBJECT_GEFF use gGanonRubbleDL, so this change is to match that EffectSsKakera_Spawn(play, &explosionPos, &velocity, initialPos, -200, phi_s0, 10, 10, 0, Rand_ZeroOne() * 20.0f + 20.0f, 20, 300, (s32)(Rand_ZeroOne() * 30.0f) + 30, -1, - OBJECT_GEFF, gfx); + OBJECT_GEFF, gGanonRubbleDL); theta += 0x2AAA; } diff --git a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c index 6be42b42d..fe4a77724 100644 --- a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c +++ b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c @@ -821,19 +821,6 @@ void func_80AF3F20(EnRu2* this, PlayState* play) { void EnRu2_Draw(Actor* thisx, PlayState* play) { EnRu2* this = (EnRu2*)thisx; - // FAST3D: This is a hack for the issue of both TEXEL0 and TEXEL1 using the same texture with different settings. - // Ruto's earring uses both TEXEL0 and TEXEL1 to render. The issue is that it never loads anything into TEXEL1, so - // it reuses whatever happens to be there, which is the water temple brick texture. It just so happens that the - // earring texture loads into the same place in tmem as the brick texture, so when it comes to rendering, TEXEL1 - // uses the earring texture with diffrent clamp settings, and it displays without noticeable error. However, both - // texel samplers are not intended to be used for the same texture with different settings, so this misuse confuses - // our texture cache, and we load the wrong settings for the earrings texture. This patch is a hack that replaces - // TEXEL1 with TEXEL0, which is most likely the original intention, and all is well. - Gfx* gfx = ResourceMgr_LoadGfxByName(gAdultRutoHeadDL); - Gfx patch = gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED, TEXEL0, 0, - PRIM_LOD_FRAC, COMBINED); - gfx[0xA2] = patch; - if ((this->drawConfig < 0) || (this->drawConfig >= ARRAY_COUNT(sDrawFuncs)) || (sDrawFuncs[this->drawConfig] == 0)) { // "Draw Mode is improper!" From 3e91d5565a55fdff7453adbd8e4ba345bbdca7ee Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Mon, 15 Jan 2024 16:46:36 -0800 Subject: [PATCH 019/300] Fix disabled icon for Easy Input Buffering checkbox when Easy Frame Advancing is enabled (#3859) --- soh/soh/SohMenuBar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 04c053f5c..e656a3a90 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1411,7 +1411,7 @@ void DrawCheatsMenu() { UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", "gCheatEasyPauseBufferEnabled", true, false); UIWidgets::Tooltip("Continue holding START button when unpausing to only advance a single frame and then re-pause"); const bool bEasyFrameAdvanceEnabled = CVarGetInteger("gCheatEasyPauseBufferEnabled", 0); - UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", "gCheatEasyInputBufferingEnabled", true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled"); + UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", "gCheatEasyInputBufferingEnabled", true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Inputs that are held down while the Subscreen is closing will be pressed when the game is resumed"); UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); From cb82e77e407ca80dc23c61cfce78fa8ea174a221 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 2 Feb 2024 01:15:13 +0000 Subject: [PATCH 020/300] fix bombchu logic bugs (#3720) --- soh/soh/Enhancements/randomizer/3drando/logic.cpp | 2 +- soh/soh/OTRGlobals.cpp | 3 +-- soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp index 580c687d0..df127e699 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp @@ -536,7 +536,7 @@ namespace Logic { Fish = HasBottle && FishAccess; Fairy = HasBottle && FairyAccess; - FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20); + FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20) && (BombBag || BombchusInLogic); CanPlayBowling = (BombchusInLogic && FoundBombchus) || (!BombchusInLogic && BombBag); HasBombchus = (BuyBombchus10 || BuyBombchus20 || (AmmoDrops.Is(AMMODROPS_BOMBCHU) && FoundBombchus)); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6543c5b8c..391db3b8c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2487,8 +2487,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { randoInf = RAND_INF_MERCHANTS_CARPET_SALESMAN; } messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT); - } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && - (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { + } else if (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); } else if (textId == TEXT_CURSED_SKULLTULA_PEOPLE) { actorParams = GET_PLAYER(play)->targetActor->params; diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 037b4b594..6aa1b7d41 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -1027,8 +1027,8 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) { Rupees_ChangeBy(-this->basePrice); // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out - // If they're in logic for rando, skip setting that flag so they can be purchased repeatedly - if (IS_RANDO && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { + // If we're in rando, skip setting that flag so they can be purchased repeatedly + if (IS_RANDO) { return; } @@ -1255,8 +1255,7 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) { this->itemGiveFunc = itemEntry->itemGiveFunc; this->buyEventFunc = itemEntry->buyEventFunc; // If chus are in logic, make the 10 pack affordable without a wallet upgrade - if (IS_RANDO && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && - this->getItemId == GI_BOMBCHUS_10) { + if (IS_RANDO && this->getItemId == GI_BOMBCHUS_10) { this->basePrice = 99; } else { this->basePrice = itemEntry->price; From e3825ec2630c50335d809102e5a9febc53972031 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 1 Feb 2024 18:23:06 -0700 Subject: [PATCH 021/300] Unify defaults for reward count sliders with Greg As Reward so they need to register changes. (#3875) --- soh/soh/Enhancements/randomizer/randomizer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 4b9a84eff..ab3554174 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4207,7 +4207,7 @@ void RandomizerSettingsWindow::DrawElement() { break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - "gRandomizeLacsStoneCount", 1, 4, "", 4, true, true, false); + "gRandomizeLacsStoneCount", 1, 4, "", 3, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", @@ -4236,7 +4236,7 @@ void RandomizerSettingsWindow::DrawElement() { break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - "gRandomizeLacsMedallionCount", 1, 7, "", 7, true, true, false); + "gRandomizeLacsMedallionCount", 1, 7, "", 6, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", @@ -4265,7 +4265,7 @@ void RandomizerSettingsWindow::DrawElement() { break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - "gRandomizeLacsRewardCount", 1, 10, "", 10, true, true, false); + "gRandomizeLacsRewardCount", 1, 10, "", 9, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", @@ -4294,7 +4294,7 @@ void RandomizerSettingsWindow::DrawElement() { break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - "gRandomizeLacsDungeonCount", 1, 9, "", 9, true, true, false); + "gRandomizeLacsDungeonCount", 1, 9, "", 8, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", From 7ef6a434f92c6529952aef3e0848daf246f149bf Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 1 Feb 2024 20:25:57 -0500 Subject: [PATCH 022/300] fix timestamp truncation (#3874) --- soh/soh/OTRGlobals.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 391db3b8c..64d70da88 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1144,8 +1144,7 @@ extern "C" uint64_t GetUnixTimestamp() { auto time = std::chrono::system_clock::now(); auto since_epoch = time.time_since_epoch(); auto millis = std::chrono::duration_cast(since_epoch); - long now = millis.count(); - return now; + return (uint64_t)millis.count(); } // C->C++ Bridge From 16ee20c2a8c7ec6bcb7076d4a962a206387acc90 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 1 Feb 2024 18:26:36 -0700 Subject: [PATCH 023/300] Renames Freecam to Free Look. (#3771) Adds helper info for invert, distance, and transition speed options. --- .../controls/GameControlEditor.cpp | 24 +++++++++++-------- soh/src/code/z_camera.c | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index eb69f3cc8..976912b63 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -258,24 +258,28 @@ namespace GameControlEditor { window->EndGroupPanelPublic(0); UIWidgets::Spacer(0); - window->BeginGroupPanelPublic("Third-Person Camera", ImGui::GetContentRegionAvail()); + window->BeginGroupPanelPublic("Free Look/Third-person Camera", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera"); - DrawHelpIcon("Enables free camera control\nNote: You must remap C buttons off of the right stick in the " + UIWidgets::PaddedEnhancementCheckbox("Enable Free Look", "gFreeCamera"); + DrawHelpIcon("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " "controller config menu, and map the camera stick to the right stick."); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); - DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera"); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera"); + UIWidgets::PaddedEnhancementCheckbox("Invert X Axis", "gInvertXAxis"); + DrawHelpIcon("Inverts the Camera X Axis in:\n-Free Look"); + UIWidgets::PaddedEnhancementCheckbox("Invert Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free Look"); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %d %%", "##ThirdPersonSensitivity Horizontal", + UIWidgets::PaddedEnhancementSliderFloat("Horizontal Sensitivity: %d %%", "##ThirdPersonSensitivity Horizontal", "gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %d %%", "##ThirdPersonSensitivity Vertical", + DrawHelpIcon("Changes the sensitivity of the X axis control for Free Look"); + UIWidgets::PaddedEnhancementSliderFloat("Vertical Sensitivity: %d %%", "##ThirdPersonSensitivity Vertical", "gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true); + DrawHelpIcon("Changes the sensitivity of the Y axis control for Free Look"); UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist", "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed", + DrawHelpIcon("How far the camera sits from Link while in Free Look mode"); + UIWidgets::PaddedEnhancementSliderInt("Transition Speed: %d", "##CamTranSpeed", "gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true); + DrawHelpIcon("How quickly the camera changes to the distance specified above"); window->EndGroupPanelPublic(0); } diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index a177e29e7..4353d397e 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -7887,7 +7887,7 @@ s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags) { } } - // Clear free camera if an action is performed that would move the camera (targeting, first person, talking) + // Clear free look if an action is performed that would move the camera (targeting, first person, talking) if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1 && ((mode >= CAM_MODE_TARGET && mode <= CAM_MODE_BATTLE) || (mode >= CAM_MODE_FIRSTPERSON && mode <= CAM_MODE_CLIMBZ) || mode == CAM_MODE_HANGZ || From 61cf2bd323e8e31d416d9d2e325b02fb2c6a2260 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 1 Feb 2024 18:29:24 -0700 Subject: [PATCH 024/300] No Magic Numbers for Preset Location Exclusions (#3801) * Adds `FormatLocations` and `PRESET_ENTRY_TYPE_CPP_STRING` to allow for feeding `RandomizerCheck` values directly in presets instead of a string with magic numbers. * Switch to concatenation with `std::to_string`. * Forgot to remove include XD --- soh/soh/Enhancements/presets.cpp | 11 +++++++++++ soh/soh/Enhancements/presets.h | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/presets.cpp b/soh/soh/Enhancements/presets.cpp index 7b2ca6595..726863e05 100644 --- a/soh/soh/Enhancements/presets.cpp +++ b/soh/soh/Enhancements/presets.cpp @@ -12,6 +12,14 @@ void clearCvars(std::vector cvarsToClear) { } } +std::string FormatLocations(std::vector locs) { + std::string locString = ""; + for (auto loc: locs) { + locString += std::to_string(loc) + ","; + } + return locString; +} + void applyPreset(std::vector entries) { for(auto& [cvar, type, value] : entries) { switch (type) { @@ -24,6 +32,9 @@ void applyPreset(std::vector entries) { case PRESET_ENTRY_TYPE_STRING: CVarSetString(cvar, std::get(value)); break; + case PRESET_ENTRY_TYPE_CPP_STRING: + CVarSetString(cvar, std::get(value).c_str()); + break; } } } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 22c9dd7db..cac60cdef 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -11,6 +12,7 @@ enum PresetEntryType { PRESET_ENTRY_TYPE_S32, PRESET_ENTRY_TYPE_FLOAT, PRESET_ENTRY_TYPE_STRING, + PRESET_ENTRY_TYPE_CPP_STRING, }; enum PresetType { @@ -36,15 +38,19 @@ enum RandomizerPreset { typedef struct PresetEntry { const char* cvar; PresetEntryType type; - std::variant value; + std::variant value; } PresetEntry; +std::string FormatLocations(std::vector locs); + #define PRESET_ENTRY_S32(cvar, value) \ { cvar, PRESET_ENTRY_TYPE_S32, value } #define PRESET_ENTRY_FLOAT(cvar, value) \ { cvar, PRESET_ENTRY_TYPE_FLOAT, value } #define PRESET_ENTRY_STRING(cvar, value) \ { cvar, PRESET_ENTRY_TYPE_STRING, value } +#define PRESET_ENTRY_CPP_STRING(cvar, value) \ + { cvar, PRESET_ENTRY_TYPE_CPP_STRING, value } void DrawPresetSelector(PresetType presetType); void clearCvars(std::vector cvarsToClear); @@ -866,7 +872,8 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32("gRandomizeDampeHint", 1), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), - PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "78,143,144,229,"), + PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations( + { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), PRESET_ENTRY_S32("gRandomizeFullWallets", 1), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), @@ -958,7 +965,8 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gRandomizeDampeHint", 1), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), - PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "78,143,144,229,"), + PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations( + { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), PRESET_ENTRY_S32("gRandomizeFullWallets", 1), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), @@ -1011,7 +1019,7 @@ const std::vector s6PresetEntries = { PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1), PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4), PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), - PRESET_ENTRY_STRING("gRandomizeExcludedLocations", "48,"), + PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })), PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_CLOSED_DEKU), PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST), From d9310e45430d638180a123a4d74cca2623ba7765 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:32:50 -0500 Subject: [PATCH 025/300] Swim Speed Modifiers (#3308) * Add CVars for swimming, apply to swim speed calc * Prevent modifer from working underwater * Re-enable swim speed mod when underwater, use new (orig) function for y-velocity while diving * Add to presets list * Fix spacing * block out vanilla + comments * re-org vanilla code block in a sane way * new documentation format * rename Surface function + comment for usage * handle merge conflicts, but like an adult this time --- .../controls/GameControlEditor.cpp | 16 +++-- soh/soh/Enhancements/presets.h | 2 + .../actors/ovl_player_actor/z_player.c | 72 ++++++++++++++++++- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index 46366135f..eaf18052c 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -315,15 +315,21 @@ namespace GameControlEditor { "certain items."); UIWidgets::Spacer(0); ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); - UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false); - DrawHelpIcon("Hold the assigned button to change the maximum walking speed\nTo change the assigned button, go into the Ports tabs above"); + UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); + DrawHelpIcon("Hold the assigned button to change the maximum walking or swimming speed\nTo change the assigned button, go into the Ports tabs above"); if (CVarGetInteger("gEnableWalkModify", 0)) { UIWidgets::Spacer(5); - window->BeginGroupPanelPublic("Walk Modifier", ImGui::GetContentRegionAvail()); + window->BeginGroupPanelPublic("Speed Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); + window->BeginGroupPanelPublic("Walk Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); - UIWidgets::PaddedEnhancementSliderFloat("Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + window->EndGroupPanelPublic(0); + window->BeginGroupPanelPublic("Swim Modifier", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + window->EndGroupPanelPublic(0); window->EndGroupPanelPublic(0); } ImGui::EndDisabled(); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index d7efeb4f3..020779216 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -256,6 +256,8 @@ const std::vector cheatCvars = { "gWalkSpeedToggle", "gWalkModifierOne", "gWalkModifierTwo", + "gSwimModifierOne", + "gSwimModifierTwo", "gGoronPot", "gDampeWin", "gCustomizeShootingGallery", diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 523e7cf11..80f4828ed 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11926,6 +11926,68 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { f32 temp1; f32 temp2; + + // #region SOH [Enhancement] + f32 swimMod = 1.0f; + + if (CVarGetInteger("gEnableWalkModify", 0) == 1) { + if (CVarGetInteger("gWalkSpeedToggle", 0) == 1) { + if (gWalkSpeedToggle1) { + swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f); + } else if (gWalkSpeedToggle2) { + swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f); + } + } else { + if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { + swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f); + } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { + swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f); + } + } + temp1 = this->skelAnime.curFrame - 10.0f; + + temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f * swimMod; + if (*arg1 > temp2) { + *arg1 = temp2; + } + + if ((0.0f < temp1) && (temp1 < 10.0f)) { + temp1 *= 6.0f; + } else { + temp1 = 0.0f; + arg2 = 0.0f; + } + + Math_AsymStepToF(arg1, arg2 * 0.8f * swimMod, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); + Math_ScaledStepToS(&this->currentYaw, arg3, 1600); + // #endregion + } else { + + temp1 = this->skelAnime.curFrame - 10.0f; + + temp2 = (R_RUN_SPEED_LIMIT / 100.0f) * 0.8f; + if (*arg1 > temp2) { + *arg1 = temp2; + } + + if ((0.0f < temp1) && (temp1 < 10.0f)) { + temp1 *= 6.0f; + } else { + temp1 = 0.0f; + arg2 = 0.0f; + } + + Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); + Math_ScaledStepToS(&this->currentYaw, arg3, 1600); + } +} + +// #region SOH [Enhancement] +//Diving uses function func_8084AEEC to calculate changes both xz and y velocity (via func_8084DBC4) +//Provide original calculation for y velocity when swim speed mod is active +void SurfaceWithoutSwimMod(Player* this, f32* arg1, f32 arg2, s16 arg3) { + f32 temp1; + f32 temp2; temp1 = this->skelAnime.curFrame - 10.0f; @@ -11944,6 +12006,7 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); Math_ScaledStepToS(&this->currentYaw, arg3, 1600); } +// #endregion void func_8084B000(Player* this) { f32 phi_f18; @@ -13098,7 +13161,14 @@ void func_8084DBC4(PlayState* play, Player* this, f32 arg2) { Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A); - func_8084AEEC(this, &this->actor.velocity.y, arg2, this->currentYaw); + // Original implementation of func_8084AEEC (SurfaceWithoutSwimMod) to prevent velocity increases via swim mod which push Link into the air + // #region SOH [Enhancement] + if (CVarGetInteger("gEnableWalkModify", 0)) { + SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->currentYaw); + // #endregion + } else { + func_8084AEEC(this, &this->actor.velocity.y, arg2, this->currentYaw); + } } void func_8084DC48(Player* this, PlayState* play) { From 4d5adbc80f4799bd7ce13581da3989374f539d09 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:36:57 -0500 Subject: [PATCH 026/300] Fisherman asks for fishing rod when leaving (#3347) * CVar, presets, custom message, fishing actor * Add placeholder translations for French/German * Fix for MS Shuffle change * Rename function to match * Missing comma in presets * Change description, CVar name, add'l function name, edit custom message * Actual whitespace fix * re-order custom message * Fix message formatting * Add enhancement comments * yeet if (play) {} from enhancement * new documentation format --- .../custom-message/CustomMessageTypes.h | 1 + soh/soh/Enhancements/presets.h | 1 + soh/soh/OTRGlobals.cpp | 3 ++ soh/soh/SohMenuBar.cpp | 2 + soh/soh/z_message_OTR.cpp | 5 +++ .../overlays/actors/ovl_Fishing/z_fishing.c | 37 +++++++++++++++++++ 6 files changed, 49 insertions(+) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index d93bae983..47729c129 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -38,6 +38,7 @@ typedef enum { TEXT_CARPET_SALESMAN_1 = 0x6077, TEXT_CARPET_SALESMAN_2 = 0x6078, TEXT_MARKET_GUARD_NIGHT = 0x7003, + TEXT_FISHERMAN_LEAVE = 0x409E, TEXT_SHEIK_NEED_HOOK = 0x700F, TEXT_SHEIK_HAVE_HOOK = 0x7010, TEXT_SCRUB_RANDOM = 0x9000, diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 020779216..bc87c47e2 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -136,6 +136,7 @@ const std::vector enhancementsCvars = { "gInjectItemCounts", "gDayGravePull", "gDampeAllNight", + "gQuitFishingAtDoor", "gSkipSwimDeepEndAnim", "gSkipScarecrow", "gBlueFireArrows", diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1045c98f8..178a8f329 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2631,6 +2631,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT); } + if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger("gQuitFishingAtDoor", 0)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE); + } font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); switch (gSaveContext.language) { case LANGUAGE_FRA: diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index e656a3a90..3c77438e8 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -610,6 +610,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate."); UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); + UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", "gQuitFishingAtDoor", true, false); + UIWidgets::Tooltip("Fisherman asks if you want to quit at the door when you still have the rod"); UIWidgets::PaddedText("Time Travel with the Song of Time", true, false); UIWidgets::EnhancementCombobox("gTimeTravel", timeTravelOptions, 0); UIWidgets::Tooltip("Allows Link to freely change age by playing the Song of Time.\n" diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 10e6b0cfe..a4255d08a 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -182,4 +182,9 @@ extern "C" void OTRMessage_Init() CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", "Du siehst gelangweilt aus.&Willst du einen Spaziergang machen?\x1B&%gJa&Nein%w", "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w")); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_FISHERMAN_LEAVE, + CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest du aufhören?&\x1B&%gJa&Nein%w", //TODO Used AI translation as placeholder + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder } diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 3f8de83ba..727a20730 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -5174,6 +5174,37 @@ static Vec3s sSinkingLureLocationPos[] = { { 553, -48, -508 }, }; +// #region SOH [Enhancement] +void Fishing_QuitAtDoor(Fishing* this, PlayState* play) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { + Message_CloseTextbox(play); + + switch (play->msgCtx.choiceIndex) { + case 0: + if (D_80B7E084 == 0) { + Message_ContinueTextbox(play, 0x4085); + } else if (sLinkAge == 1) { + Message_ContinueTextbox(play, 0x4092); + } + + if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE_FADING) { + + if (D_80B7A68C != 0) { + D_80B7A688 = 1; + D_80B7A68C = 0; + } + D_80B7E0AC = 0; + play->interfaceCtx.unk_260 = 0; + } + break; + case 1: + func_800A9F6C(0.0f, 150, 10, 10); + break; + } + } +} +// #endregion + void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { PlayState* play = play2; Fishing* this = (Fishing*)thisx; @@ -5480,6 +5511,12 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { case 11: player->actor.world.pos.z = 1360.0f; player->actor.speedXZ = 0.0f; + + // #region SOH [Enhancement] + if (CVarGetInteger("gQuitFishingAtDoor", 0)) { + Fishing_QuitAtDoor(this, play); + } + // #endregion if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) { Camera* camera = Play_GetCamera(play, MAIN_CAM); From 7ff46ba1a7a720bd71e531943596ab11badecc40 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:38:54 -0500 Subject: [PATCH 027/300] Increase Crawl Speed (#3366) * Increase animation speeds, crawl speed, add magic numbers for camera timer, add to menu and presets * Remove extra space, reformat comments * Initialilze CVar at 0, Initialize default timer, set default case for timer, change all CVarGets to 1, reorg logic * Fix remaining CVars + unify logic * block out vanilla code + comments * new documentation formatting * Simplify camera swing fix * Remove redundant multiplication * Update soh/src/code/z_onepointdemo.c reduce code duplication Co-authored-by: Garrett Cox --------- Co-authored-by: Garrett Cox --- soh/soh/Enhancements/presets.h | 1 + soh/soh/SohMenuBar.cpp | 1 + soh/src/code/z_onepointdemo.c | 31 +++++++-- .../actors/ovl_player_actor/z_player.c | 64 +++++++++++++++---- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index bc87c47e2..6304c79ce 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -70,6 +70,7 @@ const std::vector enhancementsCvars = { "gForgeTime", "gClimbSpeed", "gFasterBlockPush", + "gCrawlSpeed", "gFasterHeavyBlockLift", "gNoForcedNavi", "gSkulltulaFreeze", diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 3c77438e8..7265087a0 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -542,6 +542,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index ab62692cc..9489eefcd 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -69,7 +69,13 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor PosRot sp8C; f32 tempRand; Unique9OnePointCs* csInfo = ONEPOINT_CS_INFO(csCam); - + + // #region SOH [Enhancement] + //the default is 90, lower values necessary to prevent camera swing as animation speeds up + s16 camCrawlTemp = CVarGetInteger("gCrawlSpeed", 1); + s16 camCrawlTimer = D_8012042C / camCrawlTemp; + // #endregion + switch (csId) { case 1020: if (timer < 20) { @@ -330,13 +336,26 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 9601: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); - OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398); + if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120398); + } else { + OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398); + } break; case 9602: - Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); - Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); - OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120434); - break; + // #region SOH [Enhancement] + if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); + Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); + OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120434); + break; + // #endregion + } else { + Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); + Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); + OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120434); + break; + } case 4175: csInfo->keyFrames = D_8012147C; csInfo->keyFrameCnt = 4; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 80f4828ed..0577add9e 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6982,9 +6982,19 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall this->actor.world.pos.z = zVertex1 + (distToInteractWall * wallPolyNormZ); func_80832224(this); this->actor.prevPos = this->actor.world.pos; - Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); - Player_AnimReplaceApplyFlags(play, this, 0x9D); - + // #region SOH [Enhancement] + if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + // increase animation speed when entering a tunnel + LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, + ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f, + Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), ANIMMODE_ONCE, + 0.0f); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + // #endregion + } else { + Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + } return true; } } @@ -7065,16 +7075,39 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { if (this->linearVelocity > 0.0f) { this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; - Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); - Player_AnimReplaceApplyFlags(play, this, 0x9D); - OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM); + // #region SOH [Enhancement] + if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + // animation when exiting a tunnel forward + LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_end, + ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f, + Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_end), ANIMMODE_ONCE, + 0.0f); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM); + // #endregion + } else { + Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM); + } } else { this->actor.shape.rot.y = this->actor.wallYaw; - LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f, - Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, - 0.0f); - Player_AnimReplaceApplyFlags(play, this, 0x9D); - OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM); + // #region SOH [Enhancement] + // animation when exiting a tunnel backward + if (CVarGetInteger("gCrawlSpeed",1) > 1) { + LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, + -1.0f * ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), + Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM); + // #endregion + } + else { + LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f, + Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f); + Player_AnimReplaceApplyFlags(play, this, 0x9D); + OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM); + } } this->currentYaw = this->actor.shape.rot.y; @@ -12625,8 +12658,15 @@ void func_8084C760(Player* this, PlayState* play) { return; } + // player speed in a tunnel if (!Player_TryLeavingCrawlspace(this, play)) { - this->linearVelocity = sControlInput->rel.stick_y * 0.03f; + // #region SOH [Enhancement] + if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + this->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVarGetInteger("gCrawlSpeed", 1); + // #endregion + } else { + this->linearVelocity = sControlInput->rel.stick_y * 0.03f; + } } } return; From be948339b965d76337bbec66563e7aabbcf489c1 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:52:10 -0500 Subject: [PATCH 028/300] Lost Woods Ocarina Game Difficulty Options (#3371) * Menu options, note speed, unlimited playback time * Instant win * Add custom ocarina game cvar to all options and presets * Extra spaces * Add starting note count, ending note count by round, more presets * Block out vanilla code + comments * finish blocking out vanilla code * new documentation formatting * add starting notes to randomizer preset --- soh/soh/Enhancements/presets.h | 15 +++++ soh/soh/SohMenuBar.cpp | 34 +++++++++++ soh/src/code/code_800EC960.c | 61 +++++++++++++++---- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 27 ++++++-- 4 files changed, 119 insertions(+), 18 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 6304c79ce..bcd61c6ed 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -186,6 +186,14 @@ const std::vector enhancementsCvars = { "gBombchuBowlingNoSmallCucco", "gBombchuBowlingNoBigCucco", "gBombchuBowlingAmmunition", + "gCustomizeOcarinaGame", + "gInstantOcarinaGameWin", + "gOcarinaGameNoteSpeed", + "gOcarinaUnlimitedFailTime", + "gOcarinaGameStartingNotes", + "gOcarinaGameRoundOneNotes", + "gOcarinaGameRoundTwoNotes", + "gOcarinaGameRoundThreeNotes", "gCreditsFix", "gSilverRupeeJingleExtend", "gStaticExplosionRadius", @@ -787,6 +795,13 @@ const std::vector randomizerPresetEntries = { // Adult Minimum Weight (8 to 13) PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), + // Customize Lost Woods Ocarina Game Behavior + PRESET_ENTRY_S32("gCustomizeOcarinaGame", 1), + // Start With Five Notes + PRESET_ENTRY_S32("gOcarinaGameStartingNotes", 5), + // Round One Notes + PRESET_ENTRY_S32("gOcarinaGameRoundOneNotes", 5), + // Visual Stone of Agony PRESET_ENTRY_S32("gVisualAgony", 1), // Pull grave during the day diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 7265087a0..4df2fb960 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -817,6 +817,40 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); ImGui::EndMenu(); } + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Lost Woods Ocarina Game")) { + UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeOcarinaGame"); + UIWidgets::Tooltip("Turn on/off changes to the lost woods ocarina game behavior"); + bool disabled = !CVarGetInteger("gCustomizeOcarinaGame", 0); + static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off"; + UIWidgets::PaddedEnhancementCheckbox("Instant Win", "gInstantOcarinaGameWin", true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Skips the lost woods ocarina game"); + UIWidgets::PaddedEnhancementSliderInt("Note Play Speed: %dx", "##OcarinaGameNoteSpeed", "gOcarinaGameNoteSpeed", 1, 5, "", 1, true, true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Adjust the speed that the skull kids play notes"); + UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", "gOcarinaUnlimitedFailTime", true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Removes the timer to play back the song"); + UIWidgets::PaddedEnhancementSliderInt("Number of Starting Notes: %d", "##OcarinaGameStartingNotes", "gOcarinaGameStartingNotes", 1, 8, "", 3, true, true, false, + disabled, disabledTooltip); + UIWidgets::Tooltip("Adjust the number of notes the skull kids play to start the first round"); + int roundMin = CVarGetInteger("gOcarinaGameStartingNotes", 3); + UIWidgets::PaddedEnhancementSliderInt("Round One Notes: %d", "##OcarinaGameRoundOne", + "gOcarinaGameRoundOneNotes", roundMin, 8, "", 5, true, true, + false, + disabled, disabledTooltip); + UIWidgets::Tooltip("Adjust the number of notes you need to play to end the first round"); + UIWidgets::PaddedEnhancementSliderInt("Round Two Notes: %d", "##OcarinaGameRoundTwoNotes", + "gOcarinaGameRoundTwoNotes", roundMin, 8, "", 6, true, true, + false, + disabled, disabledTooltip); + UIWidgets::Tooltip("Adjust the number of notes you need to play to end the second round"); + UIWidgets::PaddedEnhancementSliderInt("Round Three Notes: %d", "##OcarinaGameRoundThreeNotes", + "gOcarinaGameRoundThreeNotes", roundMin, 8, "", 8, true, true, + false, + disabled, disabledTooltip); + UIWidgets::Tooltip("Adjust the number of notes you need to play to end the third round"); + ImGui::EndMenu(); + } UIWidgets::Spacer(0); diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index 27de9b2d5..41d2a8ec3 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -2065,16 +2065,40 @@ void func_800EE404(void) { void Audio_OcaMemoryGameStart(u8 minigameRound) { u8 i; + + // #region SOH [Enhancement] + if (CVarGetInteger("gCustomizeOcarinaGame", 0)) { + u8 startingNotes = 3; + u8 roundOneCount = CVarGetInteger("gOcarinaGameRoundOneNotes", 5); + u8 roundTwoCount = CVarGetInteger("gOcarinaGameRoundTwoNotes", 6); + u8 roundThreeCount = CVarGetInteger("gOcarinaGameRoundThreeNotes", 8); + u8 modMinigameNoteCnts[] = { roundOneCount, roundTwoCount, roundThreeCount }; - if (minigameRound > 2) { - minigameRound = 2; - } - sOcaMinigameAppendPos = 0; - sOcaMinigameEndPos = sOcaMinigameNoteCnts[minigameRound]; + startingNotes = CVarGetInteger("gOcarinaGameStartingNotes", 3); - for (i = 0; i < 3; i++) { - Audio_OcaMemoryGameGenNote(); + if (minigameRound > 2) { + minigameRound = 2; + } + + sOcaMinigameAppendPos = 0; + sOcaMinigameEndPos = modMinigameNoteCnts[minigameRound]; + + for (i = 0; i < startingNotes; i++) { + Audio_OcaMemoryGameGenNote(); + } + // #endregion + } else { + if (minigameRound > 2) { + minigameRound = 2; + } + + sOcaMinigameAppendPos = 0; + sOcaMinigameEndPos = sOcaMinigameNoteCnts[minigameRound]; + + for (i = 0; i < 3; i++) { + Audio_OcaMemoryGameGenNote(); + } } } @@ -2093,11 +2117,24 @@ s32 Audio_OcaMemoryGameGenNote(void) { rndNote = sOcarinaNoteValues[(rnd + 1) % 5]; } - sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote; - sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = 0x2D; - sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50; - sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0; - sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0; + // #region SOH [Enhancement] + if (CVarGetInteger("gCustomizeOcarinaGame", 0)) { + int noteSpeed = 0x2D; + noteSpeed = noteSpeed / CVarGetInteger("gOcarinaGameNoteSpeed", 1); + + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = noteSpeed; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0; + // #endregion + } else { + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = 0x2D; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].volume = 0x50; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].vibrato = 0; + sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].tone = 0; + } sOcaMinigameAppendPos++; diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 3492d6de9..207d9612b 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1412,12 +1412,20 @@ void EnSkj_StartOcarinaMinigame(EnSkj* this, PlayState* play) { EnSkj_TurnPlayer(this, player); if (dialogState == TEXT_STATE_CLOSING) { - func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME); - if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) { - sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES; + // #region SOH [Enhancement] + if (CVarGetInteger("gInstantOcarinaGameWin", 0) && CVarGetInteger("gCustomizeOcarinaGame", 0)) { + play->msgCtx.ocarinaMode = OCARINA_MODE_0F; + this->songFailTimer = 160; + this->actionFunc = EnSkj_WaitForPlayback; + // #endregion + } else { + func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME); + if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) { + sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES; + this->songFailTimer = 160; + this->actionFunc = EnSkj_WaitForPlayback; + } } - this->songFailTimer = 160; - this->actionFunc = EnSkj_WaitForPlayback; } } @@ -1466,7 +1474,14 @@ void EnSkj_WaitForPlayback(EnSkj* this, PlayState* play) { break; case MSGMODE_MEMORY_GAME_PLAYER_PLAYING: if (this->songFailTimer != 0) { - this->songFailTimer--; + // #region SOH [Enhancement] + if (CVarGetInteger("gOcarinaUnlimitedFailTime", 0) == 1 && + CVarGetInteger("gCustomizeOcarinaGame", 0) == 1) { + // don't decrement timer + // #endregion + } else { + this->songFailTimer--; + } } else { // took too long, game failed func_80078884(NA_SE_SY_OCARINA_ERROR); Message_CloseTextbox(play); From 695ab6c6ee2d7df46096679ab440f8cc0817f045 Mon Sep 17 00:00:00 2001 From: Caladius Date: Thu, 1 Feb 2024 20:57:12 -0500 Subject: [PATCH 029/300] Hurt Container Mode (#3336) * Each Heart Container or full Heart Piece reduces Links hearts by 1 * Based on Briaguya's suggested Code but modified slightly as some parts were missing. * Static Bool * The episode without Captain Hook's Hook --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: Garrett Cox --- soh/soh/Enhancements/mods.cpp | 24 ++++++++++++++++++++++++ soh/soh/Enhancements/mods.h | 1 + soh/soh/SohMenuBar.cpp | 8 ++++++++ soh/src/code/z_message_PAL.c | 9 +++++++-- soh/src/code/z_parameter.c | 9 +++++++-- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 329a8ee48..bbb5d5998 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1090,6 +1090,29 @@ void RegisterRandomizerSheikSpawn() { }); } +void UpdateHurtContainerModeState(bool newState) { + static bool hurtEnabled = false; + if (hurtEnabled == newState) { + return; + } + + hurtEnabled = newState; + uint16_t getHeartPieces = gSaveContext.sohStats.heartPieces / 4; + uint16_t getHeartContainers = gSaveContext.sohStats.heartContainers; + + if (hurtEnabled) { + gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16); + } else { + gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16); + } +} + +void RegisterHurtContainerModeHandler() { + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) { + UpdateHurtContainerModeState(CVarGetInteger("gHurtContainer", 0)); + }); +} + void RegisterRandomizedEnemySizes() { GameInteractor::Instance->RegisterGameHook([](void* refActor) { // Randomized Enemy Sizes @@ -1256,4 +1279,5 @@ void InitMods() { RegisterRandomizedEnemySizes(); RegisterToTMedallions(); NameTag_RegisterHooks(); + RegisterHurtContainerModeHandler(); } diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index 46123f968..43a41449c 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -9,6 +9,7 @@ extern "C" { void UpdateDirtPathFixState(int32_t sceneNum); void UpdateMirrorModeState(int32_t sceneNum); +void UpdateHurtContainerModeState(bool newState); void PatchToTMedallions(); void UpdatePermanentHeartLossState(); void InitMods(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 4df2fb960..9f3604219 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1294,6 +1294,14 @@ void DrawEnhancementsMenu() { } } + UIWidgets::Spacer(0); + if (UIWidgets::PaddedEnhancementCheckbox("Hurt Container Mode", "gHurtContainer", true, false)) { + UpdateHurtContainerModeState(CVarGetInteger("gHurtContainer", 0)); + } + UIWidgets::Tooltip("Changes Heart Piece and Heart Container functionality.\n\n" + "- Each Heart Container or full Heart Piece reduces Links hearts by 1.\n" + "- Can be enabled retroactively after a File has already started."); + ImGui::EndMenu(); } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 7bb3803fc..4c661aad7 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -3361,8 +3361,13 @@ void Message_Update(PlayState* play) { } if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) { gSaveContext.inventory.questItems ^= 0x40000000; - gSaveContext.healthCapacity += 0x10; - gSaveContext.health += 0x10; + if (!CVarGetInteger("gHurtContainer", 0)) { + gSaveContext.healthCapacity += 0x10; + gSaveContext.health += 0x10; + } else { + gSaveContext.healthCapacity -= 0x10; + gSaveContext.health -= 0x10; + } } if (msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOWARP_DONE) { if (sLastPlayedSong == OCARINA_SONG_SARIAS) { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index f9a54eb2c..6efa962b6 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2278,8 +2278,13 @@ u8 Item_Give(PlayState* play, u8 item) { gSaveContext.sohStats.heartPieces++; return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_HEART_CONTAINER) { - gSaveContext.healthCapacity += 0x10; - gSaveContext.health += 0x10; + if (!CVarGetInteger("gHurtContainer", 0)) { + gSaveContext.healthCapacity += 0x10; + gSaveContext.health += 0x10; + } else { + gSaveContext.healthCapacity -= 0x10; + gSaveContext.health -= 0x10; + } gSaveContext.sohStats.heartContainers++; return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_HEART) { From 2529dc59bd5ab3be95ed7d5530cde90bc48758de Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 2 Feb 2024 01:58:08 +0000 Subject: [PATCH 030/300] Increase Door Cull range (#3888) * cullzone * better cvar name * Update soh/src/code/z_actor.c * Update soh/src/code/z_actor.c --------- Co-authored-by: Garrett Cox --- soh/src/code/z_actor.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index df9b6c758..c1dc66e23 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -2860,11 +2860,19 @@ s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) { var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3; - if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) && - (((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) && - (((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) { + // #region SoH [Widescreen support] + // Doors will cull quite noticeably on wider screens. For these actors the zone is increased + f32 limit = 1.0f; + if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger("gIncreaseDoorUncullZones", 1)) { + limit = 2.0f; + } + + if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < limit) && + (((arg2->y + actor->uncullZoneDownward) * var) > -limit) && + (((arg2->y - actor->uncullZoneScale) * var) < limit)) { return true; } + // #endregion } return false; From bb1078e99ca1789a2de696a4229dd27b1ec5da3c Mon Sep 17 00:00:00 2001 From: Rozelette Date: Thu, 1 Feb 2024 19:58:22 -0600 Subject: [PATCH 031/300] Account for removed object dependency in Deku Scrub Leader (#3878) * Account for removed object dependency in Deku Scrub Leader * Update soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c --------- Co-authored-by: Garrett Cox --- soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c index ae09cb438..9ce27f4c1 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c @@ -101,6 +101,9 @@ void EnDntJiji_Destroy(Actor* thisx, PlayState* play) { } void EnDntJiji_SetFlower(EnDntJiji* this, PlayState* play) { + // SOH: Due to removed object dependencies, parent was still NULL when Init was called. In order to properly set + // stage, redo it here now that we are a frame later. + this->stage = (EnDntDemo*)this->actor.parent; if (this->actor.bgCheckFlags & 1) { this->flowerPos = this->actor.world.pos; this->actionFunc = EnDntJiji_SetupWait; From 4bdb5098b0827b341e2ef2ad18b781bb1eae3f87 Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Thu, 1 Feb 2024 21:01:18 -0500 Subject: [PATCH 032/300] Colors 1 (#3463) --- .../cosmetics/CosmeticsEditor.cpp | 40 ++++ .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 215 +++++++++++++----- 2 files changed, 192 insertions(+), 63 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 50b5c5b27..629f4b0cd 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -67,6 +67,7 @@ typedef enum { GROUP_EQUIPMENT, GROUP_CONSUMABLE, GROUP_HUD, + GROUP_KALEIDO, GROUP_TITLE, GROUP_NPC, GROUP_WORLD, @@ -85,6 +86,7 @@ std::map groupLabels = { { GROUP_EQUIPMENT, "Equipment" }, { GROUP_CONSUMABLE, "Consumables" }, { GROUP_HUD, "HUD" }, + { GROUP_KALEIDO, "Pause Menu" }, { GROUP_TITLE, "Title Screen" }, { GROUP_NPC, "NPCs" }, { GROUP_WORLD, "World" }, @@ -265,6 +267,38 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), + COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + + COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + + COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + + COSMETIC_OPTION("Kal_QuestStatusA", "Quest StatusColor A", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusB", "Quest StatusColor B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusC", "Quest StatusColor C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusD", "Quest StatusColor D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + + COSMETIC_OPTION("Kal_MapSelectA", "Map Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + + COSMETIC_OPTION("Kal_SaveA", "Save A", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveB", "Save B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveC", "Save C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveD", "Save D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + + COSMETIC_OPTION("Kal_NamePanel", "Name Panel", GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), + COSMETIC_OPTION("Title_FileChoose", "File Choose", GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), @@ -1873,10 +1907,16 @@ void CosmeticsEditorWindow::DrawElement() { DrawCosmeticGroup(GROUP_TITLE); ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("HUD Placement")) { Draw_Placements(); ImGui::EndTabItem(); } + + if (ImGui::BeginTabItem("Pause Menu")) { + DrawCosmeticGroup(GROUP_KALEIDO); + ImGui::EndTabItem(); + } ImGui::EndTabBar(); } ImGui::End(); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 2da5d5b25..5f8da1b70 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1883,11 +1883,17 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 90, 100, 130, 255); + const Color_RGBA8 namePanelColor = CVarGetColor("gCosmetics.Kal_NamePanel.Value", (Color_RGBA8){90,100,130,255}); + + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, namePanelColor.r, namePanelColor.g, namePanelColor.b, namePanelColor.a); gSPVertex(POLY_KAL_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0); gSPDisplayList(POLY_KAL_DISP++, gItemNamePanelDL); + if (CVarGetInteger("gUniformLR", 0) == 0) { // Restore the misplace gDPSetPrimColor + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 90, 100, 130, 255); + } + if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->unk_1E4 == 0)) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, D_808321A0, D_808321A2, D_808321A4, D_808321A6); } else { @@ -1895,6 +1901,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255); } } + gSPDisplayList(POLY_KAL_DISP++, gLButtonIconDL); @@ -2305,15 +2312,15 @@ void KaleidoScope_SetView(PauseContext* pauseCtx, f32 x, f32 y, f32 z) { func_800AAA50(&pauseCtx->view, 127); } -static u8 D_8082AE48[][4] = { +static u8 sPageVtxColorR[][4] = { { 10, 70, 70, 10 }, { 10, 90, 90, 10 }, { 80, 140, 140, 80 }, { 80, 120, 120, 80 }, { 80, 140, 140, 80 }, { 50, 110, 110, 50 }, }; -static u8 D_8082AE60[][4] = { +static u8 sPageVtxColorG[][4] = { { 50, 100, 100, 50 }, { 50, 100, 100, 50 }, { 40, 60, 60, 40 }, { 80, 120, 120, 80 }, { 40, 60, 60, 40 }, { 50, 110, 110, 50 }, }; -static u8 D_8082AE78[][4] = { +static u8 sPageVtxColorB[][4] = { { 80, 130, 130, 80 }, { 40, 60, 60, 40 }, { 30, 60, 60, 30 }, { 50, 70, 70, 50 }, { 30, 60, 60, 30 }, { 50, 110, 110, 50 }, }; @@ -2441,10 +2448,87 @@ static s16 D_8082B0E4[] = { 0x0019, 0x000D, 0x0001, 0x0001, 0x000D, 0x0015, 0x000F, 0x000D, 0x000C, 0x0001, 0x0000, }; -s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { +static const char* gPageVtxColorCvars[][4] = { + { + "gCosmetics.Kal_ItemSelA.Value", + "gCosmetics.Kal_ItemSelB.Value", + "gCosmetics.Kal_ItemSelC.Value", + "gCosmetics.Kal_ItemSelD.Value", + }, + { + "gCosmetics.Kal_EquipSelA.Value", + "gCosmetics.Kal_EquipSelB.Value", + "gCosmetics.Kal_EquipSelC.Value", + "gCosmetics.Kal_EquipSelD.Value", + }, + { + "gCosmetics.Kal_MapSelDunA.Value", + "gCosmetics.Kal_MapSelDunB.Value", + "gCosmetics.Kal_MapSelDunC.Value", + "gCosmetics.Kal_MapSelDunD.Value", + }, + { + "gCosmetics.Kal_QuestStatusA.Value", + "gCosmetics.Kal_QuestStatusB.Value", + "gCosmetics.Kal_QuestStatusC.Value", + "gCosmetics.Kal_QuestStatusD.Value", + }, + { + "gCosmetics.Kal_MapSelectA.Value", + "gCosmetics.Kal_MapSelectB.Value", + "gCosmetics.Kal_MapSelectC.Value", + "gCosmetics.Kal_MapSelectD.Value", + }, + { + "gCosmetics.Kal_SaveA.Value", + "gCosmetics.Kal_SaveB.Value", + "gCosmetics.Kal_SaveC.Value", + "gCosmetics.Kal_SaveD.Value", + }, +}; + +s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 pageIndex, s16 arg3) { static s16 D_8082B110 = 0; static s16 D_8082B114 = 1; static s16 D_8082B118 = 0; + static const Color_RGBA8 pageColors[][4] = { + { + { 10, 50, 80, 255 }, + { 70, 100, 130, 255 }, + { 70, 100, 130, 255 }, + { 10, 50, 80, 255 }, + }, + { + { 10, 50, 40, 255 }, + { 90, 100, 60, 255 }, + { 90, 100, 60, 255 }, + { 10, 50, 40, 255 }, + }, + { + { 80,40,30, 255}, + { 140,60,60,255 }, + { 140,60,60,255 }, + { 80, 40, 30, 255 }, + }, + { + { 80,80,50,255 }, + { 120,120,70,255 }, + { 120,120,70,255 }, + { 80, 80, 50, 255 }, + }, + { + { 80, 40, 30, 255 }, + { 140,60,60,255 }, + { 140,60,60,255 }, + { 80, 40, 30, 255 }, + }, + { + { 50,50,50,255 }, + { 110,110,110,255 }, + { 110,110,110,255 }, + { 50,50,50,255 }, + }, + }; PauseContext* pauseCtx = &play->pauseCtx; s16* ptr1; s16* ptr2; @@ -2454,109 +2538,114 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { s16 phi_t0; s16 phi_a1; s16 phi_a2; - s16 phi_t3; - s16 phi_t1; + s16 colorIndex; // Also used for other things. + s16 vtxIndex; phi_t0 = -200; - for (phi_t1 = 0, phi_t3 = 0; phi_t3 < 3; phi_t3++) { + for (vtxIndex = 0, colorIndex = 0; colorIndex < 3; colorIndex++) { phi_t0 += 80; - for (phi_a1 = 80, phi_a2 = 0; phi_a2 < 5; phi_a2++, phi_t1 += 4, phi_a1 -= 32) { - vtx[phi_t1 + 0].v.ob[0] = vtx[phi_t1 + 2].v.ob[0] = phi_t0; + for (phi_a1 = 80, phi_a2 = 0; phi_a2 < 5; phi_a2++, vtxIndex += 4, phi_a1 -= 32) { + vtx[vtxIndex + 0].v.ob[0] = vtx[vtxIndex + 2].v.ob[0] = phi_t0; - vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + 80; + vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + 80; - vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = phi_a1 + pauseCtx->offsetY; + vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = phi_a1 + pauseCtx->offsetY; - vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - 32; + vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - 32; - vtx[phi_t1 + 0].v.ob[2] = vtx[phi_t1 + 1].v.ob[2] = vtx[phi_t1 + 2].v.ob[2] = vtx[phi_t1 + 3].v.ob[2] = 0; + vtx[vtxIndex + 0].v.ob[2] = vtx[vtxIndex + 1].v.ob[2] = vtx[vtxIndex + 2].v.ob[2] = vtx[vtxIndex + 3].v.ob[2] = 0; - vtx[phi_t1 + 0].v.flag = 0; - vtx[phi_t1 + 1].v.flag = 0; - vtx[phi_t1 + 2].v.flag = 0; - vtx[phi_t1 + 3].v.flag = 0; + vtx[vtxIndex + 0].v.flag = 0; + vtx[vtxIndex + 1].v.flag = 0; + vtx[vtxIndex + 2].v.flag = 0; + vtx[vtxIndex + 3].v.flag = 0; - vtx[phi_t1 + 0].v.tc[0] = vtx[phi_t1 + 0].v.tc[1] = vtx[phi_t1 + 1].v.tc[1] = vtx[phi_t1 + 2].v.tc[0] = 0; + vtx[vtxIndex + 0].v.tc[0] = vtx[vtxIndex + 0].v.tc[1] = vtx[vtxIndex + 1].v.tc[1] = vtx[vtxIndex + 2].v.tc[0] = 0; - vtx[phi_t1 + 1].v.tc[0] = vtx[phi_t1 + 3].v.tc[0] = 0xA00; + vtx[vtxIndex + 1].v.tc[0] = vtx[vtxIndex + 3].v.tc[0] = 0xA00; - vtx[phi_t1 + 2].v.tc[1] = vtx[phi_t1 + 3].v.tc[1] = 0x400; + vtx[vtxIndex + 2].v.tc[1] = vtx[vtxIndex + 3].v.tc[1] = 0x400; - vtx[phi_t1 + 0].v.cn[0] = vtx[phi_t1 + 2].v.cn[0] = D_8082AE48[arg2][phi_t3 + 0]; + //Color in the pages. Pages are drawn in groups. Each group is faded to the next. There are 4 total colors, 1/4 and 2/3 are the same creating a mirrored color set. + // TODO, go from 0,1,2,3 to 0,1,1,0 to only use two colors instead of 4. + Color_RGBA8 color = CVarGetColor(gPageVtxColorCvars[pageIndex][colorIndex], pageColors[pageIndex][colorIndex]); + Color_RGBA8 colorb = + CVarGetColor(gPageVtxColorCvars[pageIndex][colorIndex + 1], pageColors[pageIndex][colorIndex+1]); + vtx[vtxIndex + 0].v.cn[0] = vtx[vtxIndex + 2].v.cn[0] = color.r; // sPageVtxColorR[pageIndex][colorIndex + 0]; - vtx[phi_t1 + 0].v.cn[1] = vtx[phi_t1 + 2].v.cn[1] = D_8082AE60[arg2][phi_t3 + 0]; + vtx[vtxIndex + 0].v.cn[1] = vtx[vtxIndex + 2].v.cn[1] = color.g;// sPageVtxColorG[pageIndex][colorIndex + 0]; - vtx[phi_t1 + 0].v.cn[2] = vtx[phi_t1 + 2].v.cn[2] = D_8082AE78[arg2][phi_t3 + 0]; + vtx[vtxIndex + 0].v.cn[2] = vtx[vtxIndex + 2].v.cn[2] = color.b; // sPageVtxColorB[pageIndex][colorIndex + 0]; - vtx[phi_t1 + 1].v.cn[0] = vtx[phi_t1 + 3].v.cn[0] = D_8082AE48[arg2][phi_t3 + 1]; + vtx[vtxIndex + 1].v.cn[0] = vtx[vtxIndex + 3].v.cn[0] = colorb.r;//sPageVtxColorR[pageIndex][colorIndex + 1]; - vtx[phi_t1 + 1].v.cn[1] = vtx[phi_t1 + 3].v.cn[1] = D_8082AE60[arg2][phi_t3 + 1]; + vtx[vtxIndex + 1].v.cn[1] = vtx[vtxIndex + 3].v.cn[1] = colorb.g; // sPageVtxColorG[pageIndex][colorIndex + 1]; - vtx[phi_t1 + 1].v.cn[2] = vtx[phi_t1 + 3].v.cn[2] = D_8082AE78[arg2][phi_t3 + 1]; + vtx[vtxIndex + 1].v.cn[2] = vtx[vtxIndex + 3].v.cn[2] = colorb.b; // sPageVtxColorB[pageIndex][colorIndex + 1]; - vtx[phi_t1 + 0].v.cn[3] = vtx[phi_t1 + 2].v.cn[3] = vtx[phi_t1 + 1].v.cn[3] = vtx[phi_t1 + 3].v.cn[3] = + vtx[vtxIndex + 0].v.cn[3] = vtx[vtxIndex + 2].v.cn[3] = vtx[vtxIndex + 1].v.cn[3] = vtx[vtxIndex + 3].v.cn[3] = pauseCtx->alpha; } } - phi_s2 = phi_t1; + phi_s2 = vtxIndex; if (arg3 != 0) { - ptr1 = D_8082B000[arg2]; - ptr2 = D_8082B018[arg2]; - ptr3 = D_8082B030[arg2]; - ptr4 = D_8082B048[arg2]; + ptr1 = D_8082B000[pageIndex]; + ptr2 = D_8082B018[pageIndex]; + ptr3 = D_8082B030[pageIndex]; + ptr4 = D_8082B048[pageIndex]; - for (phi_t3 = 0; phi_t3 < arg3; phi_t3++, phi_t1 += 4) { - vtx[phi_t1 + 2].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] = ptr1[phi_t3]; + for (colorIndex = 0; colorIndex < arg3; colorIndex++, vtxIndex += 4) { + vtx[vtxIndex + 2].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] = ptr1[colorIndex]; - vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + ptr2[phi_t3]; + vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + ptr2[colorIndex]; if (!((pauseCtx->state >= 8) && (pauseCtx->state <= 0x11))) { - vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = ptr3[phi_t3] + pauseCtx->offsetY; + vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = ptr3[colorIndex] + pauseCtx->offsetY; } else { - vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = YREG(60 + phi_t3) + pauseCtx->offsetY; + vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = YREG(60 + colorIndex) + pauseCtx->offsetY; } - vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - ptr4[phi_t3]; + vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - ptr4[colorIndex]; - vtx[phi_t1 + 0].v.ob[2] = vtx[phi_t1 + 1].v.ob[2] = vtx[phi_t1 + 2].v.ob[2] = vtx[phi_t1 + 3].v.ob[2] = 0; + vtx[vtxIndex + 0].v.ob[2] = vtx[vtxIndex + 1].v.ob[2] = vtx[vtxIndex + 2].v.ob[2] = vtx[vtxIndex + 3].v.ob[2] = 0; - vtx[phi_t1 + 0].v.flag = vtx[phi_t1 + 1].v.flag = vtx[phi_t1 + 2].v.flag = vtx[phi_t1 + 3].v.flag = 0; + vtx[vtxIndex + 0].v.flag = vtx[vtxIndex + 1].v.flag = vtx[vtxIndex + 2].v.flag = vtx[vtxIndex + 3].v.flag = 0; - vtx[phi_t1 + 0].v.tc[0] = vtx[phi_t1 + 0].v.tc[1] = vtx[phi_t1 + 1].v.tc[1] = vtx[phi_t1 + 2].v.tc[0] = 0; + vtx[vtxIndex + 0].v.tc[0] = vtx[vtxIndex + 0].v.tc[1] = vtx[vtxIndex + 1].v.tc[1] = vtx[vtxIndex + 2].v.tc[0] = 0; - vtx[phi_t1 + 1].v.tc[0] = vtx[phi_t1 + 3].v.tc[0] = ptr2[phi_t3] << 5; + vtx[vtxIndex + 1].v.tc[0] = vtx[vtxIndex + 3].v.tc[0] = ptr2[colorIndex] << 5; - vtx[phi_t1 + 2].v.tc[1] = vtx[phi_t1 + 3].v.tc[1] = ptr4[phi_t3] << 5; + vtx[vtxIndex + 2].v.tc[1] = vtx[vtxIndex + 3].v.tc[1] = ptr4[colorIndex] << 5; - vtx[phi_t1 + 0].v.cn[0] = vtx[phi_t1 + 2].v.cn[0] = vtx[phi_t1 + 0].v.cn[1] = vtx[phi_t1 + 2].v.cn[1] = - vtx[phi_t1 + 0].v.cn[2] = vtx[phi_t1 + 2].v.cn[2] = vtx[phi_t1 + 1].v.cn[0] = vtx[phi_t1 + 3].v.cn[0] = - vtx[phi_t1 + 1].v.cn[1] = vtx[phi_t1 + 3].v.cn[1] = vtx[phi_t1 + 1].v.cn[2] = - vtx[phi_t1 + 3].v.cn[2] = 255; + vtx[vtxIndex + 0].v.cn[0] = vtx[vtxIndex + 2].v.cn[0] = vtx[vtxIndex + 0].v.cn[1] = vtx[vtxIndex + 2].v.cn[1] = + vtx[vtxIndex + 0].v.cn[2] = vtx[vtxIndex + 2].v.cn[2] = vtx[vtxIndex + 1].v.cn[0] = vtx[vtxIndex + 3].v.cn[0] = + vtx[vtxIndex + 1].v.cn[1] = vtx[vtxIndex + 3].v.cn[1] = vtx[vtxIndex + 1].v.cn[2] = + vtx[vtxIndex + 3].v.cn[2] = 255; - vtx[phi_t1 + 0].v.cn[3] = vtx[phi_t1 + 2].v.cn[3] = vtx[phi_t1 + 1].v.cn[3] = vtx[phi_t1 + 3].v.cn[3] = + vtx[vtxIndex + 0].v.cn[3] = vtx[vtxIndex + 2].v.cn[3] = vtx[vtxIndex + 1].v.cn[3] = vtx[vtxIndex + 3].v.cn[3] = pauseCtx->alpha; } - if (arg2 == 4) { - phi_t1 -= 12; + if (pageIndex == 4) { + vtxIndex -= 12; - phi_t3 = gSaveContext.worldMapArea; + colorIndex = gSaveContext.worldMapArea; - vtx[phi_t1 + 0].v.ob[0] = vtx[phi_t1 + 2].v.ob[0] = D_8082B060[phi_t3]; + vtx[vtxIndex + 0].v.ob[0] = vtx[vtxIndex + 2].v.ob[0] = D_8082B060[colorIndex]; - if (phi_t3) {} + if (colorIndex) {} - vtx[phi_t1 + 1].v.ob[0] = vtx[phi_t1 + 3].v.ob[0] = vtx[phi_t1 + 0].v.ob[0] + D_8082B08C[phi_t3]; + vtx[vtxIndex + 1].v.ob[0] = vtx[vtxIndex + 3].v.ob[0] = vtx[vtxIndex + 0].v.ob[0] + D_8082B08C[colorIndex]; - vtx[phi_t1 + 0].v.ob[1] = vtx[phi_t1 + 1].v.ob[1] = D_8082B0B8[phi_t3] + pauseCtx->offsetY; + vtx[vtxIndex + 0].v.ob[1] = vtx[vtxIndex + 1].v.ob[1] = D_8082B0B8[colorIndex] + pauseCtx->offsetY; - vtx[phi_t1 + 2].v.ob[1] = vtx[phi_t1 + 3].v.ob[1] = vtx[phi_t1 + 0].v.ob[1] - D_8082B0E4[phi_t3]; + vtx[vtxIndex + 2].v.ob[1] = vtx[vtxIndex + 3].v.ob[1] = vtx[vtxIndex + 0].v.ob[1] - D_8082B0E4[colorIndex]; - phi_t1 += 12; + vtxIndex += 12; if (pauseCtx->tradeQuestLocation != 0xFF) { if (D_8082B114 == 0) { @@ -2576,14 +2665,14 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { D_8082B114--; } - phi_t3 = phi_s2 + (pauseCtx->tradeQuestLocation * 4) + 64; + colorIndex = phi_s2 + (pauseCtx->tradeQuestLocation * 4) + 64; phi_a2 = phi_s2 + 116; - vtx[phi_a2 + 0].v.ob[0] = vtx[phi_a2 + 2].v.ob[0] = vtx[phi_t3 + 0].v.ob[0]; + vtx[phi_a2 + 0].v.ob[0] = vtx[phi_a2 + 2].v.ob[0] = vtx[colorIndex + 0].v.ob[0]; vtx[phi_a2 + 1].v.ob[0] = vtx[phi_a2 + 3].v.ob[0] = vtx[phi_a2 + 0].v.ob[0] + 8; - vtx[phi_a2 + 0].v.ob[1] = vtx[phi_a2 + 1].v.ob[1] = vtx[phi_t3 + 0].v.ob[1] - D_8082B110 + 10; + vtx[phi_a2 + 0].v.ob[1] = vtx[phi_a2 + 1].v.ob[1] = vtx[colorIndex + 0].v.ob[1] - D_8082B110 + 10; vtx[phi_a2 + 0].v.ob[2] = vtx[phi_a2 + 1].v.ob[2] = vtx[phi_a2 + 2].v.ob[2] = vtx[phi_a2 + 3].v.ob[2] = 0; @@ -2592,7 +2681,7 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { vtx[phi_a2 + 0].v.flag = vtx[phi_a2 + 1].v.flag = vtx[phi_a2 + 2].v.flag = vtx[phi_a2 + 3].v.flag = 0; - vtx[phi_t1].v.tc[0] = vtx[phi_t1].v.tc[1] = vtx[phi_a2 + 1].v.tc[1] = vtx[phi_a2 + 2].v.tc[0] = 0; + vtx[vtxIndex].v.tc[0] = vtx[vtxIndex].v.tc[1] = vtx[phi_a2 + 1].v.tc[1] = vtx[phi_a2 + 2].v.tc[0] = 0; vtx[phi_a2 + 1].v.tc[0] = vtx[phi_a2 + 3].v.tc[0] = 0x100; @@ -2609,7 +2698,7 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { } } - return phi_t1; + return vtxIndex; } static s16 D_8082B11C[] = { 0, 4, 8, 12, 24, 32, 56 }; From e4948d9ce4d137a0dcb23433155ac1e8742f1286 Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 2 Feb 2024 03:01:38 +0100 Subject: [PATCH 033/300] Triforce Hunt GI Model Blender source files (#3478) * Triforce Hunt GI model source files * Move assets to different path --- soh/assets/.gitignore | 2 +- soh/assets/sources/triforce-hunt/paths.txt | 15 +++++++++++++++ .../triforce-hunt/textures/noise_tex.png | Bin 0 -> 660 bytes .../triforce-hunt/triforce_complete.blend | Bin 0 -> 2102772 bytes .../triforce-hunt/triforce_shard_0.blend | Bin 0 -> 2111940 bytes .../triforce-hunt/triforce_shard_1.blend | Bin 0 -> 1789284 bytes .../triforce-hunt/triforce_shard_2.blend | Bin 0 -> 2105304 bytes 7 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 soh/assets/sources/triforce-hunt/paths.txt create mode 100644 soh/assets/sources/triforce-hunt/textures/noise_tex.png create mode 100644 soh/assets/sources/triforce-hunt/triforce_complete.blend create mode 100644 soh/assets/sources/triforce-hunt/triforce_shard_0.blend create mode 100644 soh/assets/sources/triforce-hunt/triforce_shard_1.blend create mode 100644 soh/assets/sources/triforce-hunt/triforce_shard_2.blend diff --git a/soh/assets/.gitignore b/soh/assets/.gitignore index dce395e6f..d75078bf1 100644 --- a/soh/assets/.gitignore +++ b/soh/assets/.gitignore @@ -4,4 +4,4 @@ *.cfg *.vtx.inc *.dlist.inc -*.txt \ No newline at end of file +!*.png diff --git a/soh/assets/sources/triforce-hunt/paths.txt b/soh/assets/sources/triforce-hunt/paths.txt new file mode 100644 index 000000000..40b397186 --- /dev/null +++ b/soh/assets/sources/triforce-hunt/paths.txt @@ -0,0 +1,15 @@ +Complete triforce: + DL name: gTriforcePieceCompletedDL + Export Path: objects/object_triforce_completed + +Shard 0: + DL name: gTriforcePiece0DL + Export Path: objects/object_triforce_piece_0 + +Shard 1: + DL name: gTriforcePiece1DL + Export Path: objects/object_triforce_piece_1 + +Shard 2: + DL name: gTriforcePiece2DL + Export Path: objects/object_triforce_piece_2 diff --git a/soh/assets/sources/triforce-hunt/textures/noise_tex.png b/soh/assets/sources/triforce-hunt/textures/noise_tex.png new file mode 100644 index 0000000000000000000000000000000000000000..e4329f5d131e1fd8c506d9846aa7ab61d0c6db35 GIT binary patch literal 660 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�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

=I?Q<2=tHs(7z%0 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 literal 0 HcmV?d00001 diff --git a/soh/assets/sources/triforce-hunt/triforce_shard_0.blend b/soh/assets/sources/triforce-hunt/triforce_shard_0.blend new file mode 100644 index 0000000000000000000000000000000000000000..cd13e8859998aebe0f5e987c6f75e88599edfa63 GIT binary patch literal 2111940 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
    8{0=;DZSaEt^2w_?tD8J|xoSw=l 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 QYXuc5T`)g4fBX0U07`Uv;s5{u literal 0 HcmV?d00001 diff --git a/soh/assets/sources/triforce-hunt/triforce_shard_1.blend b/soh/assets/sources/triforce-hunt/triforce_shard_1.blend new file mode 100644 index 0000000000000000000000000000000000000000..aca2f06007d36663b3d07c767e12e91a87dddf0f GIT binary patch literal 1789284 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%0Ac~v9H2*KgmAW1N(fo4|YfFJHjlb zx^WY`CLV4t%}*$2C+om@J+EN3ep9@V)y=XJTJXU6Q2 zc9QKzJtlb__1j4(Q$0q8#|Fm5vo)b*-Q~QLxfANY>4$}IrhAoiJ*vmg#6{MW_<;x5 z3;W%(6%XKpbi~|=nA=;1qBlzl`(O|3n_~N5H`zzyOUnj_7xfR8Zzh!=x4=Hw1N*$y z3P0FQ=>4&qsPJtinfqj!~AMDobTO?kDSGrkg_`x37 z=e}3r2fLMh)wPUi_Q4+5H^uhBZe?HDBkmy$Y4*V$*yo+2@PpmTKDu*cSu=OX7@Ctg z2mgaTu&+L$?1SAA`^1&bP_w_lNN#5Hg1#B{z&@YtgWbwL*}n9Rtq@P}mV5_Y8o#gy z_O;%p@PpmTzQuzBBO@iw_@v_qeqj&nbIw)v!ER;WiX~%9$JL$feM<($Tjg~ndOW6E z4f|jZ?3-l!V7G4H=(0s6Tc=wT&BH#}1N+?b6n?N^AM|TRJdUW+$9xAMAmB_4h0LV7F=C;L0+sGg%GS z;eW6P_W5id>~6Dfcu81Dg*n&~88D9SY`(O|3b3Ul-gWaZm z;-wE`BPHTS<;N|s5B9*mNwyDm>-H@^d+}g%{Opl3Bk45zU=QqbJ%u0aj@UFWy&C?E?RU zJ+QC-VPzle*6n-e*y!T1=4Lo~Mb%*+?16ng+XuVJK8mjTM*GFkQu&yr@e6xkU+W_Z zKiEzBGw5_jy$(j8_i<{zoYeW6wmZ0kT z67UOqVBaL$2fGdX)GKECWJ}mr#*_<<55_I95B9)5_g@u$u)C9eWlXuG@e6xk-xS*i zyGg&lU(gv>$qKgtKiC8NypJmUU^m(K&c4MfMk=%=u4vc?dthJvLS-N9R`#tNsqRdO zvrcRO*dEyD^E&J%`@|h@qg%>8*aQ1o7b*OJBiXljaI|lDsBiI^n{oIY{K6jC=X^}r z2fL+xXD;hoGPZf*daw=qU=Qq@Wcy&Z^uO}E4VaOb!ampo``n8aey|((t=i1b#lt?> z1N)}fKG;q6aa<)>-dxd3c>cm3*ynv*;Rn0PKJm=h;%48X%@bHLI0z`pt=%0Adl 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

    LuW*< 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

    !`eqHIcrn?EP9KgDxC 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%0Aew+eh<{8)^<0_Q4+5 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 Date: Thu, 1 Feb 2024 21:10:49 -0500 Subject: [PATCH 034/300] Randomize cosmetics on new scene (#3342) * Randomize cosmetics on new scene * Code review feedback --------- Co-authored-by: Garrett Cox --- .../cosmetics/CosmeticsEditor.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 629f4b0cd..6c1e007fa 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1828,14 +1828,11 @@ void CosmeticsEditorWindow::DrawElement() { } UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync"); UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false, true); + UIWidgets::EnhancementCheckbox("Randomize All on New Scene", "gCosmetics.RandomizeAllOnNewScene"); + UIWidgets::Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene."); + if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { - for (auto& [id, cosmeticOption] : cosmeticOptions) { - if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0))) { - RandomizeColor(cosmeticOption); - } - } - ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + CosmeticsEditor_RandomizeAll(); } ImGui::SameLine(); if (ImGui::Button("Reset All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { @@ -1934,6 +1931,14 @@ void RegisterOnGameFrameUpdateHook() { }); } +void Cosmetics_RegisterOnSceneInitHook() { + GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { + if (CVarGetInteger("gCosmetics.RandomizeAllOnNewScene", 0)) { + CosmeticsEditor_RandomizeAll(); + } + }); +} + void CosmeticsEditorWindow::InitElement() { // Convert the `current color` into the format that the ImGui color picker expects for (auto& [id, cosmeticOption] : cosmeticOptions) { @@ -1951,6 +1956,7 @@ void CosmeticsEditorWindow::InitElement() { RegisterOnLoadGameHook(); RegisterOnGameFrameUpdateHook(); + Cosmetics_RegisterOnSceneInitHook(); } void CosmeticsEditor_RandomizeAll() { From ed85a1b0e227149ac2dd1b6ca557f4d1a40dab72 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 1 Feb 2024 21:12:28 -0500 Subject: [PATCH 035/300] [Time Saver] Reset Navi Timer (#3818) * Reset Navi Timer * Force Rebuild * Prefix --- soh/soh/Enhancements/mods.cpp | 9 +++++++++ soh/soh/SohMenuBar.cpp | 2 ++ 2 files changed, 11 insertions(+) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index bbb5d5998..c1561aa42 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -687,6 +687,14 @@ void RegisterMirrorModeHandler() { }); } +void RegisterResetNaviTimer() { + GameInteractor::Instance->RegisterGameHook([](int32_t sceneNum) { + if (CVarGetInteger("gEnhancements.ResetNaviTimer", 0)) { + gSaveContext.naviTimer = 0; + } + }); +} + f32 triforcePieceScale; void RegisterTriforceHunt() { @@ -1271,6 +1279,7 @@ void InitMods() { RegisterBonkDamage(); RegisterMenuPathFix(); RegisterMirrorModeHandler(); + RegisterResetNaviTimer(); RegisterTriforceHunt(); RegisterGrantGanonsBossKey(); RegisterEnemyDefeatCounts(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 9f3604219..c0aae7a5e 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -574,6 +574,8 @@ void DrawEnhancementsMenu() { "This doesn't work if the save was made in a grotto."); UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); UIWidgets::Tooltip("Prevent forced Navi conversations"); + UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false); + UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. "); UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); From f8b0e586bb4c107ddebeb2fef12de3a7debad7bb Mon Sep 17 00:00:00 2001 From: Josh Bodner <30329717+jbodner09@users.noreply.github.com> Date: Thu, 1 Feb 2024 18:14:17 -0800 Subject: [PATCH 036/300] Fix +/- buttons on float sliders not working at certain values (#3865) --- soh/soh/UIWidgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index ca104f945..8de4e9e9d 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -449,7 +449,7 @@ namespace UIWidgets { if (changed && !(abs(oldVal - val) < 0.000001f)) { std::stringstream ss; - ss << std::setprecision(ticks) << val; + ss << std::setprecision(ticks + 1) << val; val = std::stof(ss.str()); CVarSetFloat(cvarName, val); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); From f7bd6261621679a2ec9272dd7f5cc3fae20aa806 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 1 Feb 2024 21:15:25 -0500 Subject: [PATCH 037/300] change default value + scale offset by icon size appropriately (#3861) --- soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f24ab818b..2ac5b5c34 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -800,7 +800,7 @@ void DrawItemsInACircle(std::vector items) { float angle = (float)i / items.size() * 2.0f * M_PI; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; - ImGui::SetCursorPos(ImVec2(x - 14, y + 4)); + ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger("gItemTrackerIconSize", 36) - 8) / 2.0f, y + 4)); items[i].drawFunc(items[i]); } } @@ -1167,7 +1167,7 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { - if (UIWidgets::PaddedEnhancementCheckbox("Circle display", "gItemTrackerDungeonRewardsCircle", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (UIWidgets::PaddedEnhancementCheckbox("Circle display", "gItemTrackerDungeonRewardsCircle", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) { shouldUpdateVectors = true; } } From 81eb6de42ee4fbc51d11c17c99b3e62bfb9a8412 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 1 Feb 2024 21:20:35 -0500 Subject: [PATCH 038/300] Audio Editor UI Improvements and Scene Init Randomization (#3388) * Audio Editor UI Improvements and Scene Init Randomization * Update soh/soh/Enhancements/audio/AudioEditor.cpp Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * Update soh/soh/Enhancements/audio/AudioEditor.cpp Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --------- Co-authored-by: Garrett Cox Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- soh/soh/Enhancements/audio/AudioEditor.cpp | 115 ++++++++++++++++++++- soh/soh/Enhancements/audio/AudioEditor.h | 4 +- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index 654446005..8c0d415a3 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -12,6 +12,7 @@ #include #include "../../UIWidgets.hpp" #include "AudioCollection.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" Vec3f pos = { 0.0f, 0.0f, 0.0f }; f32 freqScale = 1.0f; @@ -78,7 +79,12 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) { void RandomizeGroup(SeqType type) { std::vector values; - + + // An empty IncludedSequences set means that the AudioEditor window has never been drawn + if (AudioCollection::Instance->GetIncludedSequences().empty()) { + AudioCollection::Instance->InitializeShufflePool(); + } + // use a while loop to add duplicates if we don't have enough included sequences while (values.size() < AuthenticCountBySequenceType(type)) { for (const auto& seqData : AudioCollection::Instance->GetIncludedSequences()) { @@ -123,6 +129,34 @@ void ResetGroup(const std::map& map, SeqType type) { } } +void LockGroup(const std::map& map, SeqType type) { + for (const auto& [defaultValue, seqData] : map) { + if (seqData.category == type) { + // Only save authentic sequence CVars + if (seqData.category == SEQ_FANFARE && defaultValue >= MAX_AUTHENTIC_SEQID) { + continue; + } + const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey); + const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey); + CVarSetInteger(cvarLockKey.c_str(), 1); + } + } +} + +void UnlockGroup(const std::map& map, SeqType type) { + for (const auto& [defaultValue, seqData] : map) { + if (seqData.category == type) { + // Only save authentic sequence CVars + if (seqData.category == SEQ_FANFARE && defaultValue >= MAX_AUTHENTIC_SEQID) { + continue; + } + const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey); + const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey); + CVarSetInteger(cvarLockKey.c_str(), 0); + } + } +} + void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequenceType) { const std::string cvarKey = AudioCollection::Instance->GetCvarKey(sfxKey); const std::string hiddenKey = "##" + cvarKey; @@ -163,6 +197,8 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { const std::string hiddenTabId = "##" + tabId; const std::string resetAllButton = "Reset All" + hiddenTabId; const std::string randomizeAllButton = "Randomize All" + hiddenTabId; + const std::string lockAllButton = "Lock All" + hiddenTabId; + const std::string unlockAllButton = "Unlock All" + hiddenTabId; if (ImGui::Button(resetAllButton.c_str())) { auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); @@ -184,6 +220,28 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { ReplayCurrentBGM(); } } + ImGui::SameLine(); + if (ImGui::Button(lockAllButton.c_str())) { + auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); + LockGroup(map, type); + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); + if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { + ReplayCurrentBGM(); + } + } + ImGui::SameLine(); + if (ImGui::Button(unlockAllButton.c_str())) { + auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); + auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); + UnlockGroup(map, type); + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); + if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { + ReplayCurrentBGM(); + } + } ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); @@ -350,6 +408,19 @@ void DrawTypeChip(SeqType type) { ImGui::EndDisabled(); } + +void AudioEditorRegisterOnSceneInitHook() { + GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { + if (CVarGetInteger("gAudioEditor.RandomizeAllOnNewScene", 0)) { + AudioEditor_RandomizeAll(); + } + }); +} + +void AudioEditor::InitElement() { + AudioEditorRegisterOnSceneInitHook(); +} + void AudioEditor::DrawElement() { AudioCollection::Instance->InitializeShufflePool(); @@ -359,6 +430,28 @@ void AudioEditor::DrawElement() { return; } + float buttonSegments = ImGui::GetContentRegionAvail().x / 4; + if (ImGui::Button("Randomize All Groups", ImVec2(buttonSegments, 30.0f))) { + AudioEditor_RandomizeAll(); + } + UIWidgets::Tooltip("Randomizes all unlocked music and sound effects across tab groups"); + ImGui::SameLine(); + if (ImGui::Button("Reset All Groups", ImVec2(buttonSegments, 30.0f))) { + AudioEditor_ResetAll(); + } + UIWidgets::Tooltip("Resets all unlocked music and sound effects across tab groups"); + ImGui::SameLine(); + if (ImGui::Button("Lock All Groups", ImVec2(buttonSegments, 30.0f))) { + AudioEditor_LockAll(); + } + UIWidgets::Tooltip("Locks all music and sound effects across tab groups"); + ImGui::SameLine(); + if (ImGui::Button("Unlock All Groups", ImVec2(buttonSegments, 30.0f))) { + AudioEditor_UnlockAll(); + } + UIWidgets::Tooltip("Unlocks all music and sound effects across tab groups"); + + if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Background Music")) { Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD); @@ -431,6 +524,10 @@ void AudioEditor::DrawElement() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } + ImGui::NewLine(); + UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", "gAudioEditor.RandomizeAllOnNewScene"); + UIWidgets::Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene."); + ImGui::NewLine(); ImGui::PushItemWidth(-FLT_MIN); UIWidgets::PaddedSeparator(); @@ -625,3 +722,19 @@ void AudioEditor_ResetAll() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ReplayCurrentBGM(); } + +void AudioEditor_LockAll() { + for (auto type : allTypes) { + LockGroup(AudioCollection::Instance->GetAllSequences(), type); + } + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); +} + +void AudioEditor_UnlockAll() { + for (auto type : allTypes) { + UnlockGroup(AudioCollection::Instance->GetAllSequences(), type); + } + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); +} diff --git a/soh/soh/Enhancements/audio/AudioEditor.h b/soh/soh/Enhancements/audio/AudioEditor.h index 766006ecc..9cca94efe 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.h +++ b/soh/soh/Enhancements/audio/AudioEditor.h @@ -14,13 +14,15 @@ class AudioEditor : public LUS::GuiWindow { using LUS::GuiWindow::GuiWindow; void DrawElement() override; - void InitElement() override {}; + void InitElement() override; void UpdateElement() override {}; ~AudioEditor() {}; }; void AudioEditor_RandomizeAll(); void AudioEditor_ResetAll(); +void AudioEditor_LockAll(); +void AudioEditor_UnlockAll(); extern "C" { #endif From c49908caa6bd1d3eb61385178f79ca37363f4d5b Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 1 Feb 2024 21:30:48 -0500 Subject: [PATCH 039/300] Item Tracker Hookshot/Longshot Identifiers (#3848) * H & L Adds an H and L for Hookshot and Longshot to be able to tell more clearly which one you have. * Added Toggle and Refined Adds a toggle if players don't want it on. Also scales the letter to stay constant with the icons, both size and position. Also now hides the letter if you don't have a hookshot yet. * Clean up some of the comments * prefix --- .../randomizer/randomizer_item_tracker.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 2ac5b5c34..f1841bd50 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -416,7 +416,25 @@ void DrawItemCount(ItemTrackerItem item) { ImVec2 p = ImGui::GetCursorScreenPos(); int32_t trackerNumberDisplayMode = CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); int32_t trackerKeyNumberDisplayMode = CVarGetInteger("gItemTrackerKeyTrack", KEYS_COLLECTED_MAX); + float textScalingFactor = static_cast(iconSize) / 36.0f; + uint32_t actualItemId = INV_CONTENT(item.id); + bool hasItem = actualItemId != ITEM_NONE; + if (CVarGetInteger("gTrackers.ItemTracker.HookshotIdentifier", 0)) { + if ((actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT) && hasItem) { + + // Calculate the scaled position for the text + ImVec2 textPos = ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(item.id == ITEM_HOOKSHOT ? "H" : "L").x * + textScalingFactor / 2) + 8 * textScalingFactor, p.y - 22 * textScalingFactor); + + ImGui::SetCursorScreenPos(textPos); + + ImGui::SetWindowFontScale(textScalingFactor); + + ImGui::Text(item.id == ITEM_HOOKSHOT ? "H" : "L"); + ImGui::SetWindowFontScale(1.0f); // Reset font scale to the original state + } + } if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { std::string currentString = ""; std::string maxString = std::to_string(currentAndMax.maxCapacity); @@ -1200,6 +1218,10 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } } + UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", "gTrackers.ItemTracker.HookshotIdentifier"); + UIWidgets::InsertHelpHoverText("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot."); + + UIWidgets::Spacer(0); ImGui::PopStyleVar(1); ImGui::EndTable(); From ddf039210085297d0ce035637afda169c3ac008d Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 1 Feb 2024 20:43:45 -0600 Subject: [PATCH 040/300] Add gShowDoorLocksOnBothSides (#3787) * Add gShowDoorLocksOnBothSides * Update soh/src/overlays/actors/ovl_En_Door/z_en_door.c --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- soh/soh/SohMenuBar.cpp | 1 + soh/src/overlays/actors/ovl_En_Door/z_en_door.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c0aae7a5e..a10eb6201 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1103,6 +1103,7 @@ void DrawEnhancementsMenu() { PatchToTMedallions(); } UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored"); + UIWidgets::PaddedEnhancementCheckbox("Show locked door chains on both sides of locked doors", "gShowDoorLocksOnBothSides", true, false); UIWidgets::PaddedText("Fix Vanishing Paths", true, false); if (UIWidgets::EnhancementCombobox("gSceneSpecificDirtPathFix", zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) { UpdateDirtPathFixState(gPlayState->sceneNum); diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c index f0442821a..329462c06 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c @@ -349,7 +349,15 @@ void EnDoor_Draw(Actor* thisx, PlayState* play) { } } if (this->lockTimer != 0) { + if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) { + Matrix_Push(); + } Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); + if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) { + Matrix_Pop(); + Matrix_RotateZYX(0, 0x8000, 0, MTXMODE_APPLY); + Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); + } } CLOSE_DISPS(play->state.gfxCtx); From 351a511dc7bca645c7e7e92c4a020466ddf050d0 Mon Sep 17 00:00:00 2001 From: skyyoshi86 <105878730+skyyoshi86@users.noreply.github.com> Date: Thu, 1 Feb 2024 19:44:16 -0700 Subject: [PATCH 041/300] Cosmetics Editor entry for Ivan the Fairy (#3718) * First commit * Reverted MODDING.md Reverted a correction to MODDING.md (case-sensitive broken link?) as this is not a change related to this PR * Delete CMakeSettings.json Deleted CMakeSettings.json as this is not a change related to this PR. * checks for cosmetic changes ONCE for both body and sparles Please review carefully. I made these changes blindly as I figure out why I can't compile it in my machine anymore. Sorry! * correctly updates OUTER color when it's changed in Cosmetics Editor * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * Update soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c --------- Co-authored-by: Garrett Cox Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- docs/MODDING.md | 2 +- .../cosmetics/CosmeticsEditor.cpp | 8 +++++++ .../actors/ovl_En_Partner/z_en_partner.c | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/MODDING.md b/docs/MODDING.md index ebd7cf071..75293b64a 100644 --- a/docs/MODDING.md +++ b/docs/MODDING.md @@ -188,4 +188,4 @@ Assuming all went well, you can now push your changes to your fork with the foll ```bash git push origin -``` \ No newline at end of file +``` diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 6c1e007fa..240bf5894 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -76,6 +76,7 @@ typedef enum { GROUP_SPIN_ATTACK, GROUP_TRAILS, GROUP_NAVI, + GROUP_IVAN, } CosmeticGroup; std::map groupLabels = { @@ -95,6 +96,7 @@ std::map groupLabels = { { GROUP_SPIN_ATTACK, "Spin Attack" }, { GROUP_TRAILS, "Trails" }, { GROUP_NAVI, "Navi" }, + { GROUP_IVAN, "Ivan" } }; typedef struct { @@ -350,6 +352,9 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Navi_EnemySecondary", "Enemy Secondary", GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + + COSMETIC_OPTION("Ivan_IdlePrimary", "Ivan Idle Primary", GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Ivan_IdleSecondary", "Ivan Idle Secondary", GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), @@ -1660,6 +1665,8 @@ void RandomizeColor(CosmeticOption& cosmeticOption) { CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_NPCSecondary"), 1.0f); } else if (cosmeticOption.label == "Props Primary") { CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_PropsSecondary"), 1.0f); + } else if (cosmeticOption.label == "Ivan Idle Primary") { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Ivan_IdleSecondary"), 0.5f); } else if (cosmeticOption.label == "Level 1 Secondary") { CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f); } else if (cosmeticOption.label == "Level 2 Secondary") { @@ -1892,6 +1899,7 @@ void CosmeticsEditorWindow::DrawElement() { if (ImGui::BeginTabItem("World & NPCs")) { DrawCosmeticGroup(GROUP_WORLD); DrawCosmeticGroup(GROUP_NAVI); + DrawCosmeticGroup(GROUP_IVAN); DrawCosmeticGroup(GROUP_NPC); ImGui::EndTabItem(); } diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index 51e3e1499..6a001d07b 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -745,6 +745,28 @@ void EnPartner_Update(Actor* thisx, PlayState* play) { CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); } + if (CVarGetInteger("gCosmetics.Ivan_IdlePrimary.Changed", 0)) { + Color_RGB8 ivanColor1 = CVarGetColor24("gCosmetics.Ivan_IdlePrimary.Value", (Color_RGB8){ 255, 255, 255 }); + this->innerColor.r = ivanColor1.r; + this->innerColor.g = ivanColor1.g; + this->innerColor.b = ivanColor1.b; + } else { + this->innerColor.r = 255; + this->innerColor.g = 255; + this->innerColor.b = 255; + } + + if (CVarGetInteger("gCosmetics.Ivan_IdleSecondary.Changed", 0)) { + Color_RGB8 ivanColor2 = CVarGetColor24("gCosmetics.Ivan_IdleSecondary.Value", (Color_RGB8){ 0, 255, 0 }); + this->outerColor.r = ivanColor2.r; + this->outerColor.g = ivanColor2.g; + this->outerColor.b = ivanColor2.b; + } else { + this->outerColor.r = 0; + this->outerColor.g = 255; + this->outerColor.b = 0; + } + SkelAnime_Update(&this->skelAnime); EnPartner_UpdateLights(this, play); From a6457599f9dc16455d26cb1e701a8651c98da488 Mon Sep 17 00:00:00 2001 From: "Tina H. (sheepytina)" <99330992+sheepytina@users.noreply.github.com> Date: Fri, 2 Feb 2024 13:52:53 +1100 Subject: [PATCH 042/300] Clarify descriptions of Graphics Settings (#3881) * Rewrite tooltips: Internal Resolution, Anti-Aliasing. + Tweak others. * MSAA slider will display 1x as Off. * Rename setting and tweak tooltips: FPS (to Framerate) + Code style formatting. * Add tooltip: Texture Filtering. + Small tooltip changes. + Tidy up comments/newlines. * Add internal resolution advisory for Apple users. (Because this setting being missing keeps getting reported as a bug.) * Small text tweaks. * Code review suggestion Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> * Missed one of the buttons + correct spelling of "frame rate" --------- Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> --- soh/soh/SohMenuBar.cpp | 75 ++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index a10eb6201..bba1a902e 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -273,8 +273,10 @@ void DrawSettingsMenu() { 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); } - UIWidgets::Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); - #endif + UIWidgets::Tooltip("Resolution scale. Multiplies output resolution by this value, on each axis relative to window size.\n" + "Lower values may improve performance.\n" + "Values above 100% can be used for super-sampling, as an intensive but highly effective form of anti-aliasing.\n\n" + "Default: 100%"); if (mAdvancedResolutionSettingsWindow) { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); @@ -288,14 +290,28 @@ void DrawSettingsMenu() { ImGui::PopStyleColor(1); ImGui::PopStyleVar(3); } - - #ifndef __WIIU__ - if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { - LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); - }; - UIWidgets::Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); + #else + // macOS: Internal resolution is currently disabled in libultraship. + ImGui::BeginGroup(); + ImGui::Text("Internal Resolution: 100.0%%"); + UIWidgets::Spacer(0); + ImGui::Text(" " ICON_FA_INFO_CIRCLE " Not available on this system."); + UIWidgets::Spacer(0); + ImGui::EndGroup(); #endif + #ifndef __WIIU__ + if (UIWidgets::PaddedEnhancementSliderInt( + (CVarGetInteger("gMSAAValue", 1) == 1) ? "Anti-aliasing (MSAA): Off" : "Anti-aliasing (MSAA): %d", + "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { + LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); + } + UIWidgets::Tooltip("Activates MSAA (multi-sample anti-aliasing) from 2x up to 8x, to smooth the edges of rendered geometry.\n" + "Higher sample count will result in smoother edges on models, but may reduce performance.\n\n" + "Recommended: 2x or 4x"); + #endif + + UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); { // FPS Slider const int minFps = 20; static int maxFps; @@ -369,26 +385,27 @@ void DrawSettingsMenu() { bool matchingRefreshRate = CVarGetInteger("gMatchRefreshRate", 0) && LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() != LUS::WindowBackend::DX11; UIWidgets::PaddedEnhancementSliderInt( - (currentFps == 20) ? "FPS: Original (20)" : "FPS: %d", + (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps", "##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); #endif if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { UIWidgets::Tooltip( - "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely " - "visual and does not impact game logic, execution of glitches etc.\n\n" - "A higher target FPS than your monitor's refresh rate will waste resources, and might give a worse result." - ); + "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n" + "This is purely visual and does not impact game logic, execution of glitches etc.\n" + "Higher frame rate settings may impact CPU performance." + "\n\n " ICON_FA_INFO_CIRCLE + " There is no need to set this above your monitor's refresh rate. Doing so will waste resources and may give a worse result."); } else { UIWidgets::Tooltip( - "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is purely " - "visual and does not impact game logic, execution of glitches etc." - ); + "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n" + "This is purely visual and does not impact game logic, execution of glitches etc.\n" + "Higher frame rate settings may impact CPU performance."); } } // END FPS Slider if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { UIWidgets::Spacer(0); - if (ImGui::Button("Match Refresh Rate")) { + if (ImGui::Button("Match Frame Rate to Refresh Rate")) { int hz = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); if (hz >= 20 && hz <= 360) { CVarSetInteger("gInterpolationFPS", hz); @@ -396,17 +413,22 @@ void DrawSettingsMenu() { } } } else { - UIWidgets::PaddedEnhancementCheckbox("Match Refresh Rate", "gMatchRefreshRate", true, false); + UIWidgets::PaddedEnhancementCheckbox("Match Frame Rate to Refresh Rate", "gMatchRefreshRate", true, false); } - UIWidgets::Tooltip("Matches interpolation value to the current game's window refresh rate"); + UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate."); if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", "##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false); - UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); + UIWidgets::Tooltip( + "(For DirectX backend only)\n\n" + "When Interpolation FPS (Frame Rate) setting is at least this threshold, add one frame of delay (e.g. 16.6 ms for 60 FPS) in order to avoid jitter." + "This setting allows the CPU to work on one frame while GPU works on the previous frame.\n" + "This setting should be used when your computer is too slow to do CPU + GPU work in time."); } UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); + ImGui::Text("ImGui Menu Scale"); ImGui::SameLine(); ImGui::TextColored({ 0.85f, 0.35f, 0.0f, 1.0f }, "(Experimental)"); @@ -455,6 +477,7 @@ void DrawSettingsMenu() { if (LUS::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) { UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false); + UIWidgets::Tooltip("Activate vertical sync, to prevent screen tearing."); } if (LUS::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) { @@ -462,17 +485,21 @@ void DrawSettingsMenu() { } if (LUS::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) { - UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows (Needs reload)", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect."); } // If more filters are added to LUS, make sure to add them to the filters list here - ImGui::Text("Texture Filter (Needs reload)"); - + ImGui::Text("Texture Filtering (Needs reload)"); UIWidgets::EnhancementCombobox("gTextureFilter", filters, FILTER_THREE_POINT); + UIWidgets::Tooltip("Texture filtering, aka texture smoothing. Requires a reload to take effect.\n\n" + "Three-Point: Replicates real N64 texture filtering.\n" + "Bilinear: If Three-Point causes poor performance, try this.\n" + "Nearest: Disables texture smoothing. (Not recommended)"); - UIWidgets::Spacer(0); + UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); + // Draw LUS settings menu (such as Overlays Text Font) LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings(); ImGui::EndMenu(); From 775d3e68b7eb8fa1272d081055e8e0266c2c57be Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:11:49 -0500 Subject: [PATCH 043/300] [Graphics] Show Equipment Regardless of Age (#3830) * Hookshot, Hammer, & Boomerang * Added the remainder of equipment and DL Patching for hands * Removed Mirror Shield Patch Messed with the front texture of shield * Child Hylian Shield Cheat Adds a cheat that allows Child Link to hold Hylian Shield as adult. Added to this since it uses the same way to render the shield * Debugging * Adds Scaling to Child Link with Adult Equipment * Fix Merge Conflict Blunders * More cleanup * Added Scaling checkbox and some clean up * Added an || ITEM_NONE * More cleanup and simplification * Accidently added spacer * Replace B_BTN_ITEM * Spacing Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> * Added most sheath functionality * Updated tooltips * removed child hylian shield and tweaked bow/slingshot Made child hylian shield cheat into a separate branch and hooked into existing bow/slingshot enhancement for drawing those * Prefixes * () --------- Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Co-authored-by: Garrett Cox --- soh/soh/Enhancements/mods.cpp | 51 ++++++++ soh/soh/Enhancements/mods.h | 1 + soh/soh/SohMenuBar.cpp | 9 ++ soh/src/code/z_player_lib.c | 111 ++++++++++++++++-- .../actors/ovl_player_actor/z_player.c | 6 +- 5 files changed, 168 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index c1561aa42..f829d767f 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -23,6 +23,8 @@ #include "src/overlays/actors/ovl_En_Tp/z_en_tp.h" #include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h" #include "src/overlays/actors/ovl_En_Xc/z_en_xc.h" +#include "objects/object_link_boy/object_link_boy.h" +#include "objects/object_link_child/object_link_child.h" extern "C" { #include @@ -687,6 +689,54 @@ void RegisterMirrorModeHandler() { }); } +void UpdatePatchHand() { + if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_CHILD) { + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList()); + ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList()); + ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList()); + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList()); + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList()); + ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); + ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList()); + + } else { + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2"); + ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2"); + ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2"); + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2"); + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2"); + ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1"); + ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2"); + } + if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_ADULT) { + ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); + ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); + ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); + ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); + } else { + ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword"); + ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot"); + ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang"); + ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield"); + } +} + +void RegisterPatchHandHandler() { + GameInteractor::Instance->RegisterGameHook([](int32_t sceneNum) { + UpdatePatchHand(); + }); +} + void RegisterResetNaviTimer() { GameInteractor::Instance->RegisterGameHook([](int32_t sceneNum) { if (CVarGetInteger("gEnhancements.ResetNaviTimer", 0)) { @@ -1288,5 +1338,6 @@ void InitMods() { RegisterRandomizedEnemySizes(); RegisterToTMedallions(); NameTag_RegisterHooks(); + RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); } diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index 43a41449c..57ebedfd9 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -13,6 +13,7 @@ void UpdateHurtContainerModeState(bool newState); void PatchToTMedallions(); void UpdatePermanentHeartLossState(); void InitMods(); +void UpdatePatchHand(); #ifdef __cplusplus } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index bba1a902e..f96320bc2 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1112,6 +1112,15 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); } + if (UIWidgets::PaddedEnhancementCheckbox("Show Age-Dependent Equipment", "gEnhancements.EquimentAlwaysVisible", true, + false)) { + UpdatePatchHand(); + } + UIWidgets::Tooltip("Makes all equipment visible, regardless of Age."); + if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", "gEnhancements.ScaleAdultEquimentAsChild", true, false); + UIWidgets::Tooltip("Scales all of the Adult Equipment, as well and moving some a bit, to fit on Child Link Better. May not work properly with some mods."); + } UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index e20362fd3..3edaaca5b 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -600,13 +600,23 @@ void Player_SetModelsForHoldingShield(Player* this) { if ((CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD; - this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][gSaveContext.linkAge]; + if (LINK_IS_CHILD && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) { + this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][0]; + } else if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_DEKU)) { + this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][1]; + } else { + this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][gSaveContext.linkAge]; + } if (this->sheathType == PLAYER_MODELTYPE_SHEATH_18) { this->sheathType = PLAYER_MODELTYPE_SHEATH_16; } else if (this->sheathType == PLAYER_MODELTYPE_SHEATH_19) { this->sheathType = PLAYER_MODELTYPE_SHEATH_17; } this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; + if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_CHILD && + gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI) { + this->sheathDLists = &sPlayerDListGroups[this->sheathType][0]; + } this->modelAnimType = PLAYER_ANIMTYPE_2; this->itemAction = -1; } @@ -617,12 +627,40 @@ void Player_SetModels(Player* this, s32 modelGroup) { // Left hand this->leftHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND]; this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][gSaveContext.linkAge]; - + + if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (LINK_IS_CHILD && + (this->leftHandType == PLAYER_MODELTYPE_LH_HAMMER || + ((this->leftHandType == PLAYER_MODELTYPE_LH_SWORD || this->leftHandType == PLAYER_MODELTYPE_LH_BGS) && + (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)))) { + this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][0]; + } + + if (LINK_IS_ADULT && (this->leftHandType == PLAYER_MODELTYPE_LH_BOOMERANG || + (this->leftHandType == PLAYER_MODELTYPE_LH_SWORD && gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KOKIRI))) { + this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][1]; + } + } + // Right hand this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND]; this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge]; - if (CVarGetInteger("gBowSlingShotAmmoFix", 0) && this->rightHandType == 11) { // If holding Bow/Slingshot + this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND]; + this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge]; + + if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (LINK_IS_CHILD && + (this->rightHandType == PLAYER_MODELTYPE_RH_HOOKSHOT || + (this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD && this->currentShield == PLAYER_SHIELD_MIRROR))) { + this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][0]; + } + if (LINK_IS_ADULT && + (this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD && this->currentShield == PLAYER_SHIELD_DEKU)) { + this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][1]; + } + } + if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && this->rightHandType == 11) { // If holding Bow/Slingshot this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][Player_HoldsSlingshot(this)]; } @@ -630,6 +668,23 @@ void Player_SetModels(Player* this, s32 modelGroup) { this->sheathType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_SHEATH]; this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; + if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (LINK_IS_CHILD && + (this->currentShield == PLAYER_SHIELD_HYLIAN || this->currentShield == PLAYER_SHIELD_MIRROR) && + ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER) || + (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) { + this->sheathDLists = &sPlayerDListGroups[this->sheathType][0]; + } else if (LINK_IS_CHILD && this->currentShield == PLAYER_SHIELD_MIRROR && gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KOKIRI && + this->sheathType == PLAYER_MODELTYPE_SHEATH_18) { + this->sheathDLists = &sPlayerDListGroups[this->sheathType][0]; + } else if (LINK_IS_ADULT && this->currentShield == PLAYER_SHIELD_DEKU) { + this->sheathDLists = &sPlayerDListGroups[this->sheathType][1]; + } else if (LINK_IS_CHILD && this->sheathType == PLAYER_MODELTYPE_SHEATH_17 && + ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER) || (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) { + this->sheathDLists = &sPlayerDListGroups[this->sheathType][0]; + } + } + // Waist this->waistDLists = &sPlayerDListGroups[gPlayerModelTypes[modelGroup][4]][gSaveContext.linkAge]; @@ -1187,6 +1242,42 @@ void func_8008F87C(PlayState* play, Player* this, SkelAnime* skelAnime, Vec3f* p s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { Player* this = (Player*)thisx; + + if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) && CVarGetInteger("gEnhancements.ScaleAdultEquimentAsChild", 0) && LINK_IS_CHILD) { + if (limbIndex == PLAYER_LIMB_L_HAND) { + if ((gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && sLeftHandType == PLAYER_MODELTYPE_LH_SWORD) || + (sLeftHandType == PLAYER_MODELTYPE_LH_BGS) || (sLeftHandType == PLAYER_MODELTYPE_LH_HAMMER)) { + Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY); + } + } + if (limbIndex == PLAYER_LIMB_R_HAND) { + if ((this->currentShield == PLAYER_SHIELD_MIRROR && sRightHandType == PLAYER_MODELTYPE_RH_SHIELD) || + (this->currentShield == PLAYER_SHIELD_HYLIAN && (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER || + gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS)) || (sRightHandType == PLAYER_MODELTYPE_RH_HOOKSHOT) || + (sRightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT && Player_HoldsBow(this))) { + Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY); + } + } + if (limbIndex == PLAYER_LIMB_SHEATH) { + if ((this->currentShield == PLAYER_SHIELD_MIRROR || + (this->currentShield == PLAYER_SHIELD_HYLIAN && + (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER || + gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS))) && + ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17) || + (this->sheathType == PLAYER_MODELTYPE_SHEATH_18) || + (this->sheathType == PLAYER_MODELTYPE_SHEATH_19))) { + Matrix_Translate(218, -100, 62, MTXMODE_APPLY); + Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY); + } + if ((this->currentShield == PLAYER_SHIELD_DEKU && + gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && + (this->sheathType == PLAYER_MODELTYPE_SHEATH_16 || + this->sheathType == PLAYER_MODELTYPE_SHEATH_17))) { + Matrix_Translate(218, -100, 62, MTXMODE_APPLY); + Matrix_Scale(0.8, 0.8, 0.8, MTXMODE_APPLY); + } + } + } if (limbIndex == PLAYER_LIMB_ROOT) { sLeftHandType = this->leftHandType; @@ -1305,9 +1396,11 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { dLists += PLAYER_SHIELD_MAX * 4; } - } else if (!LINK_IS_ADULT && ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17)) && - (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { - dLists = &sSheathWithSwordDLs[PLAYER_SHIELD_MAX * 4]; + } else if (!CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (!LINK_IS_ADULT && ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17)) && + (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { + dLists = &sSheathWithSwordDLs[PLAYER_SHIELD_MAX * 4]; + } } if (dLists[sDListsLodOffset] != NULL) { @@ -1345,7 +1438,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G *dList = sFirstPersonLeftForearmDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_L_HAND) { s32 handOutDlIndex = gSaveContext.linkAge; - if (CVarGetInteger("gBowSlingShotAmmoFix", 0) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) { + if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) { handOutDlIndex = 1; } *dList = sFirstPersonLeftHandDLs[handOutDlIndex]; @@ -1355,7 +1448,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G *dList = sFirstPersonForearmDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_R_HAND) { s32 firstPersonWeaponIndex = gSaveContext.linkAge; - if (CVarGetInteger("gBowSlingShotAmmoFix", 0)) { + if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { if (Player_HoldsBow(this)) { firstPersonWeaponIndex = 0; } else if (Player_HoldsSlingshot(this)) { @@ -1755,7 +1848,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve Matrix_Get(&this->shieldMf); } else if ((this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT) || (this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT_2)) { s32 stringModelToUse = gSaveContext.linkAge; - if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ + if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { stringModelToUse = Player_HoldsSlingshot(this); } BowStringData* stringData = &sBowStringData[stringModelToUse]; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 0577add9e..145abcdd0 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2911,7 +2911,11 @@ s32 func_808356E8(Player* this, PlayState* play) { } void func_808357E8(Player* this, Gfx** dLists) { - this->leftHandDLists = &dLists[gSaveContext.linkAge]; + if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0))) { + this->leftHandDLists = &dLists[1]; + } else { + this->leftHandDLists = &dLists[gSaveContext.linkAge]; + } } s32 func_80835800(Player* this, PlayState* play) { From 961b2626adc861a9a4aff833a341634ca3f8d557 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 2 Feb 2024 05:10:46 +0100 Subject: [PATCH 044/300] Merge controller menus (#3860) * Merge controller menus * Re-run Build * Update SohInputEditorWindow.h * Update soh/soh/Enhancements/controls/SohInputEditorWindow.cpp Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * pin switch devkit docker image --------- Co-authored-by: Garrett Cox Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- .github/workflows/generate-builds.yml | 2 +- .../controls/GameControlEditor.cpp | 361 ------------------ .../Enhancements/controls/GameControlEditor.h | 21 - .../controls/SohInputEditorWindow.cpp | 345 ++++++++++++++++- .../controls/SohInputEditorWindow.h | 22 +- soh/soh/OTRGlobals.cpp | 1 - soh/soh/SohGui.cpp | 4 - soh/soh/SohGui.hpp | 1 - soh/soh/SohMenuBar.cpp | 7 - 9 files changed, 351 insertions(+), 413 deletions(-) delete mode 100644 soh/soh/Enhancements/controls/GameControlEditor.cpp delete mode 100644 soh/soh/Enhancements/controls/GameControlEditor.h diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index c54d017a2..0a3cc4f0e 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -180,7 +180,7 @@ jobs: needs: generate-soh-otr runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} container: - image: devkitpro/devkita64:latest + image: devkitpro/devkita64:20240120 steps: - name: Install dependencies run: | diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp deleted file mode 100644 index eaf18052c..000000000 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include "GameControlEditor.h" - -#include -#include -#include -#include -#include -#include - -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif -#include -#include -#include -#include -#include -#include - -#include "macros.h" - -#include "../../UIWidgets.hpp" - -namespace GameControlEditor { - const ImGuiTableFlags PANEL_TABLE_FLAGS = - ImGuiTableFlags_BordersH | - ImGuiTableFlags_BordersV; - const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS = - ImGuiTableColumnFlags_IndentEnable | - ImGuiTableColumnFlags_NoSort; - - namespace TableHelper { - void InitHeader(bool has_header = true) { - if (has_header) { - ImGui::TableHeadersRow(); - } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized. - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - } - - void NextCol() { - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - } - - void NextLine() { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - } - } - - void DrawHelpIcon(const std::string& helptext) { - // place the ? button to the most of the right side of the cell it is using. - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); - ImGui::SmallButton("?"); - UIWidgets::Tooltip(helptext.c_str()); - } - - typedef uint32_t N64ButtonMask; - - // Used together for an incomplete linked hash map implementation in order to - // map button masks to their names and original mapping on N64 - static std::list> buttons; - static std::unordered_map buttonNames; - - void addButtonName(N64ButtonMask mask, const char* name) { - buttons.push_back(std::make_pair(mask, name)); - buttonNames[mask] = std::prev(buttons.end()); - } - - typedef struct { - const char* label; - const char* cVarName; - N64ButtonMask defaultBtn; - } CustomButtonMap; - - // Ocarina button maps - static CustomButtonMap ocarinaD5 = {"D5", "gOcarinaD5BtnMap", BTN_CUP}; - static CustomButtonMap ocarinaB4 = {"B4", "gOcarinaB4BtnMap", BTN_CLEFT}; - static CustomButtonMap ocarinaA4 = {"A4", "gOcarinaA4BtnMap", BTN_CRIGHT}; - static CustomButtonMap ocarinaF4 = {"F4", "gOcarinaF4BtnMap", BTN_CDOWN}; - static CustomButtonMap ocarinaD4 = {"D4", "gOcarinaD4BtnMap", BTN_A}; - static CustomButtonMap ocarinaSongDisable = {"Disable songs", "gOcarinaDisableBtnMap", BTN_L}; - static CustomButtonMap ocarinaSharp = {"Pitch up", "gOcarinaSharpBtnMap", BTN_R}; - static CustomButtonMap ocarinaFlat = {"Pitch down", "gOcarinaFlatBtnMap", BTN_Z}; - - void GameControlEditorWindow::InitElement() { - addButtonName(BTN_A, "A"); - addButtonName(BTN_B, "B"); - addButtonName(BTN_CUP, "C Up"); - addButtonName(BTN_CDOWN, "C Down"); - addButtonName(BTN_CLEFT, "C Left"); - addButtonName(BTN_CRIGHT, "C Right"); - addButtonName(BTN_L, "L"); - addButtonName(BTN_Z, "Z"); - addButtonName(BTN_R, "R"); - addButtonName(BTN_START, "Start"); - addButtonName(BTN_DUP, "D-pad up"); - addButtonName(BTN_DDOWN, "D-pad down"); - addButtonName(BTN_DLEFT, "D-pad left"); - addButtonName(BTN_DRIGHT, "D-pad right"); - addButtonName(0, "None"); - } - - // Draw a button mapping setting consisting of a padded label and button dropdown. - // excludedButtons indicates which buttons are unavailable to choose from. - void DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons) { - N64ButtonMask currentButton = CVarGetInteger(mapping.cVarName, mapping.defaultBtn); - - const char* preview; - if (buttonNames.contains(currentButton)) { - preview = buttonNames[currentButton]->second; - } else { - preview = "Unknown"; - } - - UIWidgets::Spacer(0); - ImVec2 cursorPos = ImGui::GetCursorPos(); - ImVec2 textSize = ImGui::CalcTextSize(mapping.label); - ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4); - ImGui::SetCursorPosX(cursorPos.x + abs(textSize.x - labelWidth)); - ImGui::Text("%s", mapping.label); - ImGui::SameLine(); - ImGui::SetCursorPosY(cursorPos.y); - - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); - if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) { - for (auto i = buttons.begin(); i != buttons.end(); i++) { - if ((i->first & excludedButtons) != 0) { - continue; - } - if (ImGui::Selectable(i->second, i->first == currentButton)) { - CVarSetInteger(mapping.cVarName, i->first); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - } - ImGui::EndCombo(); - } - UIWidgets::Spacer(0); - } - - void DrawOcarinaControlPanel(GameControlEditorWindow* window) { - if (!ImGui::CollapsingHeader("Ocarina Controls")) { - return; - } - - if (!ImGui::BeginTable("tableCustomOcarinaControls", 1, PANEL_TABLE_FLAGS)) { - return; - } - - ImGui::TableSetupColumn("Custom Ocarina Controls", PANEL_TABLE_COLUMN_FLAGS | ImGuiTableColumnFlags_WidthStretch); - TableHelper::InitHeader(false); - - ImVec2 cursor = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); - - if (CVarGetInteger("gCustomOcarinaControls", 0) == 1) { - if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { - float labelWidth; - N64ButtonMask disableMask = BTN_B; - if (CVarGetInteger("gDpadOcarina", 0)) { - disableMask |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; - } - - ImGui::TableSetupColumn("Notes##CustomOcarinaNotes", PANEL_TABLE_COLUMN_FLAGS); - ImGui::TableSetupColumn("Modifiers##CustomOcaranaModifiers", PANEL_TABLE_COLUMN_FLAGS); - TableHelper::InitHeader(false); - - window->BeginGroupPanelPublic("Notes", ImGui::GetContentRegionAvail()); - labelWidth = ImGui::CalcTextSize("D5").x + 10; - DrawMapping(ocarinaD5, labelWidth, disableMask); - DrawMapping(ocarinaB4, labelWidth, disableMask); - DrawMapping(ocarinaA4, labelWidth, disableMask); - DrawMapping(ocarinaF4, labelWidth, disableMask); - DrawMapping(ocarinaD4, labelWidth, disableMask); - ImGui::Dummy(ImVec2(0, 5)); - float cursorY = ImGui::GetCursorPosY(); - window->EndGroupPanelPublic(0); - - TableHelper::NextCol(); - - window->BeginGroupPanelPublic("Modifiers", ImGui::GetContentRegionAvail()); - labelWidth = ImGui::CalcTextSize(ocarinaSongDisable.label).x + 10; - DrawMapping(ocarinaSongDisable, labelWidth, disableMask); - DrawMapping(ocarinaSharp, labelWidth, disableMask); - DrawMapping(ocarinaFlat, labelWidth, disableMask); - window->EndGroupPanelPublic(cursorY - ImGui::GetCursorPosY() + 2); - - ImGui::EndTable(); - } - } else { - UIWidgets::Spacer(0); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox."); - UIWidgets::Spacer(0); - } - - window->BeginGroupPanelPublic("Alternate controls", ImGui::GetContentRegionAvail()); - if (ImGui::BeginTable("tableOcarinaAlternateControls", 2, ImGuiTableFlags_SizingFixedSame)) { - ImGui::TableSetupColumn("D-pad", PANEL_TABLE_COLUMN_FLAGS); - ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); - TableHelper::InitHeader(false); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); - TableHelper::NextCol(); - UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); - UIWidgets::Spacer(0); - ImGui::EndTable(); - } - window->EndGroupPanelPublic(0); - - ImGui::EndTable(); - } - - void DrawCameraControlPanel(GameControlEditorWindow* window) { - if (!ImGui::CollapsingHeader("Camera Controls")) { - return; - } - - UIWidgets::Spacer(0); - window->BeginGroupPanelPublic("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); - DrawHelpIcon("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"); - if (CVarGetInteger("gRightStickAiming", 0)) { - UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", "gMoveWhileFirstPerson"); - DrawHelpIcon("Changes the left stick to move the player while in first person mode"); - } - UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis"); - DrawHelpIcon("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", "gInvertAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", "gInvertShieldAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Inverts the Shield Aiming Y Axis"); - UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis"); - DrawHelpIcon("Inverts the Shield Aiming X Axis"); - UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson"); - DrawHelpIcon("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); - if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false)) { - if (!CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { - CVarClear("gFirstPersonCameraSensitivityX"); - CVarClear("gFirstPersonCameraSensitivityY"); - } - } - if (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { - UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal", - "gFirstPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true); - UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical", - "gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true); - } - UIWidgets::Spacer(0); - window->EndGroupPanelPublic(0); - - UIWidgets::Spacer(0); - window->BeginGroupPanelPublic("Third-Person Camera", ImGui::GetContentRegionAvail()); - - UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera"); - DrawHelpIcon("Enables free camera control\nNote: You must remap C buttons off of the right stick in the " - "controller config menu, and map the camera stick to the right stick."); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); - DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera"); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera"); - UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal", - "gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical", - "gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist", - "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed", - "gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true); - window->EndGroupPanelPublic(0); - } - - void DrawDpadControlPanel(GameControlEditorWindow* window) { - if (!ImGui::CollapsingHeader("D-Pad Controls")) { - return; - } - - ImVec2 cursor = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - window->BeginGroupPanelPublic("D-Pad Options", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause"); - DrawHelpIcon("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n" - "To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0"); - UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText"); - DrawHelpIcon("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n" - "To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0"); - UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); - DrawHelpIcon("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate"); - window->EndGroupPanelPublic(0); - } - - void DrawMiscControlPanel(GameControlEditorWindow* window) { - if (!ImGui::CollapsingHeader("Miscellaneous Controls")) { - return; - } - - ImVec2 cursor = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - window->BeginGroupPanelPublic("Misc Controls", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedText("Allow the cursor to be on any slot"); - static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" }; - UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY); - DrawHelpIcon("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select " - "certain items."); - UIWidgets::Spacer(0); - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); - UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); - DrawHelpIcon("Hold the assigned button to change the maximum walking or swimming speed\nTo change the assigned button, go into the Ports tabs above"); - if (CVarGetInteger("gEnableWalkModify", 0)) { - UIWidgets::Spacer(5); - window->BeginGroupPanelPublic("Speed Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); - window->BeginGroupPanelPublic("Walk Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); - UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - window->EndGroupPanelPublic(0); - window->BeginGroupPanelPublic("Swim Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - window->EndGroupPanelPublic(0); - window->EndGroupPanelPublic(0); - } - ImGui::EndDisabled(); - UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL"); - DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up"); - window->EndGroupPanelPublic(0); - } - - - void GameControlEditorWindow::DrawElement() { - ImGui::SetNextWindowSize(ImVec2(465, 430), ImGuiCond_FirstUseEver); - if (ImGui::Begin("Game Controls Configuration", &mIsVisible)) { - DrawOcarinaControlPanel(this); - DrawCameraControlPanel(this); - DrawDpadControlPanel(this); - DrawMiscControlPanel(this); - } - ImGui::End(); - } - - void GameControlEditorWindow::BeginGroupPanelPublic(const char* name, const ImVec2& size) { - BeginGroupPanel(name, size); - } - - void GameControlEditorWindow::EndGroupPanelPublic(float minHeight) { - EndGroupPanel(minHeight); - } -} diff --git a/soh/soh/Enhancements/controls/GameControlEditor.h b/soh/soh/Enhancements/controls/GameControlEditor.h deleted file mode 100644 index 7cf306741..000000000 --- a/soh/soh/Enhancements/controls/GameControlEditor.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -namespace GameControlEditor { -class GameControlEditorWindow : public LUS::GuiWindow { - public: - using LUS::GuiWindow::GuiWindow; - - void BeginGroupPanelPublic(const char* name, const ImVec2& size); - void EndGroupPanelPublic(float minHeight); - - void InitElement() override; - void DrawElement() override; - void UpdateElement() override {}; -}; - -static int CurrentPort = 0; -static int BtnReading = -1; - -} // namespace GameControlEditor diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index a5ecc39dc..a1290c238 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -22,6 +22,22 @@ void SohInputEditorWindow::InitElement() { mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT }; mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; mModifierButtonsBitmasks = { BTN_MODIFIER1, BTN_MODIFIER2 }; + + addButtonName(BTN_A, "A"); + addButtonName(BTN_B, "B"); + addButtonName(BTN_CUP, "C Up"); + addButtonName(BTN_CDOWN, "C Down"); + addButtonName(BTN_CLEFT, "C Left"); + addButtonName(BTN_CRIGHT, "C Right"); + addButtonName(BTN_L, "L"); + addButtonName(BTN_Z, "Z"); + addButtonName(BTN_R, "R"); + addButtonName(BTN_START, "Start"); + addButtonName(BTN_DUP, "D-pad up"); + addButtonName(BTN_DDOWN, "D-pad down"); + addButtonName(BTN_DLEFT, "D-pad left"); + addButtonName(BTN_DRIGHT, "D-pad right"); + addButtonName(0, "None"); } #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 @@ -1017,14 +1033,6 @@ void SohInputEditorWindow::DrawAddLEDMappingButton(uint8_t port) { } } -void SohInputEditorWindow::DrawHelpIcon(const std::string& helptext) { - // place the ? button to the most of the right side of the cell it is using. - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - SCALE_IMGUI_SIZE(22)); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - SCALE_IMGUI_SIZE(15)); - ImGui::SmallButton("?"); - UIWidgets::Tooltip(helptext.c_str()); -} - void SohInputEditorWindow::DrawLEDSection(uint8_t port) { for (auto [id, mapping] : LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) { @@ -1063,11 +1071,11 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { }; UIWidgets::PaddedText("Source"); UIWidgets::EnhancementCombobox("gLedColorSource", ledSources, LED_SOURCE_TUNIC_ORIGINAL); - DrawHelpIcon("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " - "health < 40%. Green otherwise.\n\n" - "Tunics: colors will mirror currently equipped tunic, whether original or the current " - "values in Cosmetics Editor.\n\n" - "Custom: single, solid color"); + UIWidgets::Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " + "health < 40%. Green otherwise.\n\n" + "Tunics: colors will mirror currently equipped tunic, whether original or the current " + "values in Cosmetics Editor.\n\n" + "Custom: single, solid color"); if (CVarGetInteger("gLedColorSource", 1) == LED_SOURCE_CUSTOM) { UIWidgets::Spacer(3); auto port1Color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); @@ -1087,12 +1095,12 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { } UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", "gLedBrightness", 0.0f, 1.0f, "", 1.0f, true, true); - DrawHelpIcon("Sets the brightness of controller LEDs. 0% brightness = LEDs off."); + UIWidgets::Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."); UIWidgets::PaddedEnhancementCheckbox( "Critical Health Override", "gLedCriticalOverride", true, true, CVarGetInteger("gLedColorSource", LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, "Override redundant for health source.", UIWidgets::CheckboxGraphics::Cross, true); - DrawHelpIcon("Shows red color when health is critical, otherwise displays according to color source."); + UIWidgets::Tooltip("Shows red color when health is critical, otherwise displays according to color source."); } ImGui::TreePop(); } @@ -1430,6 +1438,273 @@ void SohInputEditorWindow::DrawLEDDeviceIcons(uint8_t portIndex) { } } +const ImGuiTableFlags PANEL_TABLE_FLAGS = + ImGuiTableFlags_BordersH | + ImGuiTableFlags_BordersV; +const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS = + ImGuiTableColumnFlags_IndentEnable | + ImGuiTableColumnFlags_NoSort; + +namespace TableHelper { + void InitHeader(bool has_header = true) { + if (has_header) { + ImGui::TableHeadersRow(); + } + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized. + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + } + + void NextCol() { + ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + } + + void NextLine() { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + } +} + +typedef uint32_t N64ButtonMask; + +void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) { + buttons.push_back(std::make_pair(mask, name)); + buttonNames[mask] = std::prev(buttons.end()); +} + +// Ocarina button maps +static CustomButtonMap ocarinaD5 = {"D5", "gOcarinaD5BtnMap", BTN_CUP}; +static CustomButtonMap ocarinaB4 = {"B4", "gOcarinaB4BtnMap", BTN_CLEFT}; +static CustomButtonMap ocarinaA4 = {"A4", "gOcarinaA4BtnMap", BTN_CRIGHT}; +static CustomButtonMap ocarinaF4 = {"F4", "gOcarinaF4BtnMap", BTN_CDOWN}; +static CustomButtonMap ocarinaD4 = {"D4", "gOcarinaD4BtnMap", BTN_A}; +static CustomButtonMap ocarinaSongDisable = {"Disable songs", "gOcarinaDisableBtnMap", BTN_L}; +static CustomButtonMap ocarinaSharp = {"Pitch up", "gOcarinaSharpBtnMap", BTN_R}; +static CustomButtonMap ocarinaFlat = {"Pitch down", "gOcarinaFlatBtnMap", BTN_Z}; + +// Draw a button mapping setting consisting of a padded label and button dropdown. +// excludedButtons indicates which buttons are unavailable to choose from. +void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons) { + N64ButtonMask currentButton = CVarGetInteger(mapping.cVarName, mapping.defaultBtn); + + const char* preview; + if (buttonNames.contains(currentButton)) { + preview = buttonNames[currentButton]->second; + } else { + preview = "Unknown"; + } + + UIWidgets::Spacer(0); + ImVec2 cursorPos = ImGui::GetCursorPos(); + ImVec2 textSize = ImGui::CalcTextSize(mapping.label); + ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4); + ImGui::SetCursorPosX(cursorPos.x + abs(textSize.x - labelWidth)); + ImGui::Text("%s", mapping.label); + ImGui::SameLine(); + ImGui::SetCursorPosY(cursorPos.y); + + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + if (ImGui::BeginCombo(StringHelper::Sprintf("##%s", mapping.cVarName).c_str(), preview)) { + for (auto i = buttons.begin(); i != buttons.end(); i++) { + if ((i->first & excludedButtons) != 0) { + continue; + } + if (ImGui::Selectable(i->second, i->first == currentButton)) { + CVarSetInteger(mapping.cVarName, i->first); + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } + } + ImGui::EndCombo(); + } + UIWidgets::Spacer(0); +} + +void SohInputEditorWindow::DrawOcarinaControlPanel() { + if (!ImGui::BeginTable("tableCustomOcarinaControls", 1, PANEL_TABLE_FLAGS)) { + return; + } + + ImGui::TableSetupColumn("Custom Ocarina Controls", PANEL_TABLE_COLUMN_FLAGS | ImGuiTableColumnFlags_WidthStretch); + TableHelper::InitHeader(false); + + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); + + if (CVarGetInteger("gCustomOcarinaControls", 0) == 1) { + if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { + float labelWidth; + N64ButtonMask disableMask = BTN_B; + if (CVarGetInteger("gDpadOcarina", 0)) { + disableMask |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + } + + ImGui::TableSetupColumn("Notes##CustomOcarinaNotes", PANEL_TABLE_COLUMN_FLAGS); + ImGui::TableSetupColumn("Modifiers##CustomOcaranaModifiers", PANEL_TABLE_COLUMN_FLAGS); + TableHelper::InitHeader(false); + + LUS::GuiWindow::BeginGroupPanel("Notes", ImGui::GetContentRegionAvail()); + labelWidth = ImGui::CalcTextSize("D5").x + 10; + DrawMapping(ocarinaD5, labelWidth, disableMask); + DrawMapping(ocarinaB4, labelWidth, disableMask); + DrawMapping(ocarinaA4, labelWidth, disableMask); + DrawMapping(ocarinaF4, labelWidth, disableMask); + DrawMapping(ocarinaD4, labelWidth, disableMask); + ImGui::Dummy(ImVec2(0, 5)); + float cursorY = ImGui::GetCursorPosY(); + LUS::GuiWindow::EndGroupPanel(0); + + TableHelper::NextCol(); + + LUS::GuiWindow::BeginGroupPanel("Modifiers", ImGui::GetContentRegionAvail()); + labelWidth = ImGui::CalcTextSize(ocarinaSongDisable.label).x + 10; + DrawMapping(ocarinaSongDisable, labelWidth, disableMask); + DrawMapping(ocarinaSharp, labelWidth, disableMask); + DrawMapping(ocarinaFlat, labelWidth, disableMask); + LUS::GuiWindow::EndGroupPanel(cursorY - ImGui::GetCursorPosY() + 2); + + ImGui::EndTable(); + } + } else { + UIWidgets::Spacer(0); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox."); + UIWidgets::Spacer(0); + } + + LUS::GuiWindow::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); + if (ImGui::BeginTable("tableOcarinaAlternateControls", 2, ImGuiTableFlags_SizingFixedSame)) { + ImGui::TableSetupColumn("D-pad", PANEL_TABLE_COLUMN_FLAGS); + ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); + TableHelper::InitHeader(false); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); + TableHelper::NextCol(); + UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); + UIWidgets::Spacer(0); + ImGui::EndTable(); + } + LUS::GuiWindow::EndGroupPanel(0); + + ImGui::EndTable(); +} + +void SohInputEditorWindow::DrawCameraControlPanel() { + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + LUS::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); + UIWidgets::Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"); + if (CVarGetInteger("gRightStickAiming", 0)) { + UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", "gMoveWhileFirstPerson"); + UIWidgets::Tooltip("Changes the left stick to move the player while in first person mode"); + } + UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis"); + UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", "gInvertAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", "gInvertShieldAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Inverts the Shield Aiming Y Axis"); + UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis"); + UIWidgets::Tooltip("Inverts the Shield Aiming X Axis"); + UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson"); + UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); + if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false)) { + if (!CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { + CVarClear("gFirstPersonCameraSensitivityX"); + CVarClear("gFirstPersonCameraSensitivityY"); + } + } + if (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { + UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal", + "gFirstPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true); + UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical", + "gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true); + } + UIWidgets::Spacer(0); + LUS::GuiWindow::EndGroupPanel(0); + + UIWidgets::Spacer(0); + cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + LUS::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); + + UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera"); + UIWidgets::Tooltip("Enables free camera control\nNote: You must remap C buttons off of the right stick in the " + "controller config menu, and map the camera stick to the right stick."); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); + UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free camera"); + UIWidgets::Spacer(0); + UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal", + "gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical", + "gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist", + "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed", + "gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true); + LUS::GuiWindow::EndGroupPanel(0); +} + +void SohInputEditorWindow::DrawDpadControlPanel() { + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + LUS::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause"); + UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n" + "To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0"); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText"); + UIWidgets::Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n" + "To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0"); + UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); + UIWidgets::Tooltip("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate"); + LUS::GuiWindow::EndGroupPanel(0); +} + +void SohInputEditorWindow::DrawMiscControlPanel() { + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); + LUS::GuiWindow::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedText("Allow the cursor to be on any slot"); + static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" }; + UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY); + UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select " + "certain items."); + UIWidgets::Spacer(0); + ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); + UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed"); + if (CVarGetInteger("gEnableWalkModify", 0)) { + UIWidgets::Spacer(5); + LUS::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); + LUS::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + LUS::GuiWindow::EndGroupPanel(0); + LUS::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + LUS::GuiWindow::EndGroupPanel(0); + LUS::GuiWindow::EndGroupPanel(0); + } + ImGui::EndDisabled(); + UIWidgets::Spacer(0); + UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL"); + UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); + LUS::GuiWindow::EndGroupPanel(0); +} + void SohInputEditorWindow::DrawLinkTab() { uint8_t portIndex = 0; if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) { @@ -1516,6 +1791,46 @@ void SohInputEditorWindow::DrawLinkTab() { DrawButtonDeviceIcons(portIndex, mModifierButtonsBitmasks); } + if (ImGui::CollapsingHeader("Ocarina Controls")) { + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + DrawOcarinaControlPanel(); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + } + + if (ImGui::CollapsingHeader("Camera Controls")) { + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + DrawCameraControlPanel(); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + } + + if (ImGui::CollapsingHeader("D-Pad Controls")) { + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + DrawDpadControlPanel(); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + } + + if (ImGui::CollapsingHeader("Miscellaneous Controls")) { + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + DrawMiscControlPanel(); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.133f, 0.133f, 0.133f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + } + ImGui::PopStyleColor(); ImGui::PopStyleColor(); ImGui::PopStyleColor(); diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h index 32443bb54..e96b5b09a 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h @@ -10,6 +10,15 @@ #include #include #include +#include + +typedef uint32_t N64ButtonMask; + +typedef struct { + const char* label; + const char* cVarName; + N64ButtonMask defaultBtn; +} CustomButtonMap; class SohInputEditorWindow : public LUS::GuiWindow { public: @@ -51,6 +60,17 @@ class SohInputEditorWindow : public LUS::GuiWindow { void DrawRemoveGyroMappingButton(uint8_t port, std::string id); void DrawAddGyroMappingButton(uint8_t port); + // Used together for an incomplete linked hash map implementation in order to + // map button masks to their names and original mapping on N64 + std::list> buttons; + std::unordered_map buttonNames; + void addButtonName(N64ButtonMask mask, const char* name); + void DrawMapping(CustomButtonMap& mapping, float labelWidth, N64ButtonMask excludedButtons); + void DrawOcarinaControlPanel(); + void DrawCameraControlPanel(); + void DrawDpadControlPanel(); + void DrawMiscControlPanel(); + int32_t mGameInputBlockTimer; int32_t mMappingInputBlockTimer; int32_t mRumbleTimer; @@ -84,6 +104,4 @@ class SohInputEditorWindow : public LUS::GuiWindow { bool mInputEditorPopupOpen; void DrawSetDefaultsButton(uint8_t portIndex); void DrawClearAllButton(uint8_t portIndex); - - void DrawHelpIcon(const std::string& helptext); }; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 178a8f329..6c9c2ef7d 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -29,7 +29,6 @@ #include #include #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" -#include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/controls/SohInputEditorWindow.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/audio/AudioCollection.h" diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index fa7072f5a..49f84068a 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -116,7 +116,6 @@ namespace SohGui { std::shared_ptr mInputEditorWindow; std::shared_ptr mAudioEditorWindow; - std::shared_ptr mGameControlEditorWindow; std::shared_ptr mCosmeticsEditorWindow; std::shared_ptr mActorViewerWindow; std::shared_ptr mColViewerWindow; @@ -164,8 +163,6 @@ namespace SohGui { mAudioEditorWindow = std::make_shared("gAudioEditor.WindowOpen", "Audio Editor"); gui->AddGuiWindow(mAudioEditorWindow); - mGameControlEditorWindow = std::make_shared("gGameControlEditorEnabled", "Game Control Editor"); - gui->AddGuiWindow(mGameControlEditorWindow); mCosmeticsEditorWindow = std::make_shared("gCosmeticsEditorEnabled", "Cosmetics Editor"); gui->AddGuiWindow(mCosmeticsEditorWindow); mActorViewerWindow = std::make_shared("gActorViewerEnabled", "Actor Viewer"); @@ -211,7 +208,6 @@ namespace SohGui { mColViewerWindow = nullptr; mActorViewerWindow = nullptr; mCosmeticsEditorWindow = nullptr; - mGameControlEditorWindow = nullptr; mAudioEditorWindow = nullptr; mInputEditorWindow = nullptr; mStatsWindow = nullptr; diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp index fccc29c1f..73a3addd4 100644 --- a/soh/soh/SohGui.hpp +++ b/soh/soh/SohGui.hpp @@ -11,7 +11,6 @@ #include #include "SohMenuBar.h" #include "Enhancements/audio/AudioEditor.h" -#include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f96320bc2..f59e3a343 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -21,7 +21,6 @@ #include "Enhancements/audio/AudioEditor.h" -#include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" @@ -180,7 +179,6 @@ void DrawShipMenu() { } extern std::shared_ptr mInputEditorWindow; -extern std::shared_ptr mGameControlEditorWindow; extern std::shared_ptr mAdvancedResolutionSettingsWindow; void DrawSettingsMenu() { @@ -241,11 +239,6 @@ void DrawSettingsMenu() { mInputEditorWindow->ToggleVisibility(); } } - if (mGameControlEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Additional Controller Options", CVarGetInteger("gGameControlEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { - mGameControlEditorWindow->ToggleVisibility(); - } - } UIWidgets::PaddedSeparator(); ImGui::PopStyleColor(1); ImGui::PopStyleVar(3); From f88343839ebf5f349a8f329801a6dae303b23640 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 1 Feb 2024 23:47:55 -0500 Subject: [PATCH 045/300] Item Tracker Text Size Slider (#3856) * Adds Slider and Functionality * prefix * Changed values * HELLO --------- Co-authored-by: Garrett Cox --- .../Enhancements/randomizer/randomizer_item_tracker.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f1841bd50..f158b4f3b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -412,6 +412,7 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { void DrawItemCount(ItemTrackerItem item) { int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int textSize = CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ImVec2 p = ImGui::GetCursorScreenPos(); int32_t trackerNumberDisplayMode = CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); @@ -428,13 +429,15 @@ void DrawItemCount(ItemTrackerItem item) { textScalingFactor / 2) + 8 * textScalingFactor, p.y - 22 * textScalingFactor); ImGui::SetCursorScreenPos(textPos); - ImGui::SetWindowFontScale(textScalingFactor); ImGui::Text(item.id == ITEM_HOOKSHOT ? "H" : "L"); ImGui::SetWindowFontScale(1.0f); // Reset font scale to the original state } } + + ImGui::SetWindowFontScale(textSize / 13.0f); + if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { std::string currentString = ""; std::string maxString = std::to_string(currentAndMax.maxCapacity); @@ -689,7 +692,7 @@ void DrawDungeonItem(ItemTrackerItem item) { ImVec2 p = ImGui::GetCursorScreenPos(); std::string dungeonName = itemTrackerDungeonShortNames[item.data]; - ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16))); + ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13) + 3))); ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor); ImGui::Text("%s", dungeonName.c_str()); ImGui::PopStyleColor(); @@ -1145,6 +1148,7 @@ void ItemTrackerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36); UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12); + UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", "gTrackers.ItemTracker.ItemTrackerTextSize", 1, 30, "", 13); UIWidgets::Spacer(0); From aff9f40933c751277a07839f78d53b0780362bff Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 1 Feb 2024 23:55:53 -0500 Subject: [PATCH 046/300] gc controllers via sdl on linux (#3869) * try gc via sdl basing this idea on this comment https://github.com/Ryujinx/Ryujinx/issues/2425#issuecomment-1269658650 * libusb? * fix * use latest lus main * don't bump lus yet --- .github/workflows/apt-deps.txt | 2 +- .github/workflows/generate-builds.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index 2a12d368c..43286f69e 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 0a3cc4f0e..99fa2d3bd 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -25,10 +25,10 @@ jobs: if: ${{ !vars.LINUX_RUNNER }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz - tar -xzf SDL2-2.26.1.tar.gz - cd SDL2-2.26.1 - ./configure + wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz + tar -xzf SDL2-2.28.5.tar.gz + cd SDL2-2.28.5 + ./configure --enable-hidapi-libusb make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ @@ -135,10 +135,10 @@ jobs: if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz - tar -xzf SDL2-2.26.1.tar.gz - cd SDL2-2.26.1 - ./configure + wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz + tar -xzf SDL2-2.28.5.tar.gz + cd SDL2-2.28.5 + ./configure --enable-hidapi-libusb make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ From 41c293361953f177263a70b0d41b48eba111fe09 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 2 Feb 2024 00:11:31 -0500 Subject: [PATCH 047/300] sccache for windows builds (#3385) * cache vcpkg on windows ci * try sccache as variant * missed a spot * see if we're checking here * does this do it? * trying to make minimal changes and have this work * hopefully these z7s do something * we were almost at the max already bump to double * Apply suggestions from code review * sc * latest from soh-macready branch of otrexporter --- .github/workflows/generate-builds.yml | 4 +++- CMake/DefaultCXX.cmake | 6 +++++- CMakeLists.txt | 14 +++++++++----- OTRExporter | 2 +- soh/CMake/DefaultCXX.cmake | 6 +++++- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 99fa2d3bd..674f742d2 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -273,6 +273,8 @@ jobs: uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ runner.os }}-ccache + variant: sccache + max-size: "1G" - name: vcpkg uses: johnwason/vcpkg-action@v5 with: @@ -286,7 +288,7 @@ jobs: VCPKG_ROOT: ${{github.workspace}}/vcpkg run: | set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH" - cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DBUILD_REMOTE_CONTROL=1 + cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DBUILD_REMOTE_CONTROL=1 cmake --build build-windows --config Release --parallel 10 mkdir soh-windows diff --git a/CMake/DefaultCXX.cmake b/CMake/DefaultCXX.cmake index e87721511..6ed89d9e0 100644 --- a/CMake/DefaultCXX.cmake +++ b/CMake/DefaultCXX.cmake @@ -8,5 +8,9 @@ if(MSVC) set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc") - set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi") + if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") + set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Z7") + else() + set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi") + endif() endif() \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cabaef20..9669c5f0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,13 +14,17 @@ add_compile_options($<$:/MP>) add_compile_options($<$:/utf-8>) if (CMAKE_SYSTEM_NAME STREQUAL "Windows") -include(CMake/automate-vcpkg.cmake) + include(CMake/automate-vcpkg.cmake) -set(VCPKG_TRIPLET x64-windows-static) -set(VCPKG_TARGET_TRIPLET x64-windows-static) + set(VCPKG_TRIPLET x64-windows-static) + set(VCPKG_TARGET_TRIPLET x64-windows-static) -vcpkg_bootstrap() -vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3) + vcpkg_bootstrap() + vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3) + + if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) + endif() endif() ################################################################################ diff --git a/OTRExporter b/OTRExporter index 04b85b95f..44adc47b4 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 04b85b95fab07a394b62dcd28a502a3040f08e0c +Subproject commit 44adc47b4da529e72d968b14cab94aefd8260f22 diff --git a/soh/CMake/DefaultCXX.cmake b/soh/CMake/DefaultCXX.cmake index 7b052b9cc..032326a13 100644 --- a/soh/CMake/DefaultCXX.cmake +++ b/soh/CMake/DefaultCXX.cmake @@ -8,5 +8,9 @@ if(MSVC) set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc") - set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi") + if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") + set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Z7") + else() + set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi") + endif() endif() \ No newline at end of file From 7cd2019ef6297786203fdd5ffbd7ebecf95dfa2e Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 2 Feb 2024 06:56:35 +0100 Subject: [PATCH 048/300] Fix starting skulltulas (#3876) --- soh/soh/Enhancements/randomizer/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index f3f5b1c10..3fc4efa86 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -200,7 +200,7 @@ void Settings::CreateOptions() { mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT] = Option::Bool("Start with Requiem of Spirit", "gRandomizeStartingRequiemOfSpirit", "", IMFLAG_NONE); mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW] = Option::Bool("Start with Nocturne of Shadow", "gRandomizeStartingNocturneOfShadow", "", IMFLAG_NONE); mOptions[RSK_STARTING_PRELUDE_OF_LIGHT] = Option::Bool("Start with Prelude of Light", "gRandomizeStartingPreludeOfLight"); - mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, "", "gRandomizeStartingSkulltulaToken", WidgetType::Slider); + mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, "gRandomizeStartingSkulltulaToken", "", WidgetType::Slider); mOptions[RSK_STARTING_HEARTS] = Option::U8("Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, "", "", WidgetType::Slider, 2); // TODO: Remainder of Starting Items mOptions[RSK_LOGIC_RULES] = Option::U8("Logic", {"Glitchless", "Glitched", "No Logic", "Vanilla"}, OptionCategory::Setting, "gRandomizeLogicRules", mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); From 83da5ee67765f0f63f436733a5b423f6d3e38cbb Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Feb 2024 00:22:44 -0600 Subject: [PATCH 049/300] Moar caching (#3896) --- .github/workflows/generate-builds.yml | 117 ++++++++++++++++++-------- 1 file changed, 83 insertions(+), 34 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 674f742d2..6f7134282 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -13,20 +13,35 @@ jobs: with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ runner.os }}-soh-otr-ccache + key: ${{ runner.os }}-otr-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-otr-ccache-${{ github.ref }} + ${{ runner.os }}-otr-ccache- - name: Install dependencies if: ${{ !vars.LINUX_RUNNER }} run: | sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) + - name: Cache build folders + uses: actions/cache@v4 + with: + key: ${{ runner.os }}-otr-build-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-otr-build-${{ github.ref }} + ${{ runner.os }}-otr-build- + path: | + build-cmake + SDL2-2.28.5 - name: Install latest SDL if: ${{ !vars.LINUX_RUNNER }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz - tar -xzf SDL2-2.28.5.tar.gz + if [ ! -d "SDL2-2.28.5" ]; then + wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz + tar -xzf SDL2-2.28.5.tar.gz + fi cd SDL2-2.28.5 ./configure --enable-hidapi-libusb make -j 10 @@ -37,7 +52,7 @@ jobs: export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release cmake --build build-cmake --config Release --target GenerateSohOtr - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: soh.otr path: soh.otr @@ -50,9 +65,12 @@ jobs: with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ runner.os }}-ccache + key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-ccache-${{ github.ref }} + ${{ runner.os }}-ccache- - name: Install gtar wrapper if: ${{ !vars.MAC_RUNNER }} run: | @@ -85,7 +103,7 @@ jobs: sudo port install $(cat .github/workflows/macports-deps.txt) brew install ninja - name: Download soh.otr - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: soh.otr - name: Build SoH @@ -99,7 +117,7 @@ jobs: mv _packages/*.dmg SoH.dmg mv README.md readme.txt - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: soh-mac path: | @@ -128,15 +146,30 @@ jobs: sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ matrix.os }}-ccache + key: ${{ matrix.os }}-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ matrix.os }}-ccache-${{ github.ref }} + ${{ matrix.os }}-ccache- + - name: Cache build folders + uses: actions/cache@v4 + with: + key: ${{ matrix.os }}-build-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ matrix.os }}-build-${{ github.ref }} + ${{ matrix.os }}-build- + path: | + SDL2-2.28.5 + SDL2_net-2.2.0 - name: Install latest SDL if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz - tar -xzf SDL2-2.28.5.tar.gz + if [ ! -d "SDL2-2.28.5" ]; then + wget https://www.libsdl.org/release/SDL2-2.28.5.tar.gz + tar -xzf SDL2-2.28.5.tar.gz + fi cd SDL2-2.28.5 ./configure --enable-hidapi-libusb make -j 10 @@ -146,15 +179,17 @@ jobs: if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz - tar -xzf SDL2_net-2.2.0.tar.gz + if [ ! -d "SDL2_net-2.2.0" ]; then + wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz + tar -xzf SDL2_net-2.2.0.tar.gz + fi cd SDL2_net-2.2.0 ./configure make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ - name: Download soh.otr - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: soh.otr - name: Build SoH @@ -170,7 +205,7 @@ jobs: CC: gcc-${{ matrix.gcc }} CXX: g++-${{ matrix.gcc }} - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: soh-linux-${{ matrix.archive-suffix }} path: | @@ -193,9 +228,12 @@ jobs: with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ runner.os }}-switch-ccache + key: ${{ runner.os }}-switch-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-switch-ccache-${{ github.ref }} + ${{ runner.os }}-switch-ccache- - name: Build SoH run: | cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache @@ -204,11 +242,11 @@ jobs: mv build-switch/soh/*.nro soh.nro mv README.md readme.txt - name: Download soh.otr - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: soh.otr - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: soh-switch path: | @@ -230,9 +268,12 @@ jobs: with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ runner.os }}-wiiu-ccache + key: ${{ runner.os }}-wiiu-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-wiiu-ccache-${{ github.ref }} + ${{ runner.os }}-wiiu-ccache- - name: Build SoH run: | cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache @@ -245,11 +286,11 @@ jobs: DEVKITPRO: /opt/devkitpro DEVKITPPC: /opt/devkitpro/devkitPPC - name: Download soh.otr - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: soh.otr - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: soh-wiiu path: | @@ -270,17 +311,25 @@ jobs: with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 + uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ runner.os }}-ccache variant: sccache max-size: "1G" - - name: vcpkg - uses: johnwason/vcpkg-action@v5 + key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-ccache-${{ github.ref }} + ${{ runner.os }}-ccache- + - name: Cache build folder + uses: actions/cache@v4 with: - pkgs: zlib bzip2 libpng sdl2 sdl2-net glew glfw3 - token: ${{ github.token }} - triplet: 'x64-windows-static' + save-always: true + key: ${{ runner.os }}-build-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-build-${{ github.ref }} + ${{ runner.os }}-build- + path: | + build-windows + vcpkg - name: Configure Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1 - name: Build SoH @@ -301,12 +350,12 @@ jobs: mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt mv ./x64/Release/assets ./soh-windows - name: Download soh.otr - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: soh.otr path: soh-windows - name: Upload build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: soh-windows path: soh-windows From be8dcfda05f511dd8ea0f2a962bf17ccddabf1c9 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Fri, 2 Feb 2024 05:38:24 -0800 Subject: [PATCH 050/300] Fix Internal Resolution format to use %.1f instead of %d (#3899) --- soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp index 11a7cd75a..892b5798a 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp @@ -115,7 +115,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { const bool disabled_resolutionSlider = (CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && CVarGetInteger("gAdvancedResolution.Enabled", 0)) || CVarGetInteger("gLowResMode", 0); - if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, + if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier( CVarGetFloat("gInternalResolution", 1)); From 596ea5ebbb3e5a5dfab72fb7bee6d4802d8b13d4 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 8 Jan 2024 09:25:47 -0600 Subject: [PATCH 051/300] Vanilla Behavior Overhaul Co-authored-by: jordanpg --- soh/include/functions.h | 4 + soh/include/z64actor.h | 12 +- .../Enhancements/debugger/debugSaveEditor.h | 8 +- soh/soh/Enhancements/debugger/valueViewer.cpp | 2 + soh/soh/Enhancements/enhancementTypes.h | 7 + .../game-interactor/GameInteractor.h | 294 ++- .../game-interactor/GameInteractor_Hooks.cpp | 5 + .../game-interactor/GameInteractor_Hooks.h | 1 + soh/soh/Enhancements/mods.cpp | 4 + .../Enhancements/randomizer/3drando/fill.cpp | 14 +- .../randomizer/3drando/spoiler_log.hpp | 4 - .../Enhancements/randomizer/hook_handlers.cpp | 975 ++++++++++ .../Enhancements/randomizer/hook_handlers.h | 6 + .../Enhancements/randomizer/item_location.cpp | 13 + .../Enhancements/randomizer/item_location.h | 4 + soh/soh/Enhancements/randomizer/location.h | 20 +- .../Enhancements/randomizer/location_list.cpp | 1690 ++++++++--------- .../randomizer/randomizer_check_tracker.cpp | 21 +- .../randomizer/randomizer_entrance.c | 51 +- .../Enhancements/randomizer/randomizer_inf.h | 10 + soh/soh/Enhancements/randomizer/savefile.cpp | 142 +- .../Enhancements/timesaver_hook_handlers.cpp | 788 ++++++++ .../Enhancements/timesaver_hook_handlers.h | 6 + soh/soh/OTRGlobals.cpp | 10 +- soh/soh/SaveManager.cpp | 11 + soh/soh/SohMenuBar.cpp | 114 +- soh/src/code/z_demo.c | 171 +- soh/src/code/z_en_item00.c | 120 +- soh/src/code/z_message_PAL.c | 19 +- soh/src/code/z_onepointdemo.c | 18 +- soh/src/code/z_parameter.c | 8 +- soh/src/code/z_play.c | 126 -- soh/src/code/z_player_lib.c | 4 +- .../ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c | 15 +- .../actors/ovl_Bg_Breakwall/z_bg_breakwall.c | 10 +- .../ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c | 11 +- .../actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c | 10 +- .../actors/ovl_Bg_Treemouth/z_bg_treemouth.c | 15 +- .../actors/ovl_Bg_Treemouth/z_bg_treemouth.h | 3 + .../overlays/actors/ovl_Demo_Du/z_demo_du.c | 9 +- .../actors/ovl_Demo_Effect/z_demo_effect.c | 53 +- .../overlays/actors/ovl_Demo_Im/z_demo_im.c | 44 +- .../overlays/actors/ovl_Demo_Im/z_demo_im.h | 2 + .../overlays/actors/ovl_Demo_Sa/z_demo_sa.c | 9 +- .../actors/ovl_Door_Shutter/z_door_shutter.c | 15 +- .../actors/ovl_Door_Warp1/z_door_warp1.c | 176 +- .../overlays/actors/ovl_Elf_Msg/z_elf_msg.c | 15 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 84 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.h | 3 +- soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c | 85 +- soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h | 2 + soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 85 +- soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h | 5 +- soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c | 71 +- soh/src/overlays/actors/ovl_En_Du/z_en_du.c | 27 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 50 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h | 4 +- soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c | 43 +- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 219 +-- soh/src/overlays/actors/ovl_En_Go/z_en_go.h | 7 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 185 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h | 5 + soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c | 49 +- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 21 +- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c | 46 +- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h | 4 + soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 90 +- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h | 2 + soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c | 169 +- soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h | 3 + soh/src/overlays/actors/ovl_En_Md/z_en_md.c | 46 +- soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c | 54 +- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 36 +- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h | 3 + soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c | 9 +- .../actors/ovl_En_Niw_Lady/z_en_niw_lady.c | 46 +- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c | 8 +- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h | 2 + soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c | 5 +- soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c | 9 +- soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c | 35 +- soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h | 2 + .../actors/ovl_En_Shopnuts/z_en_shopnuts.c | 16 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 113 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.h | 3 + soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 3 +- soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c | 68 +- soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h | 2 + .../overlays/actors/ovl_En_Toryo/z_en_toryo.c | 20 +- .../ovl_En_Wonder_Talk2/z_en_wonder_talk2.c | 41 +- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 110 +- soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c | 5 +- soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c | 34 +- soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h | 5 + .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 34 +- .../actors/ovl_Item_B_Heart/z_item_b_heart.h | 5 + .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 27 +- .../actors/ovl_Obj_Switch/z_obj_switch.c | 15 +- .../actors/ovl_player_actor/z_player.c | 19 +- 99 files changed, 4191 insertions(+), 2912 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/hook_handlers.cpp create mode 100644 soh/soh/Enhancements/randomizer/hook_handlers.h create mode 100644 soh/soh/Enhancements/timesaver_hook_handlers.cpp create mode 100644 soh/soh/Enhancements/timesaver_hook_handlers.h diff --git a/soh/include/functions.h b/soh/include/functions.h index 49a8a0a93..698487621 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -183,6 +183,8 @@ void __osSetWatchLo(u32); EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params); EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params); void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry); +void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc); +void func_8001E5C8(EnItem00* this, PlayState* play); void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params); void EffectBlure_ChangeType(EffectBlure* this, int type); void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2); @@ -415,6 +417,7 @@ f32 Actor_WorldDistXZToPoint(Actor* actor, Vec3f* refPoint); void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2); f32 Actor_HeightDiff(Actor* actorA, Actor* actorB); f32 Player_GetHeight(Player* player); +s32 func_8083E5A8(Player* player, PlayState* play); f32 func_8002DCE4(Player* player); s32 func_8002DD6C(Player* player); s32 func_8002DD78(Player* player); @@ -1106,6 +1109,7 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input); u8 PlayerGrounded(Player* player); void Player_SetBootData(PlayState* play, Player* player); s32 Player_InBlockingCsMode(PlayState* play, Player* player); +s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction); s32 Player_InCsMode(PlayState* play); s32 func_8008E9C4(Player* player); s32 Player_IsChildWithHylianShield(Player* player); diff --git a/soh/include/z64actor.h b/soh/include/z64actor.h index 0a8ac9297..156f1d679 100644 --- a/soh/include/z64actor.h +++ b/soh/include/z64actor.h @@ -266,7 +266,12 @@ typedef enum { /* 0x17 */ ITEM00_TUNIC_ZORA, /* 0x18 */ ITEM00_TUNIC_GORON, /* 0x19 */ ITEM00_BOMBS_SPECIAL, - /* 0x20 */ ITEM00_BOMBCHU, + /* 0x1A */ ITEM00_BOMBCHU, + /* 0x1B */ ITEM00_SOH_DUMMY, + /* 0x1C */ ITEM00_SOH_GIVE_ITEM_ENTRY, + /* 0x1D */ ITEM00_SOH_GIVE_ITEM_ENTRY_GI, + /* 0x1E */ ITEM00_MAX, + /* 0xFF */ ITEM00_NONE = 0xFF } Item00Type; struct EnItem00; @@ -284,10 +289,13 @@ typedef struct EnItem00 { /* 0x15A */ s16 unk_15A; /* 0x15C */ f32 scale; /* 0x160 */ ColliderCylinder collider; - s16 ogParams; + // #region SOH [Randomizer] GetItemEntry randoGiEntry; RandomizerCheck randoCheck; RandomizerInf randoInf; + /* */ s16 ogParams; + /* */ GetItemEntry itemEntry; + // #endregion } EnItem00; // size = 0x1AC // Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files. diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index b0650bfa0..5a4618dac 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -505,6 +505,7 @@ const std::vector flagTables = { { RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" }, { RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" }, { RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" }, + { RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" }, { RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" }, { RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" }, @@ -515,7 +516,6 @@ const std::vector flagTables = { { RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" }, { RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" }, { RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" }, - { RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" }, { RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"}, { RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" }, @@ -607,7 +607,11 @@ const std::vector flagTables = { { RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" }, { RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" }, { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, - { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" } + { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }, + + { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, + { RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" }, + { RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" }, } }, }; diff --git a/soh/soh/Enhancements/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp index 14a571dac..213c81cfa 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.cpp +++ b/soh/soh/Enhancements/debugger/valueViewer.cpp @@ -34,6 +34,8 @@ std::vector valueTable = { { "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE }, { "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE }, { "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE }, + { "getItemID", "Player->getItemId", "ITEM:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemId; }, WHITE }, + { "getItemEntry", "Player->getItemEntry", "IE:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemEntry.itemId; }, WHITE }, /* TODO: Find these (from GZ) "XZ Units Traveled (Camera based speed variable)" f32 0x801C9018 "Movement Angle" x16 0x801DBB1C diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h index c8461bbf1..f3b8ac029 100644 --- a/soh/soh/Enhancements/enhancementTypes.h +++ b/soh/soh/Enhancements/enhancementTypes.h @@ -14,6 +14,13 @@ typedef enum { CSMC_SIZE } ChestStyleMatchesContentsType; +typedef enum { + SGIA_DISABLED, + SGIA_JUNK, + SGIA_ALL, + SGIA_SIZE +} SkipGetItemAnimationType; + typedef enum { BUNNY_HOOD_VANILLA, BUNNY_HOOD_FAST_AND_JUMP, diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index be27e74a2..c6fb7c721 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -3,6 +3,7 @@ #ifndef GameInteractor_h #define GameInteractor_h +#include "libultraship/libultraship.h" #include "GameInteractionEffect.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h" #include @@ -67,6 +68,272 @@ typedef enum { /* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7, } GITeleportDestinations; +typedef enum { + // Vanilla condition: gSaveContext.showTitleCard + GI_VB_SHOW_TITLE_CARD, + // Opt: *EnWonderTalk2 + GI_VB_WONDER_TALK, + // Opt: *ElfMsg + GI_VB_NAVI_TALK, + // Vanilla condition: INFTABLE_GREETED_BY_SARIA + GI_VB_NOT_BE_GREETED_BY_SARIA, + // Opt: *EnMd + // Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION + GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, + // Opt: *EnMd + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) + GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, + // Opt: *EnKo + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) + GI_VB_OPEN_KOKIRI_FOREST, + // Opt: *EnOwl + // Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist + GI_VB_OWL_INTERACTION, + // Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE + GI_VB_MALON_RETURN_FROM_CASTLE, + // Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0 + GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, + /* Vanilla condition: + ``` + LINK_IS_ADULT && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + ``` + */ + GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, + // Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA) + GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA) + GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, + // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) + GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, + // Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT + GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, + // Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP + GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, + /* Vanilla Condition: + ``` + LINK_IS_ADULT && + gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + ``` + */ + GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, + // Opt: *EnGo2 + // Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12 + GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, + // Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) + GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, + // Opt: *EnMs + // Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT] + GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, + // Opt: *EnItem00 + // Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag) + GI_VB_ITEM00_DESPAWN, + // Opt: *EnTk + // Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD + GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, + // Opt: *EnTk + // Vanilla condition: this->validDigHere == 1 + GI_VB_BE_VALID_GRAVEDIGGING_SPOT, + // Opt: *EnTk + // Vanilla condition: this->currentReward == 3 + GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, + // Opt: *EnTk + // Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C) + GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, + // Opt: *EnShopnuts + /* Vanilla Condition: + ``` + ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || + ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) || + ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))) + ``` + */ + GI_VB_BUSINESS_SCRUB_DESPAWN, + // Opt: *EnCow + // Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) + GI_VB_DESPAWN_HORSE_RACE_COW, + // Opt: *EnHs + // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) + GI_VB_DESPAWN_GROG, + // Opt: *EnKo + // Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false; + GI_VB_SPAWN_LW_FADO, + // Opt: *EnMk + GI_VB_PLAY_EYEDROP_CREATION_ANIM, + // Opt: *EnDs + GI_VB_PLAY_ODD_POTION_ANIM, + // Opt: *EnMk + // Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS + GI_VB_USE_EYEDROP_DIALOGUE, + // Opt: *EnMk + // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) + GI_VB_OFFER_BLUE_POTION, + // Vanilla condition: Inventory_HasEmptyBottle() == 0 + GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, + // Opt: *EnNiwLady + GI_VB_SET_CUCCO_COUNT, + // Opt: *EnKz + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) + GI_VB_KING_ZORA_THANK_CHILD, + // Opt: *EnKz + // Vanilla condition: this->actor.textId == 0x401A + GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, + // Opt: *EnKz + // Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) + GI_VB_KING_ZORA_BE_MOVED, + // Vanilla condition: gSaveState.bgsFlag + GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, + // Vanilla condition: gSaveState.bgsFlag + GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, + // Vanilla condition: Environment_GetBgsDayCount() >= 3 + GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) + GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY) + GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, + // Opt: *uint16_t + // Vanilla condition: false + GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, + // Opt: *EnGo2 + GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, + + /*** Play Cutscenes ***/ + + GI_VB_PLAY_TRANSITION_CS, + // Opt: *EventChkInf flag + GI_VB_PLAY_ENTRANCE_CS, + // Opt: *cutsceneId + GI_VB_PLAY_ONEPOINT_CS, + // Opt: *actor + GI_VB_PLAY_ONEPOINT_ACTOR_CS, + // Opt: *BgTreemouth + GI_VB_PLAY_DEKU_TREE_INTRO_CS, + // Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true + GI_VB_PLAY_BLUE_WARP_CS, + GI_VB_PLAY_DARUNIAS_JOY_CS, + GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, + // Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL + GI_VB_PLAY_PULL_MASTER_SWORD_CS, + GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, + // Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER + GI_VB_PLAY_NABOORU_CAPTURED_CS, + GI_VB_PLAY_ZELDAS_LULLABY_CS, + // Opt: *EnSa + GI_VB_PLAY_SARIAS_SONG_CS, + GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, + GI_VB_PLAY_MINUET_OF_FOREST_CS, + GI_VB_PLAY_BOLERO_OF_FIRE_CS, + GI_VB_PLAY_SERENADE_OF_WATER_CS, + GI_VB_PLAY_EYEDROPS_CS, + + /*** Give Items ***/ + + GI_VB_GIVE_ITEM_FROM_CHEST, + GI_VB_GIVE_ITEM_FROM_BLUE_WARP, + // Opt: *EnItem00 + GI_VB_GIVE_ITEM_FROM_ITEM_00, + // Opt: *EnSi + GI_VB_GIVE_ITEM_SKULL_TOKEN, + // Opt: *EnCow + GI_VB_GIVE_ITEM_FROM_COW, + // Opt: *EnDns + GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, + // Opt: *EnMk + GI_VB_GIVE_ITEM_FROM_LAB_DIVE, + // Opt: *EnDs + GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, + // Opt: *EnNiwLady + GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, + // Opt: *EnNiwLady + GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, + // Opt: *EnKz + // Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) + GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + // Opt: *EnGo2 + GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD, + // Opt: *EnGo2 + GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT, + // Opt: *EnJs + GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, + // Opt: *EnGm + GI_VB_GIVE_ITEM_FROM_MEDIGORON, + // Opt: *EnMs + GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, + // Opt: *EnFr + GI_VB_GIVE_ITEM_FROM_FROGS, + + GI_VB_GIVE_ITEM_FAIRY_OCARINA, + GI_VB_GIVE_ITEM_WEIRD_EGG, + GI_VB_GIVE_ITEM_LIGHT_ARROW, + GI_VB_GIVE_ITEM_STRENGTH_1, + GI_VB_GIVE_ITEM_ZELDAS_LETTER, + GI_VB_GIVE_ITEM_MASTER_SWORD, + GI_VB_GIVE_ITEM_OCARINA_OF_TIME, + GI_VB_GIVE_ITEM_KOKIRI_EMERALD, + GI_VB_GIVE_ITEM_GORON_RUBY, + GI_VB_GIVE_ITEM_ZORA_SAPPHIRE, + GI_VB_GIVE_ITEM_LIGHT_MEDALLION, + GI_VB_GIVE_ITEM_FOREST_MEDALLION, + GI_VB_GIVE_ITEM_FIRE_MEDALLION, + GI_VB_GIVE_ITEM_WATER_MEDALLION, + GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, + GI_VB_GIVE_ITEM_SHADOW_MEDALLION, + + /*** Give Songs ***/ + + GI_VB_GIVE_ITEM_ZELDAS_LULLABY, + GI_VB_GIVE_ITEM_SARIAS_SONG, + GI_VB_GIVE_ITEM_EPONAS_SONG, + GI_VB_GIVE_ITEM_SUNS_SONG, + GI_VB_GIVE_ITEM_SONG_OF_TIME, + GI_VB_GIVE_ITEM_SONG_OF_STORMS, + GI_VB_GIVE_ITEM_MINUET_OF_FOREST, + GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, + GI_VB_GIVE_ITEM_SERENADE_OF_WATER, + GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, + GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, + GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, + + /*** Adult Trade ***/ + // Opt: *EnNiwLady + GI_VB_TRADE_POCKET_CUCCO, + // Opt: *EnHs + GI_VB_TRADE_COJIRO, + // Opt: *EnDs + GI_VB_TRADE_ODD_MUSHROOM, + // Opt: *EnKo + GI_VB_TRADE_ODD_POTION, + // Opt: *EnToryo + GI_VB_TRADE_SAW, + // Opt: *EnGo2 + GI_VB_TRADE_BROKEN_SWORD, + // Opt: *EnKz, + GI_VB_TRADE_PRESCRIPTION, + // Opt: *EnMk + GI_VB_TRADE_FROG, + // Opt: *EnGo2 + GI_VB_TRADE_EYEDROPS, + // Opt: *EnGo2 + GI_VB_TRADE_CLAIM_CHECK, + + GI_VB_TRADE_TIMER_ODD_MUSHROOM, + GI_VB_TRADE_TIMER_EYEDROPS, + GI_VB_TRADE_TIMER_FROG, + // Opt: *EnNiwLady + GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, + + /*** Fixes ***/ + // Vanilla condition: false + GI_VB_FIX_SAW_SOFTLOCK, +} GIVanillaBehavior; + #ifdef __cplusplus extern "C" { #endif @@ -163,11 +430,28 @@ public: static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect); // Game Hooks - template struct RegisteredGameHooks { inline static std::vector functions; }; - template void RegisterGameHook(typename H::fn h) { RegisteredGameHooks::functions.push_back(h); } + uint32_t nextHookId = 0; + template struct RegisteredGameHooks { inline static std::unordered_map functions; }; + template struct HooksToUnregister { inline static std::vector hooks; }; + template uint32_t RegisterGameHook(typename H::fn h) { + // Ensure hook id is unique + while (RegisteredGameHooks::functions.find(this->nextHookId) != RegisteredGameHooks::functions.end()) { + this->nextHookId++; + } + RegisteredGameHooks::functions[this->nextHookId] = h; + return this->nextHookId++; + } + template void UnregisterGameHook(uint32_t id) { + HooksToUnregister::hooks.push_back(id); + } + template void ExecuteHooks(Args&&... args) { - for (auto& fn : RegisteredGameHooks::functions) { - fn(std::forward(args)...); + for (auto& hookId : HooksToUnregister::hooks) { + RegisteredGameHooks::functions.erase(hookId); + } + HooksToUnregister::hooks.clear(); + for (auto& hook : RegisteredGameHooks::functions) { + hook.second(std::forward(args)...); } } @@ -194,6 +478,8 @@ public: DEFINE_HOOK(OnPlayDestroy, void()); DEFINE_HOOK(OnPlayDrawEnd, void()); + DEFINE_HOOK(OnVanillaBehavior, void(GIVanillaBehavior flag, bool* result, void* opt)); + DEFINE_HOOK(OnSaveFile, void(int32_t fileNum)); DEFINE_HOOK(OnLoadFile, void(int32_t fileNum)); DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 4bd5354a6..95728c075 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -90,6 +90,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() { GameInteractor::Instance->ExecuteHooks(); } +bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) { + GameInteractor::Instance->ExecuteHooks(flag, &result, opt); + return result; +} + // MARK: - Save Files void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 7b7b226fa..d89b95381 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -27,6 +27,7 @@ void GameInteractor_ExecuteOnOcarinaSongAction(); void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price); void GameInteractor_ExecuteOnPlayDestroy(); void GameInteractor_ExecuteOnPlayDrawEnd(); +bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt); // MARK: - Save Files void GameInteractor_ExecuteOnSaveFile(int32_t fileNum); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 26adf611d..4aabf04d6 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -10,6 +10,8 @@ #include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include #include "soh/Enhancements/nametag.h" +#include "soh/Enhancements/timesaver_hook_handlers.h" +#include "soh/Enhancements/randomizer/hook_handlers.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" #include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h" @@ -1596,6 +1598,8 @@ void RegisterFishsanity() { } void InitMods() { + RandomizerRegisterHooks(); + TimeSaverRegisterHooks(); RegisterTTS(); RegisterInfiniteMoney(); RegisterInfiniteHealth(); diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 8536c1d17..92799a5db 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -1122,7 +1122,19 @@ int Fill() { std::vector remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); FastFill(remainingPool, GetAllEmptyLocations(), false); - //Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile. + //Add default prices to scrubs + for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { + if (Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_GROTTO_FRONT) { + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(40); + } else if (Rando::StaticData::scrubLocations[i] == RC_HF_DEKU_SCRUB_GROTTO) { + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); + } else { + auto loc = Rando::StaticData::GetLocation(Rando::StaticData::scrubLocations[i]); + auto item = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()); + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(item.GetPrice()); + } + } + if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) { for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp index 51fc51941..7e20b176a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp @@ -18,16 +18,12 @@ typedef enum { SPOILER_CHK_ITEM_GET_INF, SPOILER_CHK_EVENT_CHK_INF, SPOILER_CHK_INF_TABLE, - SPOILER_CHK_COW, SPOILER_CHK_FISH, SPOILER_CHK_MINIGAME, - SPOILER_CHK_SCRUB, SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, SPOILER_CHK_POE_POINTS, SPOILER_CHK_SHOP_ITEM, - SPOILER_CHK_MAGIC_BEANS, SPOILER_CHK_MASTER_SWORD, - SPOILER_CHK_MERCHANT, SPOILER_CHK_GRAVEDIGGER, SPOILER_CHK_RANDOMIZER_INF, } SpoilerCollectionCheckType; diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp new file mode 100644 index 000000000..bf236a3ba --- /dev/null +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -0,0 +1,975 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/enhancementTypes.h" +#include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "src/overlays/actors/ovl_En_Si/z_en_si.h" +#include "src/overlays/actors/ovl_En_Cow/z_en_cow.h" +#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" +#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" +#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h" +#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" +#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h" +#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h" +#include "src/overlays/actors/ovl_En_Kz/z_en_kz.h" +#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h" +#include "src/overlays/actors/ovl_En_Ms/z_en_ms.h" +#include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" +#include "adult_trade_shuffle.h" +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() + +RandomizerCheck GetRandomizerCheckFromFlag(int16_t flagType, int16_t flag) { + for (auto& loc : Rando::StaticData::GetLocationTable()) { + if (loc.GetCollectionCheck().flag == flag && ( + (flagType == FLAG_EVENT_CHECK_INF && loc.GetCollectionCheck().type == SPOILER_CHK_EVENT_CHK_INF) || + (flagType == FLAG_ITEM_GET_INF && loc.GetCollectionCheck().type == SPOILER_CHK_ITEM_GET_INF) || + (flagType == FLAG_RANDOMIZER_INF && loc.GetCollectionCheck().type == SPOILER_CHK_RANDOMIZER_INF) + ) || + (loc.GetActorParams() == flag && flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) + ) { + return loc.GetRandomizerCheck(); + } + } + + return RC_UNKNOWN_CHECK; +} + +RandomizerCheck GetRandomizerCheckFromSceneFlag(int16_t sceneNum, int16_t flagType, int16_t flag) { + for (auto& loc : Rando::StaticData::GetLocationTable()) { + if (loc.GetCollectionCheck().scene == sceneNum && loc.GetCollectionCheck().flag == flag && ( + (flagType == FLAG_SCENE_TREASURE && loc.GetCollectionCheck().type == SPOILER_CHK_CHEST) || + (flagType == FLAG_SCENE_COLLECTIBLE && loc.GetCollectionCheck().type == SPOILER_CHK_COLLECTABLE) || + (flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) + )) { + return loc.GetRandomizerCheck(); + } + } + + return RC_UNKNOWN_CHECK; +} + +bool MeetsLACSRequirements() { + switch (RAND_GET_OPTION(RSK_GANONS_BOSS_KEY)) { + case RO_GANON_BOSS_KEY_LACS_STONES: + if ((CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_STONE_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_MEDALLIONS: + if ((CheckMedallionCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_MEDALLION_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_REWARDS: + if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_REWARD_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_DUNGEONS: + if ((CheckDungeonCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_DUNGEON_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_TOKENS: + if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_LACS_TOKEN_COUNT)) { + return true; + } + break; + default: + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { + return true; + } + break; + } + + return false; +} + +// Todo Move this to randomizer context, clear it out on save load etc +static std::queue randomizerQueuedChecks; +static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; +static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE; + +void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { + RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag); + if (rc == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + if (loc == nullptr || loc->HasObtained()) return; + + SPDLOG_INFO("Queuing RC: {}", rc); + randomizerQueuedChecks.push(rc); +} + +void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) { + RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); + if (rc == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + if (loc == nullptr || loc->HasObtained()) return; + + SPDLOG_INFO("Queuing RC: {}", rc); + randomizerQueuedChecks.push(rc); +} + +static Vec3f spawnPos = { 0.0f, -999.0f, 0.0f }; + +void RandomizerOnPlayerUpdateForRCQueueHandler() { + // If we're already queued, don't queue again + if (randomizerQueuedCheck != RC_UNKNOWN_CHECK) return; + + // If there's nothing to queue, don't queue + if (randomizerQueuedChecks.size() < 1) return; + + // If we're in a cutscene, don't queue + Player* player = GET_PLAYER(gPlayState); + if (Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + RandomizerCheck rc = randomizerQueuedChecks.front(); + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + + if (loc->HasObtained()) { + SPDLOG_INFO("RC {} already obtained, skipping", rc); + } else { + randomizerQueuedCheck = rc; + randomizerQueuedItemEntry = getItemEntry; + SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, rc); + if ( + // Skipping ItemGet animation incompatible with checks that require closing a text box to finish + rc != RC_HF_OCARINA_OF_TIME_ITEM && + rc != RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && + // Always show ItemGet animation for ice traps + !(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) && + ( + CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_ALL || + ( + CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_JUNK && + ( + getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || + getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || + getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER + ) + ) + ) + ) { + Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000); + } + } + + randomizerQueuedChecks.pop(); +} + +void RandomizerOnPlayerUpdateForItemQueueHandler() { + if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return; + + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + SPDLOG_INFO("Attempting to give Item mod {} item {} from RC {}", randomizerQueuedItemEntry.modIndex, randomizerQueuedItemEntry.itemId, randomizerQueuedCheck); + GiveItemEntryWithoutActor(gPlayState, randomizerQueuedItemEntry); + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { + // Allow the player to receive the item while swimming + player->stateFlags2 |= PLAYER_STATE2_UNDERWATER; + func_8083E5A8(player, gPlayState); + } +} + +void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { + if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(randomizerQueuedCheck); + if (randomizerQueuedItemEntry.modIndex == receivedItemEntry.modIndex && randomizerQueuedItemEntry.itemId == receivedItemEntry.itemId) { + SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, randomizerQueuedCheck); + loc->MarkAsObtained(); + randomizerQueuedCheck = RC_UNKNOWN_CHECK; + randomizerQueuedItemEntry = GET_ITEM_NONE; + } + + if ( + receivedItemEntry.modIndex == MOD_NONE && ( + receivedItemEntry.itemId == ITEM_HEART_PIECE || + receivedItemEntry.itemId == ITEM_HEART_PIECE_2 || + receivedItemEntry.itemId == ITEM_HEART_CONTAINER + ) + ) { + gSaveContext.healthAccumulator = 0x140; // Refill 20 hearts + if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) { + gSaveContext.inventory.questItems ^= 0x40000000; + gSaveContext.healthCapacity += 0x10; + gSaveContext.health += 0x10; + } + } + + if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + static uint32_t updateHook; + updateHook = GameInteractor::Instance->RegisterGameHook([]() { + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + gPlayState->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.nextCutsceneIndex = 0xFFF1; + gPlayState->transitionType = TRANS_TYPE_SANDSTORM_END; + GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; + Player_TryCsAction(gPlayState, NULL, 8); + GameInteractor::Instance->UnregisterGameHook(updateHook); + }); + } +} + +void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) { + f32 mtxScale = CVarGetFloat("gTimeSavers.SkipGetItemAnimationScale", 10.0f); + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + EnItem00_CustomItemsParticles(&enItem00->actor, play, enItem00->itemEntry); + GetItemEntry_Draw(play, enItem00->itemEntry); +} + +void ItemBHeart_DrawRandomizedItem(ItemBHeart* itemBHeart, PlayState* play) { + EnItem00_CustomItemsParticles(&itemBHeart->actor, play, itemBHeart->sohItemEntry); + GetItemEntry_Draw(play, itemBHeart->sohItemEntry); +} + +void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { + ItemBHeart* itemBHeart = (ItemBHeart*)actor; + + func_80B85264(itemBHeart, play); + Actor_UpdateBgCheckInfo(play, &itemBHeart->actor, 0.0f, 0.0f, 0.0f, 4); + if ((itemBHeart->actor.xzDistToPlayer < 30.0f) && (fabsf(itemBHeart->actor.yDistToPlayer) < 40.0f)) { + Flags_SetCollectible(play, 0x1F); + Actor_Kill(&itemBHeart->actor); + } +} + +void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) { + bool moved = false; + + // Don't reposition the tail + if (enCow->actor.params != 0) { + return; + } + + // Move left cow in lon lon tower + if (play->sceneNum == SCENE_LON_LON_BUILDINGS && enCow->actor.world.pos.x == -108 && + enCow->actor.world.pos.z == -65) { + enCow->actor.world.pos.x = -229.0f; + enCow->actor.world.pos.z = 157.0f; + enCow->actor.shape.rot.y = 15783.0f; + moved = true; + // Move right cow in lon lon stable + } else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) { + enCow->actor.world.pos.x += 119.0f; + moved = true; + } + + if (moved) { + // Reposition collider + func_809DEE9C(enCow); + } +} + +u8 EnDs_RandoCanGetGrannyItem() { + return RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && + // Traded odd mushroom when adult trade is on + ((RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) || + // Found claim check when adult trade is off + (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)); +} + +RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) { + switch (songIndex) { + case FROG_ZL: + return RC_ZR_FROGS_ZELDAS_LULLABY; + case FROG_EPONA: + return RC_ZR_FROGS_EPONAS_SONG; + case FROG_SARIA: + return RC_ZR_FROGS_SARIAS_SONG; + case FROG_SUNS: + return RC_ZR_FROGS_SUNS_SONG; + case FROG_SOT: + return RC_ZR_FROGS_SONG_OF_TIME; + case FROG_STORMS: + return RC_ZR_FROGS_IN_THE_RAIN; + case FROG_CHOIR_SONG: + return RC_ZR_FROGS_OCARINA_GAME; + default: + return RC_UNKNOWN_CHECK; + } +} + +void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) { + switch (id) { + case GI_VB_GIVE_ITEM_FROM_CHEST: { + Player* player = GET_PLAYER(gPlayState); + player->unk_850 = 1; + player->getItemId = GI_NONE; + player->getItemEntry = GetItemEntry(GET_ITEM_NONE); + *should = false; + break; + } + case GI_VB_PLAY_NABOORU_CAPTURED_CS: + // This behavior is replicated for randomizer in RandomizerOnItemReceiveHandler + *should = false; + break; + case GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: { + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !Flags_GetTreasure(gPlayState, 0x2); + break; + } + case GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER: + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetTreasure(gPlayState, 0x2); + break; + case GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT: + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST); + break; + case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + if (RAND_GET_OPTION(RSK_FOREST) == RO_FOREST_OPEN) { + *should = true; + } + break; + case GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD: + *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); + break; + case GI_VB_OPEN_KOKIRI_FOREST: + *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_FOREST_CLOSED; + break; + case GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD: + *should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY); + break; + case GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS: + *should = !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements(); + break; + case GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW: + *should = + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) && + LINK_IS_ADULT && + gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE && + CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER); + break; + case GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: { + // Don't require a bomb bag to get prize in rando + *should = true; + break; + } + case GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE: { + if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { + *should = gSaveContext.rupees >= 60; + } + break; + } + case GI_VB_GIVE_ITEM_MASTER_SWORD: + if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD)) { + *should = false; + } else { + *should = true; + Rando::Context::GetInstance()->GetItemLocation(RC_TOT_MASTER_SWORD)->MarkAsObtained(); + } + break; + case GI_VB_ITEM00_DESPAWN: { + EnItem00* item00 = static_cast(optionalArg); + if (item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY) { + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(item00->actor.id, gPlayState->sceneNum, item00->ogParams); + if (rc != RC_UNKNOWN_CHECK) { + item00->actor.params = ITEM00_SOH_DUMMY; + item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + *should = Rando::Context::GetInstance()->GetItemLocation(rc)->HasObtained(); + } + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY || item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) { + GetItemEntry itemEntry = randomizerQueuedItemEntry; + item00->itemEntry = itemEntry; + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + } + break; + } + case GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG: { + *should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + break; + } + case GI_VB_SET_CUCCO_COUNT: { + EnNiwLady* enNiwLady = static_cast(optionalArg); + // Override starting Cucco count using setting value + enNiwLady->cuccosInPen = 7 - RAND_GET_OPTION(RSK_CUCCO_COUNT); + *should = false; + break; + } + case GI_VB_KING_ZORA_THANK_CHILD: { + // Allow turning in Ruto's letter even if you have already rescued her + if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + GET_PLAYER(gPlayState)->exchangeItemId = EXCH_ITEM_LETTER_RUTO; + } + *should = Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + break; + } + case GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: { + *should = LINK_IS_CHILD; + break; + } + case GI_VB_KING_ZORA_BE_MOVED: { + *should = false; + switch (RAND_GET_OPTION(RSK_ZORAS_FOUNTAIN)) { + case RO_ZF_CLOSED: + if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + *should = true; + } + break; + case RO_ZF_CLOSED_CHILD: + if (LINK_IS_ADULT) { + *should = true; + } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + *should = true; + } + break; + case RO_ZF_OPEN: + *should = true; + break; + } + break; + } + case GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED: { + *should = Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + break; + } + case GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE: { + + *should = INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK && Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + break; + } + case GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); + break; + } + case GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED: { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); + break; + } + case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { + u16* textId = static_cast(optionalArg); + *should = true; + + // For rando, prioritize opening the doors in GC when Link the goron has been stopped when + // the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved + if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { + *textId = 0x3030; + } else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { + *textId = 0x3036; + } else if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { + *textId = 0x3041; + } else { + *textId = Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; + } + break; + } + case GI_VB_EN_GO2_RESET_AFTER_GET_ITEM: { + EnGo2* enGo2 = static_cast(optionalArg); + // For randomizer, handle updating the states for the gorons after receiving the item based on + // the goron type rather then the item being received + switch (enGo2->actor.params & 0x1F) { + case GORON_DMT_BIGGORON: + // Resolves #1301. unk_13EE is used to set the opacity of the HUD. The trade sequence discussion + // with Biggoron sets the HUD to transparent, and it is restored at z_message_PAL:3549, but by + // specifically watching for trade sequence items, this leaves it transparent for non-trade sequence + // items (in rando) so we fix that here + gSaveContext.unk_13EE = 0x32; + break; + case GORON_CITY_LINK: + EnGo2_GetItemAnimation(enGo2, gPlayState); + break; + case GORON_CITY_ROLLING_BIG: + EnGo2_RollingAnimation(enGo2, gPlayState); + enGo2->actionFunc = (EnGo2ActionFunc)EnGo2_GoronRollingBigContinueRolling; + break; + default: + enGo2->actionFunc = func_80A46B40; + break; + } + break; + } + case GI_VB_GIVE_ITEM_FROM_ITEM_00: { + EnItem00* item00 = static_cast(optionalArg); + if (item00->actor.params == ITEM00_SOH_DUMMY) { + Flags_SetCollectible(gPlayState, item00->collectibleFlag); + Actor_Kill(&item00->actor); + *should = false; + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY) { + Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + if (item00->itemEntry.modIndex == MOD_NONE) { + if (item00->itemEntry.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } + Item_Give(gPlayState, item00->itemEntry.itemId); + } else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) { + if (item00->itemEntry.getItemId == RG_ICE_TRAP) { + gSaveContext.pendingIceTrapCount++; + } else { + Randomizer_Item_Give(gPlayState, item00->itemEntry); + } + } + // EnItem00_SetupAction(item00, func_8001E5C8); + // *should = false; + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) { + if (!Actor_HasParent(&item00->actor, gPlayState)) { + GiveItemEntryFromActorWithFixedRange(&item00->actor, gPlayState, item00->itemEntry); + } + EnItem00_SetupAction(item00, func_8001E5C8); + *should = false; + } + break; + } + case GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG: { + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); + break; + } + case GI_VB_GIVE_ITEM_FROM_COW: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { + break; + } + EnCow* enCow = static_cast(optionalArg); + CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z); + // Has this cow already rewarded an item? + if (Flags_GetRandomizerInf(cowIdentity.randomizerInf)) { + break; + } + Flags_SetRandomizerInf(cowIdentity.randomizerInf); + // setting the ocarina mode here prevents intermittent issues + // with the item get not triggering until walking away + gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_00; + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP: { + if (!EnDs_RandoCanGetGrannyItem()) { + break; + } + // Only setting the inf if we've actually gotten the rando item and not the vanilla blue potion + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA: { + EnKz* enKz = static_cast(optionalArg); + // If we aren't setting up the item offer, then we're just checking if it should be possible. + if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { + // Always give the reward in rando + *should = true; + break; + } + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD: { + Flags_SetItemGetInf(ITEMGETINF_0C); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: { + Flags_SetItemGetInf(ITEMGETINF_2C); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT: { + EnGo2* enGo2 = static_cast(optionalArg); + *should = false; + if (!Flags_GetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT)) { + Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); + enGo2->interactInfo.talkState = NPC_TALK_STATE_ACTION; + } + break; + } + case GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN: { + *should = RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_OFF || + // If the rando check has already been awarded, use vanilla behavior. + Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); + break; + } + case GI_VB_GIVE_ITEM_FROM_MEDIGORON: { + // fallthrough + case GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE: + if (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + if (id == GI_VB_GIVE_ITEM_FROM_MEDIGORON) { + Flags_SetInfTable(INFTABLE_B1); + *should = false; + } else { + // Resets "Talked to Medigoron" flag in infTable to restore initial conversation state + Flags_UnsetInfTable(INFTABLE_B1); + *should = true; + } + } + break; + } + case GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN: { + EnMs* enMs = static_cast(optionalArg); + if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { + Rupees_ChangeBy(-60); + BEANS_BOUGHT = 10; + // Only set inf for buying rando check + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN); + enMs->actionFunc = (EnMsActionFunc)EnMs_Wait; + *should = false; + } + break; + } + case GI_VB_GIVE_ITEM_FROM_FROGS: { + EnFr* enFr = static_cast(optionalArg); + + // Skip GiveReward+SetIdle action func if the reward is an ice trap + if (enFr->actionFunc == (EnFrActionFunc)EnFr_GiveReward) { + RandomizerCheck rc = EnFr_RandomizerCheckFromSongIndex(enFr->songIndex); + GetItemEntry gi = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + if (gi.getItemId == RG_ICE_TRAP) { + enFr->actionFunc = (EnFrActionFunc)EnFr_Idle; + } + } + + *should = false; + break; + } + case GI_VB_TRADE_POCKET_CUCCO: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_POCKET_CUCCO); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_2E); + *should = false; + break; + } + case GI_VB_TRADE_COJIRO: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_COJIRO); + *should = false; + break; + } + case GI_VB_TRADE_ODD_MUSHROOM: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_MUSHROOM); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_30); + *should = false; + break; + } + case GI_VB_TRADE_ODD_POTION: { + EnKo* enKo = static_cast(optionalArg); + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_POTION); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_31); + *should = false; + break; + } + case GI_VB_TRADE_SAW: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SAW); + *should = false; + break; + } + case GI_VB_TRADE_PRESCRIPTION: { + EnKz* enKz = static_cast(optionalArg); + // If we aren't setting up the item offer, then we're just checking if it should be possible. + if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { + *should = !Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION); + break; + } + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_PRESCRIPTION); + *should = false; + break; + } + case GI_VB_TRADE_FROG: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_FROG); + *should = false; + break; + } + case GI_VB_TRADE_BROKEN_SWORD: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SWORD_BROKEN); + *should = false; + break; + } + case GI_VB_TRADE_EYEDROPS: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_EYEDROPS); + *should = false; + break; + } + case GI_VB_DESPAWN_HORSE_RACE_COW: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { + break; + } + EnCow* enCow = static_cast(optionalArg); + // If this is a cow we have to move, then move it now. + EnCow_MoveForRandomizer(enCow, gPlayState); + break; + } + case GI_VB_BUSINESS_SCRUB_DESPAWN: { + EnShopnuts* enShopnuts = static_cast(optionalArg); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + ScrubIdentity scrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enShopnuts->actor.params, respawnData); + + if (scrubIdentity.isShuffled) { + *should = Flags_GetRandomizerInf(scrubIdentity.randomizerInf); + } + break; + } + case GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB: { + EnDns* enDns = static_cast(optionalArg); + *should = !enDns->sohScrubIdentity.isShuffled; + break; + } + // To explain the logic because Fado and Grog are linked: + // - If you have Cojiro, then spawn Grog and not Fado. + // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. + // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. + // - If you don't have either but have traded the mushroom, don't spawn either. + case GI_VB_DESPAWN_GROG: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { + break; + } + if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { + *should = false; + } else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) { + *should = true; + } else { + *should = Flags_GetItemGetInf(ITEMGETINF_30); // Traded odd mushroom + } + break; + } + case GI_VB_SPAWN_LW_FADO: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { + break; + } + + if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { + *should = false; + } else { + *should = PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION); + } + + break; + } + case GI_VB_USE_EYEDROP_DIALOGUE: { + // Skip eye drop text on rando if Link went in the water, so you can still receive the dive check + EnMk* enMk = static_cast(optionalArg); + *should &= enMk->swimFlag == 0; + break; + } + case GI_VB_OFFER_BLUE_POTION: { + // Always offer blue potion when adult trade is off + *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF; + break; + } + case GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM: { + // Allow buying the rando item regardless of having a bottle + *should &= !EnDs_RandoCanGetGrannyItem(); + break; + } + case GI_VB_TRADE_CLAIM_CHECK: + case GI_VB_TRADE_TIMER_ODD_MUSHROOM: + case GI_VB_TRADE_TIMER_EYEDROPS: + case GI_VB_TRADE_TIMER_FROG: + case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: + case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD: + case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: + case GI_VB_GIVE_ITEM_SKULL_TOKEN: + case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: + case GI_VB_GIVE_ITEM_FAIRY_OCARINA: + case GI_VB_GIVE_ITEM_WEIRD_EGG: + case GI_VB_GIVE_ITEM_LIGHT_ARROW: + case GI_VB_GIVE_ITEM_STRENGTH_1: + case GI_VB_GIVE_ITEM_ZELDAS_LETTER: + case GI_VB_GIVE_ITEM_OCARINA_OF_TIME: + case GI_VB_GIVE_ITEM_KOKIRI_EMERALD: + case GI_VB_GIVE_ITEM_GORON_RUBY: + case GI_VB_GIVE_ITEM_ZORA_SAPPHIRE: + case GI_VB_GIVE_ITEM_LIGHT_MEDALLION: + case GI_VB_GIVE_ITEM_FOREST_MEDALLION: + case GI_VB_GIVE_ITEM_FIRE_MEDALLION: + case GI_VB_GIVE_ITEM_WATER_MEDALLION: + case GI_VB_GIVE_ITEM_SPIRIT_MEDALLION: + case GI_VB_GIVE_ITEM_SHADOW_MEDALLION: + *should = false; + break; + } +} + +void RandomizerOnSceneInitHandler(int16_t sceneNum) { + // LACs & Prelude checks + static uint32_t updateHook = 0; + + if (updateHook) { + GameInteractor::Instance->UnregisterGameHook(updateHook); + updateHook = 0; + } + + if ( + sceneNum != SCENE_TEMPLE_OF_TIME || + ( + Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && + Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) + ) + ) return; + + updateHook = GameInteractor::Instance->RegisterGameHook([]() { + if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && gPlayState->roomCtx.curRoom.num == 0) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + } + + if (!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements()) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + } + + if ( + Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && + Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) + ) { + GameInteractor::Instance->UnregisterGameHook(updateHook); + } + }); +} + +void EnSi_DrawRandomizedItem(EnSi* enSi, PlayState* play) { + func_8002ED80(&enSi->actor, play, 0); + func_8002EBCC(&enSi->actor, play, 0); + EnItem00_CustomItemsParticles(&enSi->actor, play, enSi->sohGetItemEntry); + GetItemEntry_Draw(play, enSi->sohGetItemEntry); +} + +u32 EnDns_RandomizerPurchaseableCheck(EnDns* enDns) { + if (Flags_GetRandomizerInf(enDns->sohScrubIdentity.randomizerInf)) { + return 3; // Can't get this now + } + if (gSaveContext.rupees < enDns->dnsItemEntry->itemPrice) { + return 0; // Not enough rupees + } + return 4; +} + +void EnDns_RandomizerPurchase(EnDns* enDns) { + Rupees_ChangeBy(-enDns->dnsItemEntry->itemPrice); + Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf); +} + +void RandomizerOnActorInitHandler(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id == ACTOR_EN_SI) { + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params); + if (rc != RC_UNKNOWN_CHECK) { + EnSi* enSi = static_cast(actorRef); + enSi->sohGetItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + actor->draw = (ActorFunc)EnSi_DrawRandomizedItem; + } + } + + if (actor->id == ACTOR_ITEM_B_HEART) { + ItemBHeart* itemBHeart = static_cast(actorRef); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(itemBHeart->actor.id, gPlayState->sceneNum, itemBHeart->actor.params); + if (rc != RC_UNKNOWN_CHECK) { + itemBHeart->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + itemBHeart->actor.draw = (ActorFunc)ItemBHeart_DrawRandomizedItem; + itemBHeart->actor.update = (ActorFunc)ItemBHeart_UpdateRandomizedItem; + } + } + + if (actor->id == ACTOR_EN_DNS) { + EnDns* enDns = static_cast(actorRef); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + enDns->sohScrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enDns->actor.params, respawnData); + + if (enDns->sohScrubIdentity.isShuffled) { + // DNS uses pointers so we're creating our own entry instead of modifying the original + enDns->sohDnsItemEntry = { + enDns->dnsItemEntry->itemPrice, + 1, + enDns->sohScrubIdentity.getItemId, + EnDns_RandomizerPurchaseableCheck, + EnDns_RandomizerPurchase, + }; + enDns->dnsItemEntry = &enDns->sohDnsItemEntry; + + if (enDns->sohScrubIdentity.itemPrice != -1) { + enDns->dnsItemEntry->itemPrice = enDns->sohScrubIdentity.itemPrice; + } + + enDns->actor.textId = TEXT_SCRUB_RANDOM; + + static uint32_t enDnsUpdateHook = 0; + static uint32_t enDnsKillHook = 0; + if (!enDnsUpdateHook) { + enDnsUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_DNS) { + EnDns* innerEnDns = static_cast(innerActorRef); + if (innerEnDns->sohScrubIdentity.isShuffled) { + innerActor->textId = TEXT_SCRUB_RANDOM; + } + } + }); + enDnsKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { + GameInteractor::Instance->UnregisterGameHook(enDnsUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enDnsKillHook); + enDnsUpdateHook = 0; + enDnsKillHook = 0; + }); + } + } + } +} + +void RandomizerRegisterHooks() { + static uint32_t onFlagSetHook = 0; + static uint32_t onSceneFlagSetHook = 0; + static uint32_t onPlayerUpdateForRCQueueHook = 0; + static uint32_t onPlayerUpdateForItemQueueHook = 0; + static uint32_t onItemReceiveHook = 0; + static uint32_t onVanillaBehaviorHook = 0; + static uint32_t onSceneInitHook = 0; + static uint32_t onActorInitHook = 0; + + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) { + randomizerQueuedChecks = std::queue(); + randomizerQueuedCheck = RC_UNKNOWN_CHECK; + randomizerQueuedItemEntry = GET_ITEM_NONE; + + GameInteractor::Instance->UnregisterGameHook(onFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onSceneFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateForRCQueueHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateForItemQueueHook); + GameInteractor::Instance->UnregisterGameHook(onItemReceiveHook); + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + GameInteractor::Instance->UnregisterGameHook(onSceneInitHook); + GameInteractor::Instance->UnregisterGameHook(onActorInitHook); + + onFlagSetHook = 0; + onSceneFlagSetHook = 0; + onPlayerUpdateForRCQueueHook = 0; + onPlayerUpdateForItemQueueHook = 0; + onItemReceiveHook = 0; + onVanillaBehaviorHook = 0; + onSceneInitHook = 0; + onActorInitHook = 0; + + if (!IS_RANDO) return; + + onFlagSetHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnFlagSetHandler); + onSceneFlagSetHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnSceneFlagSetHandler); + onPlayerUpdateForRCQueueHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnPlayerUpdateForRCQueueHandler); + onPlayerUpdateForItemQueueHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnPlayerUpdateForItemQueueHandler); + onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnItemReceiveHandler); + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnVanillaBehaviorHandler); + onSceneInitHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnSceneInitHandler); + onActorInitHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnActorInitHandler); + }); +} diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.h b/soh/soh/Enhancements/randomizer/hook_handlers.h new file mode 100644 index 000000000..46abb30b7 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef RANDOMIZER_HOOK_HANDLERS_H +#define RANDOMIZER_HOOK_HANDLERS_H + +void RandomizerRegisterHooks(); + +#endif // RANDOMIZER_HOOK_HANDLERS_H \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 736778786..adc805550 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -101,6 +101,18 @@ void ItemLocation::SetCustomPrice(const uint16_t price_) { hasCustomPrice = true; } +bool ItemLocation::HasObtained() const { + return obtained; +} + +void ItemLocation::MarkAsObtained() { + obtained = true; +} + +void ItemLocation::MarkAsNotObtained() { + obtained = false; +} + bool ItemLocation::IsHintable() const { return isHintable; } @@ -201,5 +213,6 @@ void ItemLocation::ResetVariables() { wothCandidate = false; barrenCandidate = false; area = RA_NONE; + obtained = false; } } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h index a4b60a5d3..ab74b2d77 100644 --- a/soh/soh/Enhancements/randomizer/item_location.h +++ b/soh/soh/Enhancements/randomizer/item_location.h @@ -31,6 +31,9 @@ class ItemLocation { void SetPrice(uint16_t price_); bool HasCustomPrice() const; void SetCustomPrice(uint16_t price_); + bool HasObtained() const; + void MarkAsObtained(); + void MarkAsNotObtained(); bool IsHintable() const; void SetAsHintable(); bool IsHintedAt() const; @@ -67,5 +70,6 @@ class ItemLocation { bool visibleInImGui = false; bool wothCandidate = false; bool barrenCandidate = false; + bool obtained = false; }; } // namespace Rando \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index 993e8c184..fcea02eb4 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -51,10 +51,6 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag); } - static auto Cow(const uint8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_COW, scene, flag); - } - static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) { return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag); } @@ -63,10 +59,6 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit); } - static auto Scrub(const uint8_t scene, const uint8_t bit) { - return SpoilerCollectionCheck(SPOILER_CHK_SCRUB, scene, bit); - } - static auto GerudoToken() { return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00); } @@ -83,20 +75,12 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot); } - static auto MagicBeans(const uint8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_MAGIC_BEANS, scene, flag); - } - static auto MasterSword() { return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00); } - static auto Merchant(const int8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_MERCHANT, scene, flag); - } - - static auto RandomizerInf(const int8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene, flag); + static auto RandomizerInf(const uint8_t flag) { + return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, 0x00, flag); } }; diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index ea4775d46..28ca3b85a 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -245,6 +245,7 @@ std::vector Rando::StaticData::overworldLocations = { RC_TOT_MASTER_SWORD, RC_SHEIK_AT_TEMPLE, RC_TOT_LIGHT_ARROWS_CUTSCENE, + RC_GIFT_FROM_SAGES, // Kakariko RC_SHEIK_IN_KAKARIKO, @@ -595,786 +596,773 @@ typedef enum { using namespace Rando; -void Rando::StaticData::InitLocationTable() { +void Rando::StaticData::InitLocationTable() { // Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // clang-format off - locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression + locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); // Kokiri Forest - locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", "KF Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", "KF Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", "KF Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", "KF Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", "KF Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", "KF Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", "KF Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", "KF Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", "KF Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", "KF Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", "KF Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", "KF Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", "LW Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(30), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", "LW Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x5B, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", "LW Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", "LW Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(31), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", "LW Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right","LW Deku Scrub Near Deku Theater Right",RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x5B, 0x01), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x5B, 0x02), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE,{ Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x5B, 0x0A), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1F, 0x04), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x1F, 0x0B), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE,{}, SpoilerCollectionCheck::Chest(0x3E, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1E), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", "LW Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(22), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", "LW Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", "LW Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(49), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", "LW Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(23), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", "LW Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right", "LW Deku Scrub Near Deku Theater Right", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1E), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); // Sacred Forest Meadow - locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x18, 0x08), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x18, 0x09), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", "HF Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", "HF Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", "HF Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", "HF Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", "HF Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x10, 0x03), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", "HF Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", "HF Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", "HF Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", "HF Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", "HF Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); // Lake Hylia - locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", "LH Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_FISHING_POND, RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", "LH Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_FISHING_POND, RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", "LH Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(24), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x38, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", "LH Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", "LH Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", "LH Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x01), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x06), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x04), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", "LH Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", "LH Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", "LH Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", "LH Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", "LH Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", "LH Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", "GV Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", "GV Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x5A, 0x1F), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", "GV Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1A, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1A, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", "GV Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", "GV Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", "GV Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(7), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // RandoTodo: Do we replace these with the RC_HIDEOUT keys or keep these? - locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // Haunted Wasteland - locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", "Wasteland Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", "Wasteland Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::Merchant(0x5E, 0x86), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", "Wasteland Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", "Wasteland Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Desert Colossus - locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", "Colossus Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x27, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x27, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", "Colossus Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Market - locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", "MK Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(19), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(25), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(26), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_MARKET_GUARD_HOUSE, RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x05, "Chest Game Third Room Chest", "MK Chest Game Third Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x07, "Chest Game Fourth Room Chest", "MK Chest Game Fourth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x09, "Chest Game Fifth Room Chest", "MK Chest Game Fifth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", "MK Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(27), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(13), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x05, "Chest Game Third Room Chest", "MK Chest Game Third Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x07, "Chest Game Fourth Room Chest", "MK Chest Game Fourth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x09, "Chest Game Fifth Room Chest", "MK Chest Game Fifth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Hyrule Castle - locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); // Kakariko - locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", "Kak Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", "Kak Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", "Kak 10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", "Kak 20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_HOUSE_OF_SKULLTULA, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(56), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_POTION_SHOP_GRANNY, RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(36), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", "Kak Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", "Kak Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(38), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", "Kak Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", "Kak Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", "Kak 10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", "Kak 20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", "Kak Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(12), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", "Kak Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(46), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Graveyard - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN,21824, 0x00, "Shield Grave Chest", "GY Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", "GY Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", "GY Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", "GY Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", "GY Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] =Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH,RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH,RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x08, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::Gravedigger(0x53, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 21824, 0x00, "Shield Grave Chest", "GY Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", "GY Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", "GY Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", "GY Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", "GY Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x19, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Death Mountain - locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", "DMT Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", "DMT Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", "DMT Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x60, 0x1D), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", "DMT Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x60, 0x1E), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", "DMT Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::Chest(0x60, 0x1F), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", "DMT Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", "DMT Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", "DMT Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", "DMT Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", "DMT Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", "DMT Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", "DMT Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); // Goron City - locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(0x11, 0x06), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(0x10, 0x01), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::Chest(0x62, 0x1E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x01), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x06), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x04), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", "GC Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::Merchant(0x62, 0x87), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ROLLING_GORON_AS_CHILD), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DARUNIAS_JOY), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", "GC Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MEDIGORON), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Death Mountain Crater - locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", "DMC Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", "DMC Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", "DMC Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x61, 0x06), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x06), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x04), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", "DMC Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", "DMC Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", "DMC Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); // Zoras River - locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", "ZR Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", "ZR Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::MagicBeans(0x54, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", "ZR Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", "ZR Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", "ZR Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", "ZR Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", "ZR Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", "ZR Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x15, 0x08), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x15, 0x09), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", "ZR Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", "ZR Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", "ZR Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", "ZR Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", "ZR Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", "ZR Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", "ZR Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", "ZR Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zoras Domain - locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", "ZD Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", "ZD Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", "ZD King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::InfTable(0x13, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", "ZD Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::Chest(0x58, 0x1F), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", "ZD Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", "ZD Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", "ZD King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KING_ZORA_THAWED), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", "ZD Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Zora's Fountain - locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", "ZF Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", "ZF Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", "ZF Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", "ZF Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Lon Lon Ranch - locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", "LLR Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(10), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", "LLR Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x01), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x06), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x04), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", "LLR Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(2), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", "LLR Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); // Dungeons - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Deku Tree Vanilla - locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", "Deku Tree Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", "Deku Tree Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", "Deku Tree Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", "Deku Tree Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", "Deku Tree Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", "Deku Tree Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", "Deku Tree Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", "Deku Tree Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", "Deku Tree Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", "Deku Tree Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", "Deku Tree Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", "Deku Tree Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Deku Tree MQ - locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", "Deku Tree MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", "Deku Tree MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", "Deku Tree MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", "Deku Tree MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", "Deku Tree MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x00, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", "Deku Tree MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", "Deku Tree MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", "Deku Tree MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", "Deku Tree MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", "Deku Tree MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Dodongo's Cavern Shared - locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", "Dodongos Cavern Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", "Dodongos Cavern Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern Vanilla - locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", "Dodongos Cavern Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", "Dodongos Cavern Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x02), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", "Dodongos Cavern Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", "Dodongos Cavern Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern MQ - locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", "Dodongos Cavern MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x02), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", "Dodongos Cavern MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Jabu-Jabu's Belly Vanilla - locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", "Jabu Jabus Belly Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", "Jabu Jabus Belly Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", "Jabu Jabus Belly Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x02, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", "Jabu Jabus Belly Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", "Jabu Jabus Belly Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", "Jabu Jabus Belly Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); // Jabu-Jabu's Belly MQ - locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", "Jabu Jabus Belly MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", "Jabu Jabus Belly MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", "Jabu Jabus Belly MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", "Jabu Jabus Belly MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", "Jabu Jabus Belly MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", "Jabu Jabus Belly MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", "Jabu Jabus Belly MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", "Jabu Jabus Belly MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", "Jabu Jabus Belly MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", "Jabu Jabus Belly MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", "Jabu Jabus Belly MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", "Jabu Jabus Belly MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", "Jabu Jabus Belly MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", "Jabu Jabus Belly MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", "Jabu Jabus Belly MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", "Jabu Jabus Belly MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Forest Temple Vanilla - locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", "Forest Temple First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", "Forest Temple First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", "Forest Temple Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", "Forest Temple Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", "Forest Temple Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", "Forest Temple Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", "Forest Temple Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", "Forest Temple Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", "Forest Temple Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", "Forest Temple Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", "Forest Temple Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", "Forest Temple Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", "Forest Temple Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", "Forest Temple First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", "Forest Temple First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", "Forest Temple Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", "Forest Temple Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", "Forest Temple Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", "Forest Temple Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", "Forest Temple Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", "Forest Temple Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", "Forest Temple Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", "Forest Temple Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", "Forest Temple Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", "Forest Temple Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", "Forest Temple Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Forest Temple MQ - locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", "Forest Temple MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", "Forest Temple MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", "Forest Temple MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", "Forest Temple MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", "Forest Temple MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", "Forest Temple MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", "Forest Temple MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", "Forest Temple MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", "Forest Temple MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", "Forest Temple MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", "Forest Temple MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", "Forest Temple MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", "Forest Temple MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", "Forest Temple MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", "Forest Temple MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", "Forest Temple MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", "Forest Temple MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", "Forest Temple MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", "Forest Temple MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", "Forest Temple MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", "Forest Temple MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", "Forest Temple MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", "Forest Temple MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", "Forest Temple MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Fire Temple Vanilla - locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", "Fire Temple Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", "Fire Temple Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", "Fire Temple Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", "Fire Temple Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", "Fire Temple Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", "Fire Temple Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", "Fire Temple Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", "Fire Temple Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", "Fire Temple Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", "Fire Temple Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", "Fire Temple Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", "Fire Temple Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", "Fire Temple Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", "Fire Temple Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", "Fire Temple Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", "Fire Temple Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", "Fire Temple Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", "Fire Temple Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", "Fire Temple Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", "Fire Temple Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", "Fire Temple Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", "Fire Temple Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", "Fire Temple Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", "Fire Temple Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", "Fire Temple Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", "Fire Temple Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", "Fire Temple Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", "Fire Temple Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); // Fire Temple MQ - locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", "Fire Temple MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", "Fire Temple MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", "Fire Temple MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", "Fire Temple MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", "Fire Temple MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", "Fire Temple MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", "Fire Temple MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", "Fire Temple MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", "Fire Temple MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", "Fire Temple MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", "Fire Temple MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", "Fire Temple MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", "Fire Temple MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", "Fire Temple MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", "Fire Temple MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", "Fire Temple MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", "Fire Temple MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", "Fire Temple MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", "Fire Temple MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", "Fire Temple MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", "Fire Temple MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", "Fire Temple MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", "Fire Temple MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", "Fire Temple MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Randomizer Get Categories Collection Check Group Vanilla Progression // Water Temple Vanilla - locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", "Water Temple Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", "Water Temple Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", "Water Temple Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", "Water Temple Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", "Water Temple Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", "Water Temple Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", "Water Temple Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", "Water Temple Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", "Water Temple Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", "Water Temple River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", "Water Temple Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", "Water Temple Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", "Water Temple Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", "Water Temple Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", "Water Temple Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", "Water Temple Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", "Water Temple Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", "Water Temple Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", "Water Temple Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", "Water Temple River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); // Water Temple MQ - locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", "Water Temple MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Water Temple MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", "Water Temple MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Water Temple MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", "Water Temple MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", "Water Temple MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", "Water Temple MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Water Temple MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", "Water Temple MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Water Temple MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", "Water Temple MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", "Water Temple MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Spirit Temple Shared - locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple Vanilla - locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", "Spirit Temple Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", "Spirit Temple Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", "Spirit Temple Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", "Spirit Temple First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", "Spirit Temple First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", "Spirit Temple Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", "Spirit Temple Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", "Spirit Temple Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", "Spirit Temple Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", "Spirit Temple Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", "Spirit Temple Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", "Spirit Temple Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", "Spirit Temple Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", "Spirit Temple Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", "Spirit Temple Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", "Spirit Temple Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", "Spirit Temple Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", "Spirit Temple Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", "Spirit Temple Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", "Spirit Temple First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", "Spirit Temple First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", "Spirit Temple Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", "Spirit Temple Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", "Spirit Temple Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", "Spirit Temple Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", "Spirit Temple Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", "Spirit Temple Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", "Spirit Temple Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", "Spirit Temple Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", "Spirit Temple Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", "Spirit Temple Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", "Spirit Temple Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple MQ - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", "Spirit Temple MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", "Spirit Temple MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", "Spirit Temple MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", "Spirit Temple MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", "Spirit Temple MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", "Spirit Temple MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", "Spirit Temple MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", "Spirit Temple MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", "Spirit Temple MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", "Spirit Temple MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", "Spirit Temple MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", "Spirit Temple MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", "Spirit Temple MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", "Spirit Temple MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", "Spirit Temple MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", "Spirit Temple MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", "Spirit Temple MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", "Spirit Temple MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Spirit Temple MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", "Spirit Temple MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", "Spirit Temple MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", "Spirit Temple MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", "Spirit Temple MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", "Spirit Temple MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", "Spirit Temple MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", "Spirit Temple MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", "Spirit Temple MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", "Spirit Temple MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", "Spirit Temple MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", "Spirit Temple MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", "Spirit Temple MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", "Spirit Temple MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", "Spirit Temple MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", "Spirit Temple MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", "Spirit Temple MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", "Spirit Temple MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", "Spirit Temple MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", "Spirit Temple MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Spirit Temple MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", "Spirit Temple MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Shadow Temple Vanilla - locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", "Shadow Temple Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", "Shadow Temple Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", "Shadow Temple Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", "Shadow Temple Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", "Shadow Temple Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", "Shadow Temple Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", "Shadow Temple Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", "Shadow Temple Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", "Shadow Temple Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", "Shadow Temple Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", "Shadow Temple Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", "Shadow Temple After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", "Shadow Temple After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", "Shadow Temple Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", "Shadow Temple Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", "Shadow Temple Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", "Shadow Temple Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", "Shadow Temple Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", "Shadow Temple Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", "Shadow Temple Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", "Shadow Temple Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", "Shadow Temple Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", "Shadow Temple Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", "Shadow Temple Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", "Shadow Temple Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", "Shadow Temple Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", "Shadow Temple Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", "Shadow Temple Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", "Shadow Temple After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", "Shadow Temple After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", "Shadow Temple Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", "Shadow Temple Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", "Shadow Temple Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", "Shadow Temple Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); // Shadow Temple MQ - locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Shadow Temple MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", "Shadow Temple MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", "Shadow Temple MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", "Shadow Temple MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", "Shadow Temple MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", "Shadow Temple MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", "Shadow Temple MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", "Shadow Temple MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", "Shadow Temple MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", "Shadow Temple MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", "Shadow Temple MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", "Shadow Temple MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", "Shadow Temple MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", "Shadow Temple MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", "Shadow Temple MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", "Shadow Temple MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", "Shadow Temple MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", "Shadow Temple MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", "Shadow Temple MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", "Shadow Temple MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Shadow Temple MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", "Shadow Temple MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", "Shadow Temple MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", "Shadow Temple MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", "Shadow Temple MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", "Shadow Temple MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", "Shadow Temple MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", "Shadow Temple MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", "Shadow Temple MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", "Shadow Temple MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", "Shadow Temple MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", "Shadow Temple MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", "Shadow Temple MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", "Shadow Temple MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", "Shadow Temple MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", "Shadow Temple MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", "Shadow Temple MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", "Shadow Temple MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", "Shadow Temple MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", "Shadow Temple MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Bottom of the Well Vanilla - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", "Bottom of the Well Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", "Bottom of the Well Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", "Bottom of the Well Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", "Bottom of the Well Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", "Bottom of the Well Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", "Bottom of the Well Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", "Bottom of the Well Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", "Bottom of the Well Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", "Bottom of the Well Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", "Bottom of the Well Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", "Bottom of the Well Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", "Bottom of the Well Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", "Bottom of the Well Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", "Bottom of the Well Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", "Bottom of the Well Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", "Bottom of the Well Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", "Bottom of the Well Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", "Bottom of the Well Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", "Bottom of the Well Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", "Bottom of the Well Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", "Bottom of the Well Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", "Bottom of the Well Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", "Bottom of the Well Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", "Bottom of the Well Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", "Bottom of the Well Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", "Bottom of the Well Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", "Bottom of the Well Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", "Bottom of the Well Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); // Bottom of the Well Master Quest - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", "Bottom of the Well MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", "Bottom of the Well MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", "Bottom of the Well MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", "Bottom of the Well MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", "Bottom of the Well MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", "Bottom of the Well MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", "Bottom of the Well MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", "Bottom of the Well MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", "Bottom of the Well MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", "Bottom of the Well MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Ice Cavern Vanilla - locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest( RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", "Ice Cavern Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest( RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", "Ice Cavern Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest( RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", "Ice Cavern Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", "Ice Cavern Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", "Ice Cavern Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", "Ice Cavern Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", "Ice Cavern Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", "Ice Cavern Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); // Ice Cavern Master Quest - locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", "Ice Cavern MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", "Ice Cavern MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", "Ice Cavern MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", "Ice Cavern MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", "Ice Cavern MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", "Ice Cavern MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", "Ice Cavern MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", "Ice Cavern MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Gerudo Training Grounds Vanilla - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", "Gerudo Training Grounds Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", "Gerudo Training Grounds Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", "Gerudo Training Grounds Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", "Gerudo Training Grounds Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", "Gerudo Training Grounds Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", "Gerudo Training Grounds Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", "Gerudo Training Grounds Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", "Gerudo Training Grounds Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", "Gerudo Training Grounds Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", "Gerudo Training Grounds Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", "Gerudo Training Grounds Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", "Gerudo Training Grounds Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", "Gerudo Training Grounds Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", "Gerudo Training Grounds Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", "Gerudo Training Grounds Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", "Gerudo Training Grounds Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", "Gerudo Training Grounds Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", "Gerudo Training Grounds Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", "Gerudo Training Grounds Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", "Gerudo Training Grounds Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", "Gerudo Training Grounds Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", "Gerudo Training Grounds Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", "Gerudo Training Grounds Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", "Gerudo Training Grounds Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", "Gerudo Training Grounds Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", "Gerudo Training Grounds Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", "Gerudo Training Grounds Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", "Gerudo Training Grounds Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", "Gerudo Training Grounds Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", "Gerudo Training Grounds Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", "Gerudo Training Grounds Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", "Gerudo Training Grounds Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", "Gerudo Training Grounds Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", "Gerudo Training Grounds Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", "Gerudo Training Grounds Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", "Gerudo Training Grounds Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", "Gerudo Training Grounds Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", "Gerudo Training Grounds Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", "Gerudo Training Grounds Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", "Gerudo Training Grounds Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", "Gerudo Training Grounds Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", "Gerudo Training Grounds Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", "Gerudo Training Grounds Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", "Gerudo Training Grounds Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); // Gerudo Training Grounds Master Quest - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", "Gerudo Training Grounds MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", "Gerudo Training Grounds MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", "Gerudo Training Grounds MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", "Gerudo Training Grounds MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", "Gerudo Training Grounds MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", "Gerudo Training Grounds MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", "Gerudo Training Grounds MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", "Gerudo Training Grounds MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", "Gerudo Training Grounds MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", "Gerudo Training Grounds MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", "Gerudo Training Grounds MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", "Gerudo Training Grounds MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest( RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", "Gerudo Training Grounds MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", "Gerudo Training Grounds MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", "Gerudo Training Grounds MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", "Gerudo Training Grounds MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", "Gerudo Training Grounds MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", "Gerudo Training Grounds MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", "Gerudo Training Grounds MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", "Gerudo Training Grounds MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", "Gerudo Training Grounds MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", "Gerudo Training Grounds MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", "Gerudo Training Grounds MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", "Gerudo Training Grounds MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", "Gerudo Training Grounds MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", "Gerudo Training Grounds MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", "Gerudo Training Grounds MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", "Gerudo Training Grounds MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", "Gerudo Training Grounds MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", "Gerudo Training Grounds MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", "Gerudo Training Grounds MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", "Gerudo Training Grounds MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Ganon's Castle Shared - locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Boss Key Chest", "Ganon's Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Boss Key Chest", "Ganon's Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); // Ganon's Castle Vanilla - locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", "Ganon's Castle Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", "Ganon's Castle Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", "Ganon's Castle Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", "Ganon's Castle Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", "Ganon's Castle Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", "Ganon's Castle Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", "Ganon's Castle Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", "Ganon's Castle Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", "Ganon's Castle Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x06), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x09), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", "Ganon's Castle Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", "Ganon's Castle Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", "Ganon's Castle Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", "Ganon's Castle Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", "Ganon's Castle Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", "Ganon's Castle Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", "Ganon's Castle Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", "Ganon's Castle Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", "Ganon's Castle Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Ganon's Castle MQ - locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", "Ganon's Castle MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", "Ganon's Castle MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", "Ganon's Castle MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", "Ganon's Castle MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", "Ganon's Castle MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", "Ganon's Castle MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", "Ganon's Castle MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x06), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x09), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", "Ganon's Castle MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", "Ganon's Castle MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", "Ganon's Castle MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", "Ganon's Castle MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", "Ganon's Castle MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", "Ganon's Castle MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", "Ganon's Castle MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Gold Skulltula Tokens // Dungeons - // Deku Tree RandomizerCheck RandomizerCheck Quest Area Scene ID params Flag Short Name Spoiler Name Hint Text Key Categories Collection Check Group - locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", "Deku Tree GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", "Deku Tree GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", "Deku Tree GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", "Deku Tree GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", "Deku Tree MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", "Deku Tree MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", "Deku Tree MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", "Deku Tree MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + // Deku Tree + locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", "Deku Tree GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", "Deku Tree GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", "Deku Tree GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", "Deku Tree GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", "Deku Tree MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", "Deku Tree MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", "Deku Tree MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", "Deku Tree MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Dodongo's Cavern - locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", "Dodongos Cavern GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", "Dodongos Cavern GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", "Dodongos Cavern GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", "Dodongos Cavern MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", "Dodongos Cavern MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", "Dodongos Cavern MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", "Dodongos Cavern MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", "Dodongos Cavern MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", "Jabu Jabus Belly GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", "Jabu Jabus Belly GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", "Jabu Jabus Belly GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", "Jabu Jabus Belly GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", "Jabu Jabus Belly MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", "Jabu Jabus Belly MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", "Jabu Jabus Belly MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", "Jabu Jabus Belly MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", "Forest Temple GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", "Forest Temple GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", "Forest Temple GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", "Forest Temple GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", "Forest Temple GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", "Forest Temple MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", "Forest Temple MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", "Forest Temple MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", "Forest Temple MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", "Forest Temple MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", "Dodongos Cavern GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", "Dodongos Cavern GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", "Dodongos Cavern GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", "Dodongos Cavern MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", "Dodongos Cavern MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", "Dodongos Cavern MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", "Dodongos Cavern MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", "Dodongos Cavern MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", "Jabu Jabus Belly GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", "Jabu Jabus Belly GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", "Jabu Jabus Belly GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", "Jabu Jabus Belly GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", "Jabu Jabus Belly MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", "Jabu Jabus Belly MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", "Jabu Jabus Belly MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", "Jabu Jabus Belly MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", "Forest Temple GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", "Forest Temple GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", "Forest Temple GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", "Forest Temple GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", "Forest Temple GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", "Forest Temple MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", "Forest Temple MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", "Forest Temple MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", "Forest Temple MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", "Forest Temple MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Fire Temple - locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", "Fire Temple GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", "Fire Temple GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", "Fire Temple GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", "Fire Temple GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", "Fire Temple GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", "Fire Temple MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", "Fire Temple MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", "Fire Temple MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", "Fire Temple MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", "Fire Temple MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", "Fire Temple GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", "Fire Temple GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", "Fire Temple GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", "Fire Temple GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", "Fire Temple GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", "Fire Temple MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", "Fire Temple MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", "Fire Temple MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", "Fire Temple MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", "Fire Temple MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); // Water Temple - locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", "Water Temple GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", "Water Temple GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", "Water Temple GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", "Water Temple GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", "Water Temple GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", "Water Temple MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", "Water Temple MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", "Water Temple MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", "Water Temple MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", "Water Temple MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", "Water Temple GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", "Water Temple GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", "Water Temple GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", "Water Temple GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", "Water Temple GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", "Water Temple MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", "Water Temple MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", "Water Temple MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", "Water Temple MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", "Water Temple MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); // Spirit Temple - locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", "Spirit Temple GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", "Spirit Temple GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", "Spirit Temple GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", "Spirit Temple GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", "Spirit Temple GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", "Spirit Temple MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", "Spirit Temple MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", "Spirit Temple MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", "Spirit Temple MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", "Spirit Temple MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", "Spirit Temple GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", "Spirit Temple GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", "Spirit Temple GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", "Spirit Temple GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", "Spirit Temple GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", "Spirit Temple MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", "Spirit Temple MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", "Spirit Temple MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", "Spirit Temple MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", "Spirit Temple MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); // Shadow Temple - locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", "Shadow Temple GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", "Shadow Temple GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", "Shadow Temple GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", "Shadow Temple GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", "Shadow Temple GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", "Shadow Temple MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", "Shadow Temple MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", "Shadow Temple MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", "Shadow Temple MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", "Shadow Temple MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", "Shadow Temple GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", "Shadow Temple GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", "Shadow Temple GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", "Shadow Temple GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", "Shadow Temple GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", "Shadow Temple MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", "Shadow Temple MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", "Shadow Temple MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", "Shadow Temple MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", "Shadow Temple MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); // Bottom of the Well - locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", "Bottom of the Well GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", "Bottom of the Well GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", "Bottom of the Well GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", "Bottom of the Well MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", "Bottom of the Well MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", "Bottom of the Well MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", "Bottom of the Well GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", "Bottom of the Well GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", "Bottom of the Well GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", "Bottom of the Well MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", "Bottom of the Well MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", "Bottom of the Well MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); // Ice Cavern - locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", "Ice Cavern GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", "Ice Cavern GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", "Ice Cavern GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", "Ice Cavern MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", "Ice Cavern MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", "Ice Cavern MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", "Ice Cavern GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", "Ice Cavern GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", "Ice Cavern GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", "Ice Cavern MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", "Ice Cavern MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", "Ice Cavern MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); // Overworld - // Kokiri Forest RandomizerCheck RandomizerCheck Quest Area Scene ID params Flag Short Name Spoiler Name Hint Text Key Categories Map Index Collection Check Group - locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", "KF GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", "KF GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", "KF GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + // Kokiri Forest + locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", "KF GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", "KF GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", "KF GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", "LW GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", "LW GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", "SFM GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", "LW GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", "LW GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", "SFM GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", "HF GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", "HF GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", "HF GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", "HF GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); // Lake Hylia - locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", "LH GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", "LH GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", "LH GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", "LH GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", "LH GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", "LH GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", "LH GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", "LH GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", "LH GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", "LH GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", "GV GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", "GV GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", "GV GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", "GV GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", "GV GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", "GV GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", "GV GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", "GV GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", "GF GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", "GF GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", "GF GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", "GF GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Wasteland & Desert Colossus - locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", "Wasteland GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", "Colossus GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", "Colossus GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", "Colossus GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", "Wasteland GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", "Colossus GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", "Colossus GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", "Colossus GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Hyrule Castle, Market, and Outside Ganon's Castle - locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE,11777, 0x01, "OGC GS", "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", "HC GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", "HC GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, 11777, 0x01, "OGC GS", "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", "HC GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", "HC GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Kakariko - locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", "Kak GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", "Kak GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", "Kak GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", "Kak GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", "Kak GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", "Kak GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", "Kak GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", "Kak GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", "Kak GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", "Kak GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", "Kak GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", "Kak GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Graveyard - locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", "Graveyard GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", "Graveyard GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", "Graveyard GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", "Graveyard GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Death Mountain - locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER,28417, 0x01, "GS Bean Patch", "DMC GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER,-28800, 0x80, "GS Crate", "DMC GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", "DMT GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", "DMT GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", "DMT GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", "DMT GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", "GC GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", "GC GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 28417, 0x01, "GS Bean Patch", "DMC GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, -28800, 0x80, "GS Crate", "DMC GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", "DMT GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", "DMT GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", "DMT GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", "DMT GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", "GC GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", "GC GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Zora's River, Domain, and Fountain - locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", "ZR GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", "ZR GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", "ZR GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", "ZR GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", "ZD GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", "ZF GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", "ZF GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", "ZF GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", "ZR GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", "ZR GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", "ZR GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", "ZR GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", "ZD GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", "ZF GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", "ZF GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", "ZF GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Lon Lon Ranch - locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", "LLR GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", "LLR GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", "LLR GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", "LLR GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", "LLR GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", "LLR GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", "LLR GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", "LLR GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - // Bosses Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::AlwaysCollected(), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::Chest(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::Chest(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::Chest(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); + // Bosses + locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_NONE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LINKS_POCKET), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(0x07), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(0x25), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(0x37), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x48), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x49), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x4A), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0xC9), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); - // Heart Containers Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", "Deku Tree Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", "Dodongos Cavern King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", "Jabu Jabus Belly Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", "Forest Temple Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", "Fire Temple Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", "Water Temple Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", "Spirit Temple Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", "Shadow Temple Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + // Heart Containers + locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", "Deku Tree Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", "Dodongos Cavern King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", "Jabu Jabus Belly Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", "Forest Temple Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", "Fire Temple Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", "Water Temple Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", "Spirit Temple Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", "Shadow Temple Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - // Cutscenes Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::MasterSword(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::Chest(0x43, 0x1E), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::Chest(0x3D, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x02), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x03), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x02), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::Chest(0x3B, 0x03), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + // Cutscenes + locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::EventChkInf(0x45), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::EventChkInf(0xC4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::Chest(0x3D, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x02), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x03), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x02), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::Chest(0x3B, 0x03), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - // Songs Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::Chest(0x43, 0x1F), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::Chest(0x63, 0x1F), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::Chest(0x56, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::Chest(0x41, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::Chest(0x51, 0x1F), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x5B), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + // Songs + locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x55), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x00), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x5B), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - //Beehives Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, false); - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", "KF Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, false); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", "LW Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", "LW Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", "LW Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", "SFM Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", "HF Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", "HF Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", "HF Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", "HF Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", "HF Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", "HF Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", "HF Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", "LLR Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, false); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", "Kak Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, false); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", "Kak Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, false); - locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", "DMT Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", "DMT Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", "DMT Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", "GC Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, false); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", "DMC Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", "DMC Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", "DMC Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", "ZR Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", "ZR Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", "ZR Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", "ZD In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", "ZD In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", "ZD Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", "LH Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, false); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", "GV Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, false); - locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", "Colossus Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, false); + //Beehives + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", "KF Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", "LW Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", "LW Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", "LW Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", "SFM Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", "HF Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", "HF Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", "HF Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", "HF Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", "HF Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", "HF Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", "HF Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", "LLR Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", "Kak Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", "Kak Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", "DMT Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", "DMT Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", "DMT Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", "GC Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", "DMC Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", "DMC Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", "DMC Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", "ZR Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", "ZR Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", "ZR Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", "ZD In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", "ZD In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", "ZD Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", "LH Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", "GV Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", "Colossus Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - // Cows Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group - locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", "KF Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x34, 0x15), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", "HF Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x3E, 0x16), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", "LLR Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x36, 0x16), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", "LLR Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x36, 0x15), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", "LLR Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x4C, 0x16), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", "LLR Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x4C, 0x15), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", "Kak Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x37, 0x15), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", "DMT Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x3E, 0x15), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x5A, 0x15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x02, 0x15), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + // Cows + locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", "KF Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", "HF Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", "LLR Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", "LLR Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", "LLR Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", "LLR Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", "Kak Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", "DMT Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); /*------------------------------- --- SHOPS --- @@ -1382,192 +1370,190 @@ void Rando::StaticData::InitLocationTable() { 7 5 1 3 -------------------------------*/ - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Spoiler Collection Check Group // Kokiri Forest - locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", "KF Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", "KF Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", "KF Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", "KF Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", "KF Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", "KF Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", "KF Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", "KF Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", "KF Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", "KF Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", "KF Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", "KF Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", "KF Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", "KF Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", "KF Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", "KF Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Kakariko Village - locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", "Kak Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", "Kak Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", "Kak Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", "Kak Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", "Kak Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", "Kak Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", "Kak Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", "Kak Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", "Kak Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", "Kak Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", "Kak Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", "Kak Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", "Kak Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", "Kak Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", "Kak Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", "Kak Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", "Kak Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", "Kak Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", "Kak Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", "Kak Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", "Kak Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", "Kak Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", "Kak Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", "Kak Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", "Kak Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", "Kak Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", "Kak Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", "Kak Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", "Kak Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", "Kak Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", "Kak Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", "Kak Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Market - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", "MK Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", "MK Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", "MK Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", "MK Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", "MK Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", "MK Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", "MK Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", "MK Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", "MK Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", "MK Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", "MK Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", "MK Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", "MK Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", "MK Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", "MK Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", "MK Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", "MK Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", "MK Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", "MK Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", "MK Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", "MK Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", "MK Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", "MK Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", "MK Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", "MK Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", "MK Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", "MK Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", "MK Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", "MK Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", "MK Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", "MK Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", "MK Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", "MK Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", "MK Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", "MK Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", "MK Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", "MK Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", "MK Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", "MK Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", "MK Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", "MK Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", "MK Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", "MK Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", "MK Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", "MK Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", "MK Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", "MK Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", "MK Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Zora's Domain - locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", "ZD Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", "ZD Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", "ZD Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", "ZD Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", "ZD Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", "ZD Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", "ZD Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", "ZD Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", "ZD Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", "ZD Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", "ZD Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", "ZD Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", "ZD Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", "ZD Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", "ZD Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", "ZD Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Goron City - locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", "GC Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", "GC Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", "GC Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", "GC Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", "GC Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", "GC Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", "GC Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", "GC Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", "GC Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", "GC Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", "GC Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", "GC Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); /* +--------------+ | FISHSANITY | +--------------+ */ - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group - locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + // Fishing Pond + locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Grotto fish - locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER,ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zora's Domain fish - locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Gossip Stones - // RandomizerCheck Randomizer Check Quest Area Scene Params Flag Short Name Spoiler name Categories - locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); - locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); - locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); - locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); - locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); - locationTable[RC_GY_GOSSIP_STONE] = Location::HintStone(RC_GY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); - locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); - locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); - locationTable[RC_KF_STORMS_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); - locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); - locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); - locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); - locationTable[RC_TOT_LEFT_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); - locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); - locationTable[RC_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); - locationTable[RC_JABU_GOSSIP_STONE] = Location::HintStone(RC_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); - locationTable[RC_HF_NEAR_MARKET_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); - locationTable[RC_HF_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); - locationTable[RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); + locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); + locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); + locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); + locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); + locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); + locationTable[RC_GY_GOSSIP_STONE] = Location::HintStone(RC_GY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); + locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); + locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); + locationTable[RC_KF_STORMS_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); + locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); + locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); + locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); + locationTable[RC_TOT_LEFT_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); + locationTable[RC_TOT_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); + locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); + locationTable[RC_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); + locationTable[RC_JABU_GOSSIP_STONE] = Location::HintStone(RC_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); + locationTable[RC_HF_NEAR_MARKET_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); + locationTable[RC_HF_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); + locationTable[RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); // Other Hints - locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); - locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle"); - locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle"); - locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint"); - locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint"); - locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); - locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text"); - locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text"); - locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT,RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint","Fishing Pole Hint"); + locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); + locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle"); + locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle"); + locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint"); + locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint"); + locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); + locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text"); + locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text"); + locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint", "Fishing Pole Hint"); - locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); + locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on } diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 2dc6d2271..8bf50387f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -419,11 +419,8 @@ bool HasItemBeenCollected(RandomizerCheck rc) { case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE: return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) || gSaveContext.sceneFlags[scene].collect & (1 << flag); - case SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT: case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM: - case SpoilerCollectionCheckType::SPOILER_CHK_COW: case SpoilerCollectionCheckType::SPOILER_CHK_FISH: - case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB: case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF: case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD: return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)); @@ -437,8 +434,6 @@ bool HasItemBeenCollected(RandomizerCheck rc) { return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF: return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); - case SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS: - return BEANS_BOUGHT >= 10; case SpoilerCollectionCheckType::SPOILER_CHK_NONE: return false; case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER: @@ -749,11 +744,8 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck(); SpoilerCollectionCheckType scCheckType = scCheck.type; if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF && - (scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW || + (scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) { if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) { @@ -1343,6 +1335,11 @@ void DrawLocation(RandomizerCheck rc) { Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc); RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc]; RandomizerCheckStatus status = checkData.status; + + if (itemLoc->HasObtained()) { + status = RCSHOW_COLLECTED; + } + bool skipped = checkData.skipped; if (status == RCSHOW_COLLECTED) { if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) { @@ -1677,12 +1674,12 @@ void CheckTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook([](uint32_t fileNum) { Teardown(); }); - GameInteractor::Instance->RegisterGameHook(CheckTrackerItemReceive); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerItemReceive); GameInteractor::Instance->RegisterGameHook(CheckTrackerFrame); GameInteractor::Instance->RegisterGameHook(CheckTrackerTransition); GameInteractor::Instance->RegisterGameHook(CheckTrackerShopSlotChange); - GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); - GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1); alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0); diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index fc2c651af..84e60bb23 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -461,34 +461,31 @@ void Entrance_SetWarpSongEntrance(void) { } void Entrance_OverrideBlueWarp(void) { - // Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance - // won't return index 0x7FFF, which can't work to override blue warps. - gPlayState->nextEntranceIndex = 0; + // Handles first time entering bluewarp (with item give) + switch (gSaveContext.entranceIndex) { + case ENTR_KOKIRI_FOREST_11: // Gohma blue warp + case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp + case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp + case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp + case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp + case ENTR_LAKE_HYLIA_9: // Morpha blue warp + case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp + case ENTR_GRAVEYARD_8: // Twinrova blue warp + gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex); + return; + } - switch (gPlayState->sceneNum) { - case SCENE_DEKU_TREE_BOSS: // Ghoma boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_KOKIRI_FOREST_11); - return; - case SCENE_DODONGOS_CAVERN_BOSS: // King Dodongo boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_TRAIL_5); - return; - case SCENE_JABU_JABU_BOSS: // Barinade boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_ZORAS_FOUNTAIN_0); - return; - case SCENE_FOREST_TEMPLE_BOSS: // Phantom Ganon boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_SACRED_FOREST_MEADOW_3); - return; - case SCENE_FIRE_TEMPLE_BOSS: // Volvagia boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_CRATER_5); - return; - case SCENE_WATER_TEMPLE_BOSS: // Morpha boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_LAKE_HYLIA_9); - return; - case SCENE_SPIRIT_TEMPLE_BOSS: // Twinrova boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DESERT_COLOSSUS_8); - return; - case SCENE_SHADOW_TEMPLE_BOSS: // Bongo-Bongo boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_GRAVEYARD_8); + // Handles second+ times entering bluewarp + switch (gPlayState->nextEntranceIndex) { + case ENTR_KOKIRI_FOREST_11: // Gohma blue warp + case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp + case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp + case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp + case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp + case ENTR_LAKE_HYLIA_9: // Morpha blue warp + case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp + case ENTR_GRAVEYARD_8: // Twinrova blue warp + gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex); return; } } diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index c61f933bf..31ca0a805 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -143,12 +143,15 @@ typedef enum { RAND_INF_MERCHANTS_CARPET_SALESMAN, RAND_INF_MERCHANTS_MEDIGORON, RAND_INF_MERCHANTS_GRANNYS_SHOP, + RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN, RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, RAND_INF_ADULT_TRADES_GV_TRADE_SAW, RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD, + RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION, RAND_INF_ADULT_TRADES_LH_TRADE_FROG, RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, + RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, @@ -267,6 +270,13 @@ typedef enum { RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_5, + RAND_INF_LINKS_POCKET, + RAND_INF_LEARNED_EPONA_SONG, + RAND_INF_DARUNIAS_JOY, + RAND_INF_KING_ZORA_THAWED, + RAND_INF_ROLLING_GORON_AS_CHILD, + RAND_INF_ROLLING_GORON_AS_ADULT, + // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index d3c2d535b..19ef26ac0 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -97,6 +97,9 @@ void GiveLinksPocketItem() { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE); StartingItemGive(getItemEntry); + Rando::Context::GetInstance()->GetItemLocation(RC_LINKS_POCKET)->MarkAsObtained(); + // If we re-add the above, we'll get the item on save creation, now it's given on first load + Flags_SetRandomizerInf(RAND_INF_LINKS_POCKET); } } @@ -202,40 +205,42 @@ void SetStartingItems() { } extern "C" void Randomizer_InitSaveFile() { - // Sets all rando flags to false - for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) { - gSaveContext.randomizerInf[i] = 0; - } + // Now handled by cutscene skips + // gSaveContext.cutsceneIndex = 0; // no intro cutscene + // Starts pending ice traps out at 0 before potentially incrementing them down the line. + gSaveContext.pendingIceTrapCount = 0; // Reset triforce pieces collected gSaveContext.triforcePiecesCollected = 0; - gSaveContext.cutsceneIndex = 0; // no intro cutscene - // Starts pending ice traps out at 0 before potentially incrementing them down the line. - gSaveContext.pendingIceTrapCount = 0; - // Set Cutscene flags and texts to skip them - Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); + // Now handled by cutscene skips + // Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO); - Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); - Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); + // Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); - Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); + // Now using this to grant master sword check + // Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); - Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + // Now used to give player LACS rewards + // Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO); Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET); Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE); - Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); - Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); - Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); - Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); + // Now handled by cutscene skips + // Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); + // Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); + // Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); + // Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); // Ruto already met in jabu and spawns down the hole immediately Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); @@ -246,51 +251,55 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + // Now handled by cutscene skips // Skip boss cutscenes - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); - // Entered areas - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); + // Ensure Malon appears at castle first time you enter + // Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // skip the z target talk instructions by the kokiri shop - gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F); + // Now handled by cutscene skips + // gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F); // Go away ruto (water temple first cutscene) gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10); + // Now handled by cutscene skips // no more kaepora - gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest - gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia - gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria - gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria - gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora - gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora + // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest + // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia + // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria + // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria + // gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora + // gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple @@ -398,15 +407,16 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); } - int openForest = Randomizer_GetSettingValue(RSK_FOREST); - switch (openForest) { - case RO_FOREST_OPEN: - Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); - // Fallthrough - case RO_FOREST_CLOSED_DEKU: - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); - break; - } + // Now handled on the fly + // int openForest = Randomizer_GetSettingValue(RSK_FOREST); + // switch (openForest) { + // case RO_FOREST_OPEN: + // Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + // // Fallthrough + // case RO_FOREST_CLOSED_DEKU: + // Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); + // break; + // } int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); switch (doorOfTime) { diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp new file mode 100644 index 000000000..cd34e5608 --- /dev/null +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -0,0 +1,788 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + +extern "C" { +#include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h" +#include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h" +#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h" +#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" +#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h" +#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" +#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h" +#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" +#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h" +#include "src/overlays/actors/ovl_En_Sa/z_en_sa.h" +#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" +#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() + +void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) { + func_80A995CC(enKo, play); + + if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) { + // Typically this doesn't get get live updated in vanilla, but we need to + // live update it if we're skipping a certain cutscene or in randomizer + if (GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { + enKo->collider.dim.height -= 200; + Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos); + enKo->actionFunc = func_80A99384; + } + } +} + +void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { + if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { + Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + func_80078884(NA_SE_SY_CORRECT_CHIME); + enMa1->actor.flags &= ~ACTOR_FLAG_WILL_TALK; + play->msgCtx.ocarinaMode = OCARINA_MODE_04; + enMa1->actionFunc = func_80AA0D88; + enMa1->unk_1E0 = 1; + enMa1->interactInfo.talkState = NPC_TALK_STATE_IDLE; + return; + } +} + +u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) { + return 0x207D; +} + +void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { + if (enZl4->csState == 0 && enZl4->actor.xzDistToPlayer < 600.0f && EnZl4_SetNextAnim(enZl4, 3)) { + Audio_PlayFanfare(NA_BGM_APPEAR); + enZl4->csState = 8; // ZL4_CS_PLAN + } else { + Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); + func_80B5BB78(enZl4, play); + + if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { + enZl4->talkState = 6; + enZl4->actionFunc = EnZl4_Cutscene; + } + } +} + +static int successChimeCooldown = 0; +void RateLimitedSuccessChime() { + if (successChimeCooldown == 0) { + func_80078884(NA_SE_SY_CORRECT_CHIME); + successChimeCooldown = 120; + } +} + +void TimeSaverOnGameFrameUpdateHandler() { + if (successChimeCooldown > 0) { + successChimeCooldown--; + } +} + +void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { + switch (id) { + case GI_VB_PLAY_TRANSITION_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } + + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + // Song of Time + if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) { + gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_16; + gSaveContext.cutsceneIndex = 0; + gSaveContext.nextTransitionType = 3; + *should = false; + } + + // Requiem of Spirit + if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); + // Normally happens in the cutscene + if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + Item_Give(gPlayState, ITEM_SONG_REQUIEM); + } + *should = false; + } + + u8 meetsBurningKakRequirements = + LINK_IS_ADULT && + gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, meetsBurningKakRequirements, NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + // Normally happens in the cutscene + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + Item_Give(gPlayState, ITEM_SONG_NOCTURNE); + } + *should = false; + } + } + + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + uint8_t isBlueWarp = 0; + // Deku Tree Blue warp + if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11; + isBlueWarp = 1; + // Dodongo's Cavern Blue warp + } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; + isBlueWarp = 1; + // Jabu Jabu's Blue warp + } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_0 && gSaveContext.cutsceneIndex == 0xFFF0) { + gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_0; + isBlueWarp = 1; + // Forest Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { + // Normally set in the blue warp cutscene + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + + gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3; + isBlueWarp = 1; + // Fire Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; + isBlueWarp = 1; + // Water Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { + gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; + isBlueWarp = 1; + // Spirit Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { + gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_8; + isBlueWarp = 1; + // Shadow Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { + gSaveContext.entranceIndex = ENTR_GRAVEYARD_8; + isBlueWarp = 1; + } + + if (isBlueWarp) { + *should = false; + gSaveContext.cutsceneIndex = 0; + + if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { + Entrance_OverrideBlueWarp(); + } + } + + // Flee hyrule castle cutscene + if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } + + // Lost Woods Bridge + if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { + Item_Give(gPlayState, ITEM_OCARINA_FAIRY); + } + *should = false; + } + + // LACS + u8 meetsLACSRequirements = + LINK_IS_ADULT && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements, NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + Item_Give(gPlayState, ITEM_ARROW_LIGHT); + } + *should = false; + } + } + break; + case GI_VB_PLAY_ENTRANCE_CS: { + s32* entranceFlag = static_cast(opt); + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { + *should = false; + } + break; + } + case GI_VB_PLAY_ONEPOINT_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) { + s16* csId = static_cast(opt); + switch (*csId) { + case 4180: + case 4100: + *should = false; + RateLimitedSuccessChime(); + break; + default: + SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_CS {}", *csId); + break; + } + } + break; + } + case GI_VB_PLAY_ONEPOINT_ACTOR_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) { + Actor* actor = static_cast(opt); + switch (actor->category) { + case ACTORCAT_BG: + if (actor->id == ACTOR_BG_DDAN_KD) { + BgDdanKd* ddanKd = static_cast(opt); + Flags_SetSwitch(gPlayState, ddanKd->dyna.actor.params); + } + if (actor->id == ACTOR_BG_MORI_HINERI) { + break; + } + + RateLimitedSuccessChime(); + *should = false; + break; + } + switch (actor->id) { + case ACTOR_OBJ_SWITCH: { + ObjSwitch *switchActor = static_cast(opt); + switchActor->cooldownTimer = 0; + *should = false; + RateLimitedSuccessChime(); + break; + } + case ACTOR_BG_BDAN_SWITCH: { + BgBdanSwitch* switchActor = static_cast(opt); + switchActor->unk_1D8 = 0; + switchActor->unk_1DA = 0; + *should = false; + RateLimitedSuccessChime(); + break; + } + // case ACTOR_PLAYER: // This might cause issues + case ACTOR_EN_TA: + case ACTOR_DOOR_SHUTTER: + case ACTOR_EN_BOX: + case ACTOR_OBJ_SYOKUDAI: + case ACTOR_OBJ_TIMEBLOCK: + case ACTOR_EN_PO_SISTERS: + // Prop + case ACTOR_OBJ_ICE_POLY: + case ACTOR_BG_YDAN_MARUTA: + case ACTOR_BG_SPOT18_SHUTTER: + case ACTOR_BG_SPOT05_SOKO: + case ACTOR_BG_SPOT18_BASKET: + // BG + // case ACTOR_BG_YDAN_SP: + // case ACTOR_BG_YDAN_HASI: + // case ACTOR_BG_DODOAGO: + // case ACTOR_BG_DDAN_KD: + // case ACTOR_BG_DDAN_JD: + *should = false; + RateLimitedSuccessChime(); + break; + } + if (*should) { + SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category); + } + } + break; + } + case GI_VB_SHOW_TITLE_CARD: + if (CVarGetInteger("gTimeSavers.DisableTitleCard", 0)) { + *should = false; + } + break; + case GI_VB_WONDER_TALK: { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) { + *should = false; + } + break; + } + case GI_VB_NAVI_TALK: { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) { + ElfMsg* naviTalk = static_cast(opt); + Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F); + Actor_Kill(&naviTalk->actor); + *should = false; + } + break; + } + case GI_VB_NOT_BE_GREETED_BY_SARIA: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); + *should = true; + } + break; + case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + if ( + CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && + !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && + (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && + (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) + ) { + Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + *should = true; + } + break; + case GI_VB_PLAY_DEKU_TREE_INTRO_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + BgTreemouth* treeMouth = static_cast(opt); + Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); + Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + BgTreemouth_SetupAction(treeMouth, func_808BC6F8); + *should = false; + } + break; + } + case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: + case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: + case GI_VB_GIVE_ITEM_FAIRY_OCARINA: + case GI_VB_GIVE_ITEM_LIGHT_ARROW: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + *should = false; + } + break; + case GI_VB_PLAY_NABOORU_CAPTURED_CS: + if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA); + *should = false; + } + break; + case GI_VB_PLAY_PULL_MASTER_SWORD_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { + // Normally, these would be done in the cutscene, but we're skipping it + Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); + Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); + Flags_SetEventChkInf(EVENTCHKINF_TIME_TRAVELED_TO_ADULT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + Item_Give(gPlayState, ITEM_MEDALLION_LIGHT); + } + } + *should = false; + } + break; + case GI_VB_OWL_INTERACTION: { + if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) && *should) { + EnOwl* enOwl = static_cast(opt); + s32 owlType = (enOwl->actor.params & 0xFC0) >> 6; + + if (((enOwl->actor.params & 0xFC0) >> 6) == 1) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_KAEPORA_BY_LOST_WOODS); + } + + func_80ACA62C(enOwl, gPlayState); + *should = false; + } + break; + } + case GI_VB_PLAY_EYEDROP_CREATION_ANIM: + case GI_VB_PLAY_EYEDROPS_CS: + case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS: + case GI_VB_PLAY_DARUNIAS_JOY_CS: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + *should = false; + } + break; + case GI_VB_PLAY_ZELDAS_LULLABY_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + DemoIm* demoIm = static_cast(opt); + Player* player = GET_PLAYER(gPlayState); + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; + player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM; + func_80986794(demoIm); + + static uint32_t demoImUpdateHook = 0; + static uint32_t demoImKillHook = 0; + demoImUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* actorRef) mutable { + Actor* actor = static_cast(actorRef); + if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + DemoIm* demoIm = static_cast(actorRef); + Player* player = GET_PLAYER(gPlayState); + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; + player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM; + + if (Animation_OnFrame(&demoIm->skelAnime, 25.0f)) { + Audio_PlaySoundGeneral(NA_SE_IT_DEKU, &demoIm->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); + GameInteractor::Instance->UnregisterGameHook(demoImUpdateHook); + GameInteractor::Instance->UnregisterGameHook(demoImKillHook); + demoImUpdateHook = 0; + demoImKillHook = 0; + } else if (Animation_OnFrame(&demoIm->skelAnime, 15.0f)) { + Player* player = GET_PLAYER(gPlayState); + // SOH [Randomizer] In entrance rando have impa bring link back to the front of castle grounds + if (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { + gPlayState->nextEntranceIndex = ENTR_HYRULE_CASTLE_0; + } else { + gPlayState->nextEntranceIndex = ENTR_HYRULE_FIELD_17; + } + gPlayState->transitionType = TRANS_TYPE_FADE_WHITE; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.nextTransitionType = 2; + func_8002DF54(gPlayState, &player->actor, 8); + } + } + }); + demoImKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(demoImUpdateHook); + GameInteractor::Instance->UnregisterGameHook(demoImKillHook); + demoImUpdateHook = 0; + demoImKillHook = 0; + }); + *should = false; + } + break; + } + case GI_VB_PLAY_SARIAS_SONG_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + EnSa* enSa = static_cast(opt); + enSa->actionFunc = func_80AF6B20; + *should = false; + } + break; + } + case GI_VB_DESPAWN_HORSE_RACE_COW: { + if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger("gCowOfTime", 0)) { + *should = false; + } + break; + } + case GI_VB_GIVE_ITEM_MINUET_OF_FOREST: + case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE: + case GI_VB_GIVE_ITEM_SERENADE_OF_WATER: + case GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT: + case GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW: + case GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT: + case GI_VB_GIVE_ITEM_ZELDAS_LULLABY: + case GI_VB_GIVE_ITEM_EPONAS_SONG: + case GI_VB_GIVE_ITEM_SARIAS_SONG: + case GI_VB_GIVE_ITEM_SUNS_SONG: + case GI_VB_GIVE_ITEM_SONG_OF_TIME: + case GI_VB_GIVE_ITEM_SONG_OF_STORMS: + case GI_VB_PLAY_MINUET_OF_FOREST_CS: + case GI_VB_PLAY_BOLERO_OF_FIRE_CS: + case GI_VB_PLAY_SERENADE_OF_WATER_CS: + case GI_VB_PLAY_PRELUDE_OF_LIGHT_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + *should = false; + } + break; + case GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN: + if (CVarGetInteger("gDampeAllNight", 0)) { + *should = LINK_IS_ADULT || gPlayState->sceneNum != SCENE_GRAVEYARD; + } + break; + case GI_VB_BE_VALID_GRAVEDIGGING_SPOT: + if (CVarGetInteger("gDampeWin", 0)) { + EnTk *enTk = static_cast(opt); + enTk->validDigHere = true; + *should = true; + } + break; + case GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: + if (CVarGetInteger("gDampeWin", 0)) { + EnTk *enTk = static_cast(opt); + enTk->currentReward = 3; + *should = true; + } + break; + case GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE: + if (CVarGetInteger("gGravediggingTourFix", 0) || IS_RANDO) { + *should = !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE); + } + break; + case GI_VB_FIX_SAW_SOFTLOCK: + // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw + // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. + *should = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should; + break; + case GI_VB_BIGGORON_CONSIDER_SWORD_FORGED: + *should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3); + break; + } +} + +static uint32_t enKoUpdateHook = 0; +static uint32_t enKoKillHook = 0; +static uint32_t itemOcarinaUpdateHook = 0; +static uint32_t itemOcarinaframesSinceSpawn = 0; +static uint32_t enMa1UpdateHook = 0; +static uint32_t enMa1KillHook = 0; +void TimeSaverOnActorInitHandler(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) { + enKoUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) || IS_RANDO)) { + EnKo* enKo = static_cast(innerActorRef); + // They haven't moved yet, wrap their update function so we check every frame + if (enKo->actionFunc == func_80A995CC) { + enKo->actionFunc = EnKo_MoveWhenReady; + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + // They have already moved + } else if (enKo->actionFunc == func_80A99384) { + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + } + } + }); + enKoKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + }); + } + + if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + itemOcarinaframesSinceSpawn = 0; + itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id != ACTOR_ITEM_OCARINA || innerActor->params != 3) return; + itemOcarinaframesSinceSpawn++; + if (itemOcarinaframesSinceSpawn > 20) { + Audio_PlayActorSound2(innerActor, NA_SE_EV_BOMB_DROP_WATER); + + GameInteractor::Instance->UnregisterGameHook(itemOcarinaUpdateHook); + itemOcarinaUpdateHook = 0; + } + }); + } + + if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) { + enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + EnMa1* enMa1 = static_cast(innerActorRef); + if (enMa1->actionFunc == func_80AA106C) { + enMa1->actionFunc = EnMa1_EndTeachSong; + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + // They've already learned the song + } else if (enMa1->actionFunc == func_80AA0D88) { + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + } + } + }); + enMa1KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + }); + } + + if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + EnZl4* enZl4 = static_cast(actorRef); + if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; + + enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; + } +} + +void TimeSaverOnSceneInitHandler(int16_t sceneNum) { + switch (sceneNum) { + case SCENE_HYRULE_CASTLE: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); + } + break; + case SCENE_LON_LON_RANCH: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); + Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); + Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); + } + break; + case SCENE_DEKU_TREE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); + } + } + break; + case SCENE_DODONGOS_CAVERN_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); + } + } + break; + case SCENE_JABU_JABU_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); + } + } + break; + } +} + +static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; + +void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { + if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) return; + + switch (flagType) { + case FLAG_EVENT_CHECK_INF: + switch (flag) { + case EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FAIRY_OCARINA).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_ZELDAS_LULLABY: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZELDAS_LULLABY).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_MINUET_OF_FOREST: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MINUET_OF_FOREST).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_BOLERO_OF_FIRE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_BOLERO_OF_FIRE).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SERENADE_OF_WATER: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SERENADE_OF_WATER).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_REQUIEM_OF_SPIRIT).GetGIEntry_Copy(); + break; + case EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NOCTURNE_OF_SHADOW).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_PRELUDE_OF_LIGHT).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SARIAS_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SARIAS_SONG).GetGIEntry_Copy(); + break; + case EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_GORON_RUBY).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZORA_SAPPHIRE).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FOREST_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FIRE_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_WATER_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_ARROWS).GetGIEntry_Copy(); + break; + case EVENTCHKINF_TIME_TRAVELED_TO_ADULT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SONG_OF_TIME: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy(); + break; + } + break; + case FLAG_RANDOMIZER_INF: + switch (flag) { + case RAND_INF_LEARNED_EPONA_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_EPONAS_SONG).GetGIEntry_Copy(); + break; + case RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SHADOW_MEDALLION).GetGIEntry_Copy(); + break; + case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy(); + break; + } + break; + } +} + +void TimeSaverOnPlayerUpdateHandler() { + if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return; + + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + SPDLOG_INFO("Attempting to give Item: mod {} item {}", vanillaQueuedItemEntry.modIndex, vanillaQueuedItemEntry.itemId); + GiveItemEntryWithoutActor(gPlayState, vanillaQueuedItemEntry); + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { + // Allow the player to receive the item while swimming + player->stateFlags2 |= PLAYER_STATE2_UNDERWATER; + func_8083E5A8(player, gPlayState); + } +} + +void TimeSaverOnItemReceiveHandler(GetItemEntry receivedItemEntry) { + if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return; + + if (vanillaQueuedItemEntry.modIndex == receivedItemEntry.modIndex && vanillaQueuedItemEntry.itemId == receivedItemEntry.itemId) { + SPDLOG_INFO("Item received: mod {} item {}", receivedItemEntry.modIndex, receivedItemEntry.itemId); + vanillaQueuedItemEntry = GET_ITEM_NONE; + } +} + +static uint32_t onSceneInitHook = 0; +static uint32_t onVanillaBehaviorHook = 0; +static uint32_t onActorInitHook = 0; +static uint32_t onGameFrameUpdate = 0; +static uint32_t onFlagSetHook = 0; +static uint32_t onPlayerUpdateHook = 0; +static uint32_t onItemReceiveHook = 0; +void TimeSaverRegisterHooks() { + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) mutable { + vanillaQueuedItemEntry = GET_ITEM_NONE; + + GameInteractor::Instance->UnregisterGameHook(onSceneInitHook); + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + GameInteractor::Instance->UnregisterGameHook(onActorInitHook); + GameInteractor::Instance->UnregisterGameHook(onGameFrameUpdate); + GameInteractor::Instance->UnregisterGameHook(onFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateHook); + GameInteractor::Instance->UnregisterGameHook(onItemReceiveHook); + + onSceneInitHook = 0; + onVanillaBehaviorHook = 0; + onActorInitHook = 0; + onGameFrameUpdate = 0; + onFlagSetHook = 0; + onPlayerUpdateHook = 0; + onItemReceiveHook = 0; + + onSceneInitHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnSceneInitHandler); + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnVanillaBehaviorHandler); + onActorInitHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnActorInitHandler); + onGameFrameUpdate = GameInteractor::Instance->RegisterGameHook(TimeSaverOnGameFrameUpdateHandler); + + if (IS_RANDO) return; + + onFlagSetHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnFlagSetHandler); + onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnPlayerUpdateHandler); + onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnItemReceiveHandler); + }); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.h b/soh/soh/Enhancements/timesaver_hook_handlers.h new file mode 100644 index 000000000..41bccd8d9 --- /dev/null +++ b/soh/soh/Enhancements/timesaver_hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef TIMESAVER_HOOK_HANDLERS_H +#define TIMESAVER_HOOK_HANDLERS_H + +void TimeSaverRegisterHooks(); + +#endif // TIMESAVER_HOOK_HANDLERS_H \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 38da2015b..334b99949 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -122,6 +122,10 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/config/ConfigUpdaters.h" +extern "C" { +#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" +} + void SoH_ProcessDroppedFiles(std::string filePath); OTRGlobals* OTRGlobals::Instance; @@ -2567,9 +2571,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) - } else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) { - RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); + } else if (textId == TEXT_SCRUB_RANDOM) { + EnDns* enDns = (EnDns*)GET_PLAYER(play)->targetActor; + messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(enDns->sohScrubIdentity.randomizerInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index daae87146..e42e16b3f 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -351,6 +351,13 @@ void SaveManager::LoadRandomizerVersion3() { // all ItemLocations is 0 anyway. randoContext->GetItemLocation(i)->SetCustomPrice(price); } + uint16_t obtained = 0; + SaveManager::Instance->LoadData("obtained", obtained, (uint16_t)0); + if (obtained) { + randoContext->GetItemLocation(i)->MarkAsObtained(); + } else { + randoContext->GetItemLocation(i)->MarkAsNotObtained(); + } }); }); @@ -449,6 +456,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f if (randoContext->GetItemLocation(i)->HasCustomPrice()) { SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); } + SaveManager::Instance->SaveData("obtained", randoContext->GetItemLocation(i)->HasObtained()); }); }); @@ -727,6 +735,9 @@ void SaveManager::InitFileNormal() { for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) { gSaveContext.infTable[flag] = 0; } + for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.randomizerInf); flag++) { + gSaveContext.randomizerInf[flag] = 0; + } gSaveContext.worldMapAreaData = 0; gSaveContext.scarecrowLongSongSet = 0; for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 56e12e53e..2ec571e26 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -69,6 +69,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large }; static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" }; + static const char* skipGetItemAnimationOptions[3] = { "Disabled", "Junk Items", "All Items" }; static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" }; static const char* mirroredWorldModes[9] = { "Disabled", "Always", "Random", "Random (Seeded)", "Dungeons", @@ -555,6 +556,83 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); ImGui::Text("Speed-ups:"); UIWidgets::PaddedSeparator(); + bool allChecked = + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) && + CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) && + CVarGetInteger("gTimeSavers.NoForcedDialog", 0) && + CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) && + CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && + CVarGetInteger("gTimeSavers.DisableTitleCard", 0); + bool someChecked = + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) || + CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) || + CVarGetInteger("gTimeSavers.NoForcedDialog", 0) || + CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) || + CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) || + CVarGetInteger("gTimeSavers.DisableTitleCard", 0); + + ImGuiContext* g = ImGui::GetCurrentContext(); + ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; + if (!allChecked && someChecked) g->CurrentItemFlags |= ImGuiItemFlags_MixedValue; + if (ImGui::Checkbox("All", &allChecked)) { + if (allChecked) { + CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1); + CVarSetInteger("gTimeSavers.NoForcedDialog", 1); + CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1); + CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1); + CVarSetInteger("gTimeSavers.DisableTitleCard", 1); + } else { + CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0); + CVarSetInteger("gTimeSavers.NoForcedDialog", 0); + CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0); + CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0); + CVarSetInteger("gTimeSavers.DisableTitleCard", 0); + } + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } + g->CurrentItemFlags = backup_item_flags; + UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro"); + UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances"); + UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story"); + UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong"); + UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro"); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding"); + UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); + UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint"); + UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog"); + UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs"); + UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions"); + UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions"); + UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard"); + + UIWidgets::PaddedText("Skip Get Item Animations", true, false); + UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED); + if (CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) != SGIA_DISABLED) { + UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", "gTimeSavers.SkipGetItemAnimationScale", 5.0f, 15.0f, "", 10.0f, false); + UIWidgets::Tooltip("The size of the item when it is picked up"); + } UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true); @@ -565,37 +643,8 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); - UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); - UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); - UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); - UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); - static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, - forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); - UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); - UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); - UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); - UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false); - UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); - UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false); - UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); - - ImGui::TableNextColumn(); - UIWidgets::Spacer(0); - ImGui::Text("Changes:"); - UIWidgets::PaddedSeparator(); - - UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); - UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); - UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); - UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" - "This doesn't work if the save was made in a grotto."); - UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); - UIWidgets::Tooltip("Prevent forced Navi conversations"); - UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false); - UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. "); + UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); + UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); @@ -1164,7 +1213,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); - UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false, SaveManager::Instance->IsRandoFile(), + "This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 9c0dd9b05..94b04580f 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -32,6 +32,7 @@ #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" u16 D_8011E1C0 = 0; u16 D_8011E1C4 = 0; @@ -485,6 +486,7 @@ void func_80065134(PlayState* play, CutsceneContext* csCtx, CsCmdDayTime* cmd) { gSaveContext.dayTime = temp1 + temp2; gSaveContext.skyboxTime = temp1 + temp2; + LUSLOG_INFO("SET TIME %d", gSaveContext.dayTime); } } @@ -493,11 +495,16 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB Player* player = GET_PLAYER(play); s32 temp = 0; - // Automatically skip certain cutscenes when in rando - // cmd->base == 8: Traveling back/forward in time cutscene - // cmd->base == 24: Dropping a fish for Jabu Jabu - // cmd->base == 33: Zelda escaping with impa cutscene - bool randoCsSkip = (IS_RANDO && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33)); + bool shouldSkipCommand = false; + + if (cmd->base == 8 && !GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) { + shouldSkipCommand = true; + } + + if (cmd->base == 24 && !GameInteractor_Should(GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) { + shouldSkipCommand = true; + } + bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) && (gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0)); @@ -558,7 +565,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB } } - if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) { + if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (shouldSkipCommand || debugCsSkip))) { csCtx->state = CS_STATE_UNSKIPPABLE_EXEC; Audio_SetCutsceneFlag(0); @@ -624,7 +631,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB gSaveContext.fw.set = 0; gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0; } - if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { + if (GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0; play->transitionTrigger = TRANS_TRIGGER_START; @@ -716,7 +723,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_WHITE; break; case 22: - Item_Give(play, ITEM_SONG_REQUIEM); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + Item_Give(play, ITEM_SONG_REQUIEM); + } play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.cutsceneIndex = 0xFFF0; @@ -768,7 +777,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_WHITE; - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } gSaveContext.chamberCutsceneNum = 1; break; case 31: @@ -848,7 +859,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; break; case 47: - Item_Give(play, ITEM_SONG_NOCTURNE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + Item_Give(play, ITEM_SONG_NOCTURNE); + } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; play->transitionTrigger = TRANS_TRIGGER_START; @@ -1292,7 +1305,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB break; } - if (randoCsSkip) { + if (shouldSkipCommand && IS_RANDO) { Entrance_OverrideCutsceneEntrance(cmd->base); } } @@ -1561,7 +1574,49 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText } else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { Message_StartTextbox(play, cmd->textId1, NULL); } else { + GetItemEntry getItemEntry = GET_ITEM_NONE; + if (IS_RANDO) { + switch (cmd->base) { + case 0x80: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD); + break; + case 0x81: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY); + break; + case 0x82: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + break; + case 0x3E: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION); + break; + case 0x3C: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION); + break; + case 0x3D: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION); + break; + case 0x3F: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION); + break; + case 0x41: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION); + break; + case 0x40: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION); + break; + case 0x72: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS); + break; + } + if (getItemEntry.getItemId != GI_NONE) { + // cmd->base = getItemEntry.textId; + // GET_PLAYER(play)->getItemEntry = getItemEntry; + } + } Message_StartTextbox(play, cmd->base, NULL); + if (IS_RANDO && getItemEntry.getItemId != GI_NONE) { + // GET_PLAYER(play)->getItemEntry = (GetItemEntry)GET_ITEM_NONE; + } } return; } @@ -1584,12 +1639,14 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { if (play->msgCtx.choiceIndex == 0) { if (cmd->textId1 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox D: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId1); } else { csCtx->frames++; } } else { if (cmd->textId2 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox E: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId2); } else { csCtx->frames++; @@ -1599,6 +1656,7 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText if (dialogState == TEXT_STATE_9) { if (cmd->textId1 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox F: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId1); } else { csCtx->frames++; @@ -2113,34 +2171,23 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) { u8 requiredAge; s16 i; - if (IS_RANDO && - // don't skip epona escape cutscenes - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_11 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_12 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_13 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_15 && - // don't skip nabooru iron knuckle cs - gSaveContext.entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_0) { - gSaveContext.showTitleCard = false; - return; - } - for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) { entranceCutscene = &sEntranceCutsceneTable[i]; - requiredAge = entranceCutscene->ageRestriction; if (requiredAge == 2) { requiredAge = gSaveContext.linkAge; } if ((gSaveContext.entranceIndex == entranceCutscene->entrance) && - (!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == 0x18)) && + (!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == EVENTCHKINF_EPONA_OBTAINED)) && (gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) && (gSaveContext.respawnFlag <= 0)) { Flags_SetEventChkInf(entranceCutscene->flag); - Cutscene_SetSegment(play, entranceCutscene->segAddr); - gSaveContext.cutsceneTrigger = 2; - gSaveContext.showTitleCard = false; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) { + Cutscene_SetSegment(play, entranceCutscene->segAddr); + gSaveContext.cutsceneTrigger = 2; + gSaveContext.showTitleCard = false; + } break; } } @@ -2148,48 +2195,48 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) { void Cutscene_HandleConditionalTriggers(PlayState* play) { osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag)); + LUSLOG_INFO("Cutscene_HandleConditionalTriggers - entranceIndex: %#x cutsceneIndex: %#x", gSaveContext.entranceIndex, gSaveContext.cutsceneIndex); + + if (!GameInteractor_Should(GI_VB_PLAY_TRANSITION_CS, true, NULL)) { + return; + } if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { - const bool bShouldTowerRandoSkip = - (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE)); if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); - gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; - gSaveContext.cutsceneIndex = 0xFFF0; - } - } else if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && LINK_IS_ADULT && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) && - (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) && (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) && - !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); - gSaveContext.cutsceneIndex = 0xFFF0; - } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); + gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; + gSaveContext.cutsceneIndex = 0xFFF0; + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, ( + (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && + LINK_IS_ADULT && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) + ), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + gSaveContext.cutsceneIndex = 0xFFF0; } else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { Item_Give(play, ITEM_OCARINA_FAIRY); - gSaveContext.entranceIndex = ENTR_LOST_WOODS_0; - gSaveContext.cutsceneIndex = 0xFFF0; } - } else if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); - gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0; - gSaveContext.cutsceneIndex = 0xFFF8; - } - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && - gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS) || - (bShouldTowerRandoSkip && - gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) { + gSaveContext.entranceIndex = ENTR_LOST_WOODS_0; + gSaveContext.cutsceneIndex = 0xFFF0; + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, ( + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + LINK_IS_ADULT && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) + ), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0; + gSaveContext.cutsceneIndex = 0xFFF8; + } else if (!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS)) { Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; - // In rando, skip the cutscene for the tower falling down after the escape. - if (IS_RANDO) { - return; - } gSaveContext.cutsceneIndex = 0xFFF0; } } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 77f42aebd..da7454961 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -349,6 +350,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { s32 getItemId = GI_NONE; this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE; this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK; + this->itemEntry = (GetItemEntry)GET_ITEM_NONE; s16 spawnParam8000 = this->actor.params & 0x8000; s32 pad1; @@ -358,7 +360,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.params &= 0xFF; - if (Flags_GetCollectible(play, this->collectibleFlag)) { + if (GameInteractor_Should(GI_VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) { Actor_Kill(&this->actor); return; } @@ -381,12 +383,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->unk_158 = 0; Actor_SetScale(&this->actor, 0.03f); this->scale = 0.03f; - // Offset keys in randomizer slightly higher for their GID replacement - if (!IS_RANDO) { - yOffset = 350.0f; - } else { - yOffset = 430.0f; - } + yOffset = 350.0f; break; case ITEM00_HEART_PIECE: this->unk_158 = 0; @@ -479,6 +476,14 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { Actor_SetScale(&this->actor, 0.03f); this->scale = 0.03f; break; + case ITEM00_SOH_GIVE_ITEM_ENTRY: + case ITEM00_SOH_GIVE_ITEM_ENTRY_GI: + case ITEM00_SOH_DUMMY: + this->unk_158 = 0; + Actor_SetScale(&this->actor, 0.03f); + this->scale = 0.03f; + yOffset = 430.0f; + break; } this->unk_156 = 0; @@ -507,6 +512,10 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.velocity.y = 0.0f; this->actor.gravity = 0.0f; + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + return; + } + switch (this->actor.params) { case ITEM00_RUPEE_GREEN: Item_Give(play, ITEM_RUPEE_GREEN); @@ -576,16 +585,8 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { break; } - if (!Actor_HasParent(&this->actor, play)) { - if (getItemId != GI_NONE) { - if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) { - func_8002F554(&this->actor, play, getItemId); - } else { - if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } - } + if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) { + func_8002F554(&this->actor, play, getItemId); } EnItem00_SetupAction(this, func_8001E5C8); @@ -603,8 +604,7 @@ void func_8001DFC8(EnItem00* this, PlayState* play) { (this->actor.params == ITEM00_HEART_PIECE)) { this->actor.shape.rot.y += 960; } else { - if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && - (this->actor.params != ITEM00_BOMBCHU)) { + if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) { if (this->unk_15A == -1) { if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) == 0) { @@ -697,8 +697,7 @@ void func_8001E304(EnItem00* this, PlayState* play) { if (this->actor.params <= ITEM00_RUPEE_RED) { this->actor.shape.rot.y += 960; - } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && - (this->actor.params != ITEM00_BOMBCHU)) { + } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) { this->actor.world.rot.x -= 700; this->actor.shape.rot.y += 400; this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000; @@ -733,13 +732,7 @@ void func_8001E5C8(EnItem00* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->getItemId != GI_NONE) { if (!Actor_HasParent(&this->actor, play)) { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f); - } else { - if (GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } + func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f); this->unk_15A++; } else { this->getItemId = GI_NONE; @@ -781,13 +774,15 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { s32 pad; // Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect - if ((this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || + if ( + (this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || (this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) || - this->actor.params == ITEM00_BOMBS_A || this->actor.params == ITEM00_ARROWS_SINGLE || - this->actor.params == ITEM00_BOMBS_SPECIAL || this->actor.params == ITEM00_BOMBCHU) { - if (CVarGetInteger("gNewDrops", 0) || - // Keys in randomizer need to always rotate for their GID replacement - (IS_RANDO && this->actor.params == ITEM00_SMALL_KEY)) { + this->actor.params == ITEM00_BOMBS_A || + this->actor.params == ITEM00_ARROWS_SINGLE || + this->actor.params == ITEM00_BOMBS_SPECIAL || + (this->actor.params >= ITEM00_BOMBCHU && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI) + ) { + if (CVarGetInteger("gNewDrops", 0) || (this->actor.params >= ITEM00_SOH_DUMMY && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)) { this->actor.shape.rot.y += 960; } else { this->actor.shape.rot.y = 0; @@ -871,6 +866,10 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { return; } + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + return; + } + switch (this->actor.params) { case ITEM00_RUPEE_GREEN: Item_Give(play, ITEM_RUPEE_GREEN); @@ -955,14 +954,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { params = &this->actor.params; if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) { - if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) { - func_8002F554(&this->actor, play, getItemId); - } else { - getItemId = this->randoGiEntry.getItemId; - if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } + func_8002F554(&this->actor, play, getItemId); } switch (*params) { @@ -1052,7 +1044,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { } break; case ITEM00_HEART_PIECE: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger("gNewDrops", 0)) { mtxScale = 21.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_HEART_PIECE); @@ -1162,7 +1154,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { break; } case ITEM00_SMALL_KEY: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger("gNewDrops", 0)) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_KEY_SMALL); @@ -1368,17 +1360,7 @@ static const Vtx customDropVtx[] = { * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). */ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { - if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { - if (this->randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } - - f32 mtxScale = 10.67f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); - } else if (this->actor.params == ITEM00_BOMBCHU) { + if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -1458,29 +1440,17 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) { * Draw Function used for the Piece of Heart type of En_Item00. */ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { - if (IS_RANDO) { - if (this->randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } + s32 pad; - f32 mtxScale = 16.0f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); - } else { - s32 pad; + OPEN_DISPS(play->state.gfxCtx); - OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + func_8002ED80(&this->actor, play, 0); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL); - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - func_8002ED80(&this->actor, play, 0); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL); - - CLOSE_DISPS(play->state.gfxCtx); - } + CLOSE_DISPS(play->state.gfxCtx); } /** diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 4c661aad7..1d00f73bb 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2603,8 +2603,23 @@ void Message_DrawMain(PlayState* play, Gfx** p) { msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state; msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS; - if (!IS_RANDO) { - Item_Give(play, ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]); + u8 songItemId = ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]; + + if ( + (songItemId == ITEM_SONG_MINUET && GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) || + (songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) || + (songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) || + (songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) || + (songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) || + (songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) || + (songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) || + (songItemId == ITEM_SONG_EPONA && GameInteractor_Should(GI_VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SARIA && GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SUN && GameInteractor_Should(GI_VB_GIVE_ITEM_SUNS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_TIME && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) || + (songItemId == ITEM_SONG_STORMS && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL)) + ) { + Item_Give(play, songItemId); } osSyncPrintf(VT_FGCOL(YELLOW)); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 9489eefcd..ad5df65bd 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -1,6 +1,7 @@ #include "global.h" #include "vt.h" #include "overlays/actors/ovl_En_Sw/z_en_sw.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" static s16 sDisableAttention = false; static s16 sUnused = -1; @@ -810,12 +811,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor break; case 4100: csInfo->keyFrames = D_801225D4; - // RANDO: Waterfall opening cutscene skips to the end of the cutscene data earlier by doing this - if (!(IS_RANDO)) { - csInfo->keyFrameCnt = 5; - } else { - csInfo->keyFrameCnt = 2; - } + csInfo->keyFrameCnt = ARRAY_COUNT(D_801225D4); player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = 0x3FFC; func_800C0808(play, camIdx, player, CAM_SET_CS_C); @@ -1176,6 +1172,16 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1 s16 csCamIdx; Camera* csCam; + if (actor != NULL && actor->id != ACTOR_PLAYER) { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) { + return; + } + } else { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) { + return; + } + } + if (parentCamIdx == SUBCAM_ACTIVE) { parentCamIdx = play->activeCamera; } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 828e98368..bc253ef3a 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2128,7 +2128,9 @@ u8 Item_Give(PlayState* play, u8 item) { AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); } } - item = ITEM_STICK; + // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook + INV_CONTENT(ITEM_STICK) = ITEM_STICK; + return Return_Item(item, MOD_NONE, returnItem); } else if (item == ITEM_NUT) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { Inventory_ChangeUpgrade(UPG_NUTS, 1); @@ -2152,7 +2154,9 @@ u8 Item_Give(PlayState* play, u8 item) { AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); } } - item = ITEM_NUT; + // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook + INV_CONTENT(ITEM_NUT) = ITEM_NUT; + return Return_Item(item, MOD_NONE, returnItem); } else if (item == ITEM_BOMB) { // "Bomb Bomb Bomb Bomb Bomb Bomb Bomb" osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n"); diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index f9b3e7cf4..3ce5eeefc 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -226,60 +226,6 @@ void Play_Destroy(GameState* thisx) { gPlayState = NULL; } -void GivePlayerRandoRewardSongOfTime(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_16 && player != NULL && !Player_InBlockingCsMode(play, player) && - !Flags_GetTreasure(play, 0x1F) && gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT && !gSaveContext.pendingIceTrapCount) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } -} - -void GivePlayerRandoRewardNocturne(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 || - gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_1 || - gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_2) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && - CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && player != NULL && - !Player_InBlockingCsMode(play, player) && !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_NOCTURNE_OF_SHADOW); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0xAA; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } -} - -void GivePlayerRandoRewardRequiem(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { - if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT) && player != NULL && - !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0xAC; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } - } -} - -void GivePlayerRandoRewardMasterSword(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_2 && LINK_IS_ADULT && player != NULL && - !Player_InBlockingCsMode(play, player) && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - !Flags_GetRandomizerInf(RAND_INF_TOT_MASTER_SWORD)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_MASTER_SWORD); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = RAND_INF_TOT_MASTER_SWORD; - player->pendingFlag.flagType = FLAG_RANDOMIZER_INF; - } -} - u8 CheckStoneCount() { u8 stoneCount = 0; @@ -402,69 +348,6 @@ u8 CheckLACSRewardCount() { return lacsRewardCount; } -void GivePlayerRandoRewardZeldaLightArrowsGift(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - u8 meetsRequirements = 0; - - switch (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY)) { - case RO_GANON_BOSS_KEY_LACS_STONES: - if ((CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_STONE_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_MEDALLIONS: - if ((CheckMedallionCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_MEDALLION_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_REWARDS: - if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_REWARD_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_DUNGEONS: - if ((CheckDungeonCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_DUNGEON_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_TOKENS: - if (gSaveContext.inventory.gsTokens >= Randomizer_GetSettingValue(RSK_LACS_TOKEN_COUNT)) { - meetsRequirements = true; - } - break; - default: - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { - meetsRequirements = true; - } - break; - } - - if (meetsRequirements && LINK_IS_ADULT && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && - !Flags_GetTreasure(play, 0x1E) && player != NULL && !Player_InBlockingCsMode(play, player) && - play->transitionTrigger == TRANS_TRIGGER_OFF) { - GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT); - if (GiveItemEntryWithoutActor(play, getItem)) { - player->pendingFlag.flagID = 0x1E; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - } -} - -void GivePlayerRandoRewardSariaGift(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - if (gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY); - - if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE) && player != NULL && !Player_InBlockingCsMode(play, player)) { - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - player->pendingFlag.flagID = 0xC1; - } - } -} - void Play_Init(GameState* thisx) { PlayState* play = (PlayState*)thisx; GraphicsContext* gfxCtx = play->state.gfxCtx; @@ -1448,15 +1331,6 @@ skip: Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx, &play->gameOverCtx, play->state.gfxCtx); - - if (IS_RANDO) { - GivePlayerRandoRewardSariaGift(play, RC_LW_GIFT_FROM_SARIA); - GivePlayerRandoRewardSongOfTime(play, RC_SONG_FROM_OCARINA_OF_TIME); - GivePlayerRandoRewardZeldaLightArrowsGift(play, RC_TOT_LIGHT_ARROWS_CUTSCENE); - GivePlayerRandoRewardNocturne(play, RC_SHEIK_IN_KAKARIKO); - GivePlayerRandoRewardRequiem(play, RC_SHEIK_AT_COLOSSUS); - GivePlayerRandoRewardMasterSword(play, RC_TOT_MASTER_SWORD); - } } void Play_DrawOverlayElements(PlayState* play) { diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index dfffa7729..1f136674b 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -564,8 +564,8 @@ uint8_t Player_IsCustomLinkModel() { } s32 Player_InBlockingCsMode(PlayState* play, Player* this) { - return (this->stateFlags1 & 0x20000080) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || - (this->stateFlags1 & 1) || (this->stateFlags3 & 0x80) || + return (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || + (this->stateFlags1 & PLAYER_STATE1_LOADING) || (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING) || ((gSaveContext.magicState != MAGIC_STATE_IDLE) && (Player_ActionToMagicSpell(this, this->itemAction) >= 0)); } diff --git a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c index 86d23c45b..e05c171f0 100644 --- a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c +++ b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c @@ -6,6 +6,7 @@ #include "z_bg_bdan_switch.h" #include "objects/object_bdan_objects/object_bdan_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -224,10 +225,12 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) { if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { type = this->dyna.actor.params & 0xFF; Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); - if (type == BLUE || type == YELLOW_TALL_2) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); - } else { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (type == BLUE || type == YELLOW_TALL_2) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } else { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + } } } } @@ -236,7 +239,9 @@ void func_8086D548(BgBdanSwitch* this, PlayState* play) { if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 58f11a7f3..d0fc8864f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -8,6 +8,7 @@ #include "scenes/dungeons/ddan/ddan_scene.h" #include "objects/object_bwall/object_bwall.h" #include "objects/object_kingdodongo/object_kingdodongo.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -300,10 +301,13 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) { if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); - Cutscene_SetSegment(play, gDcOpeningCs); - gSaveContext.cutsceneTrigger = 1; + s32 flag = EVENTCHKINF_ENTERED_DODONGOS_CAVERN; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + Cutscene_SetSegment(play, gDcOpeningCs); + gSaveContext.cutsceneTrigger = 1; + func_8002DF54(play, NULL, 0x31); + } Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - func_8002DF54(play, NULL, 0x31); } if (this->dyna.actor.params < 0) { diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index eeecfabcb..51b7dc622 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -6,6 +6,7 @@ #include "z_bg_mori_bigst.h" #include "objects/object_mori_objects/object_mori_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -149,7 +150,9 @@ void BgMoriBigst_StalfosFight(BgMoriBigst* this, PlayState* play) { if ((this->dyna.actor.home.rot.z == 0) && ((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) { BgMoriBigst_SetupFall(this, play); - OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); + } } } @@ -163,8 +166,10 @@ void BgMoriBigst_Fall(BgMoriBigst* this, PlayState* play) { this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y; BgMoriBigst_SetupLanding(this, play); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND); - OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); - func_8002DF38(play, NULL, 0x3C); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); + func_8002DF38(play, NULL, 0x3C); + } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c index 26a02aa96..b6d5ed15a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c +++ b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c @@ -6,6 +6,7 @@ #include "z_bg_toki_swd.h" #include "objects/object_toki_objects/object_toki_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -115,14 +116,17 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) { if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) && Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); - play->csCtx.segment = D_808BBD90; - gSaveContext.cutsceneTrigger = 1; + s32 flag = EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + play->csCtx.segment = D_808BBD90; + gSaveContext.cutsceneTrigger = 1; + } } if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) { if (Actor_HasParent(&this->actor, play)) { if (!LINK_IS_ADULT) { - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) { Item_Give(play, ITEM_SWORD_MASTER); } play->csCtx.segment = D_808BB2F0; diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c index 75e920b29..04d1d6c72 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c @@ -7,6 +7,7 @@ #include "z_bg_treemouth.h" #include "objects/object_spot04_objects/object_spot04_objects.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -73,11 +74,7 @@ void BgTreemouth_Init(Actor* thisx, PlayState* play) { if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) { BgTreemouth_SetupAction(this, func_808BC8B8); - // If dungeon entrance randomizer is on, keep the tree mouth open - // when Link is adult and sword & shield have been shown to Mido - } else if ((LINK_IS_ADULT && (!IS_RANDO || - Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || - !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || (gSaveContext.sceneSetupIndex == 7)) { + } else if (LINK_IS_ADULT || (gSaveContext.sceneSetupIndex == 7)) { this->unk_168 = 0.0f; BgTreemouth_SetupAction(this, BgTreemouth_DoNothing); } else { @@ -157,9 +154,11 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) { } } else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) { Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); - play->csCtx.segment = D_808BCE20; - gSaveContext.cutsceneTrigger = 1; - BgTreemouth_SetupAction(this, func_808BC9EC); + if (GameInteractor_Should(GI_VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) { + play->csCtx.segment = D_808BCE20; + gSaveContext.cutsceneTrigger = 1; + BgTreemouth_SetupAction(this, func_808BC9EC); + } } } } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h index 7fe96cfa1..daa33bfee 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h @@ -15,4 +15,7 @@ typedef struct BgTreemouth { /* 0x016C */ BgTreemouthActionFunc actionFunc; } BgTreemouth; // size = 0x0170 +void BgTreemouth_SetupAction(BgTreemouth* actor, BgTreemouthActionFunc actionFunc); +void func_808BC6F8(BgTreemouth* actor, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c index 1c2f4c16b..cffdbea38 100644 --- a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c +++ b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c @@ -3,6 +3,7 @@ #include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -184,7 +185,9 @@ void func_80969F38(DemoDu* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, DEMO_EFFECT_MEDAL_FIRE); - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } } void func_80969FB4(DemoDu* this, PlayState* play) { @@ -201,7 +204,9 @@ void DemoDu_CsFireMedallion_AdvanceTo01(DemoDu* this, PlayState* play) { this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1); play->csCtx.segment = D_8096C1A4; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 9e4dd6119..4af2e9f87 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -142,7 +142,7 @@ f32 DemoEffect_InterpolateCsFrames(PlayState* play, s32 csActionId) { */ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) { this->initDrawFunc = DemoEffect_DrawJewel; - if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { + if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { this->initDrawFunc = DemoEffect_DrawGetItem; } if (!LINK_IS_ADULT) { @@ -156,7 +156,7 @@ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) { Actor_SetScale(&this->actor, 0.10f); } this->csActionId = 1; - this->actor.shape.rot.x = (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) ? 0 : 16384; + this->actor.shape.rot.x = (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) ? 0 : 16384; DemoEffect_InitJewelColor(this); this->jewel.alpha = 0; this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0; @@ -2087,13 +2087,48 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { this->getItem.isLoaded = 1; return; } - if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); - this->getItem.drawId = getItemEntry.gid; - func_8002EBCC(thisx, play, 0); - func_8002ED80(thisx, play, 0); - GetItemEntry_Draw(play, getItemEntry); - return; + if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { + GetItemEntry getItemEntry = GET_ITEM_NONE; + + switch (this->actor.params) { + case DEMO_EFFECT_JEWEL_KOKIRI: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD); + break; + case DEMO_EFFECT_JEWEL_GORON: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY); + break; + case DEMO_EFFECT_JEWEL_ZORA: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + break; + case DEMO_EFFECT_MEDAL_FOREST: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_FIRE: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_WATER: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_SPIRIT: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_SHADOW: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_LIGHT: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION); + break; + case DEMO_EFFECT_LIGHTARROW: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS); + break; + } + if (getItemEntry.getItemId != GI_NONE) { + this->getItem.drawId = getItemEntry.gid; + func_8002EBCC(thisx, play, 0); + func_8002ED80(thisx, play, 0); + GetItemEntry_Draw(play, getItemEntry); + return; + } } func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index 4ddeec155..a06786b2d 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -10,6 +10,7 @@ #include "scenes/indoors/nakaniwa/nakaniwa_scene.h" #include "objects/object_im/object_im.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -318,7 +319,9 @@ void func_809853B4(DemoIm* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0, 0, 0, 0xD); - Item_Give(play, ITEM_MEDALLION_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SHADOW); + } } void func_80985430(DemoIm* this, PlayState* play) { @@ -334,7 +337,9 @@ void func_8098544C(DemoIm* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8098786C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SHADOW); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } } @@ -903,40 +908,17 @@ void func_80986BF8(DemoIm* this, PlayState* play) { } } -void GivePlayerRandoRewardImpa(Actor* impa, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY); - - if (impa->parent != NULL && impa->parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { - GiveItemEntryFromActor(impa, play, getItemEntry, 75.0f, 50.0f); - } else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - play->transitionTrigger = TRANS_TRIGGER_START; - play->transitionType = TRANS_TYPE_FADE_WHITE; - gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; - // In entrance rando have impa bring link back to the front of castle grounds - if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { - play->nextEntranceIndex = ENTR_HYRULE_CASTLE_0; - } else { - play->nextEntranceIndex = ENTR_HYRULE_FIELD_17; - } - gSaveContext.nextCutsceneIndex = 0; - } -} - void func_80986C30(DemoIm* this, PlayState* play) { if (func_80986A5C(this, play)) { - if (IS_RANDO) { - GivePlayerRandoRewardImpa(this, play, RC_SONG_FROM_IMPA); - } else { + if (GameInteractor_Should(GI_VB_PLAY_ZELDAS_LULLABY_CS, true, this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - Item_Give(play, ITEM_SONG_LULLABY); func_80985F54(this); } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) { + Item_Give(play, ITEM_SONG_LULLABY); + } } } @@ -960,7 +942,7 @@ void func_80986D40(DemoIm* this, PlayState* play) { if (gSaveContext.sceneSetupIndex == 6) { this->action = 19; this->drawConfig = 1; - } else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { + } else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { // SoH [Randomizer] Not sure why we're not killing impa here. Actor_Kill(&this->actor); } else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) { this->action = 23; diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h index 3697733e1..06d6e5d7e 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h @@ -51,4 +51,6 @@ typedef struct DemoIm { /* 0x02D4 */ NpcInteractInfo interactInfo; } DemoIm; // size = 0x02FC +void func_80986794(DemoIm* demoIm); + #endif diff --git a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c index 6da87ab3c..85dcb4ebe 100644 --- a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c +++ b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "objects/object_sa/object_sa.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "vt.h" @@ -241,7 +242,9 @@ void func_8098E8C8(DemoSa* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xB); - Item_Give(play, ITEM_MEDALLION_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FOREST); + } } void func_8098E944(DemoSa* this, PlayState* play) { @@ -258,7 +261,9 @@ void func_8098E960(DemoSa* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8099010C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FOREST); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } else { this->action = 1; diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index 290e809f6..eeb0df2d2 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -23,6 +23,7 @@ #include "objects/object_menkuri_objects/object_menkuri_objects.h" #include "objects/object_demo_kekkai/object_demo_kekkai.h" #include "objects/object_ouke_haka/object_ouke_haka.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -354,9 +355,11 @@ void func_80996A54(DoorShutter* this, PlayState* play) { if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) { Flags_SetClear(play, this->dyna.actor.room); DoorShutter_SetupAction(this, func_80997150); - OnePointCutscene_Attention(play, &this->dyna.actor); - OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); - this->unk_16F = -100; + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Attention(play, &this->dyna.actor); + OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); + this->unk_16F = -100; + } } else if (func_809968D4(this, play) != 0) { Player* player = GET_PLAYER(play); @@ -470,8 +473,10 @@ void func_80996EE8(DoorShutter* this, PlayState* play) { if (func_80996E08(this, play, 1.0f)) { if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { DoorShutter_SetupAction(this, func_80997150); - OnePointCutscene_Attention(play, &this->dyna.actor); - this->unk_16F = -100; + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Attention(play, &this->dyna.actor); + this->unk_16F = -100; + } } else if (func_809968D4(this, play)) { Player* player = GET_PLAYER(play); // Jabu navi text for switch doors is different diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 5ea64e232..bdb154a92 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -2,6 +2,7 @@ #include "objects/object_warp1/object_warp1.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -487,44 +488,6 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, PlayState* play) { return ret; } -void GivePlayerRandoReward(DoorWarp1* this, Player* player, PlayState* play, u8 ruto, u8 adult) { - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, 0x00, GI_NONE); - - if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f); - } else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) { - if (adult) { - OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); - player->unk_450.x = this->actor.world.pos.x; - player->unk_450.z = this->actor.world.pos.z; - this->unk_1B2 = 20; - DoorWarp1_SetupAction(this, func_8099A508); - } else { - if (ruto) { - this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; - func_8002DF54(play, &this->actor, 10); - this->unk_1B2 = 1; - DoorWarp1_SetupAction(this, func_80999EE0); - } else { - Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, - &D_801333E8); - OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); - - player->unk_450.x = this->actor.world.pos.x; - player->unk_450.z = this->actor.world.pos.z; - this->unk_1B2 = 1; - - DoorWarp1_SetupAction(this, DoorWarp1_ChildWarpOut); - } - } - } -} - void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { Player* player; @@ -532,11 +495,6 @@ void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { if (DoorWarp1_PlayerInRange(this, play)) { player = GET_PLAYER(play); - - if (IS_RANDO) { - GivePlayerRandoReward(this, player, play, 0, 0); - return; - } Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -570,36 +528,26 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) { osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START); if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) { Item_Give(play, ITEM_GORON_RUBY); - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; } + play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; } else { play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11; - gSaveContext.nextCutsceneIndex = 0; - // Skip Mido complaining about dead Deku tree - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) { Item_Give(play, ITEM_KOKIRI_EMERALD); - play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; } + play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; } else { play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11; gSaveContext.nextCutsceneIndex = 0; @@ -635,12 +583,6 @@ void DoorWarp1_RutoWarpIdle(DoorWarp1* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG); if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) { - - if (IS_RANDO) { - GivePlayerRandoReward(this, GET_PLAYER(play), play, 1, 0); - return; - } - this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; func_8002DF54(play, &this->actor, 10); this->unk_1B2 = 1; @@ -670,9 +612,8 @@ void func_80999EE0(DoorWarp1* this, PlayState* play) { Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye); Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f); this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING; - if (!IS_RANDO) { - Message_StartTextbox(play, 0x4022, NULL); - } + // TODO: Why was this disabled in rando? + Message_StartTextbox(play, 0x4022, NULL); DoorWarp1_SetupAction(this, func_80999FE4); } } @@ -704,17 +645,14 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, PlayState* play) { this->warpTimer++; if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) { - Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; - gSaveContext.nextCutsceneIndex = 0; - } else { - Item_Give(play, ITEM_ZORA_SAPPHIRE); - play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) { + Item_Give(play, ITEM_ZORA_SAPPHIRE); + } gSaveContext.nextCutsceneIndex = 0xFFF0; } + play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { @@ -767,11 +705,6 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) { player = GET_PLAYER(play); - if (IS_RANDO) { - GivePlayerRandoReward(this, player, play, 0, 1); - return; - } - OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); func_8002DF54(play, &this->actor, 10); player->unk_450.x = this->actor.world.pos.x; @@ -829,19 +762,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { if (IS_BOSS_RUSH) { BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z); } else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_3; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) { Item_Give(play, ITEM_MEDALLION_FOREST); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2; @@ -851,20 +779,13 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; - gSaveContext.nextCutsceneIndex = 0; - // Change Death Mountain cloud since we aren't warping to the cutscene - Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) { Item_Give(play, ITEM_MEDALLION_FIRE); - play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; - gSaveContext.nextCutsceneIndex = 0xFFF3; } + play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; + gSaveContext.nextCutsceneIndex = 0xFFF3; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4; @@ -874,21 +795,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_LAKE_HYLIA_9; - gSaveContext.nextCutsceneIndex = 0; - // Fill Lake Hylia since we aren't warping to the cutscene - Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) { Item_Give(play, ITEM_MEDALLION_WATER); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_LAKE_HYLIA_8; @@ -898,18 +812,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_8; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { Item_Give(play, ITEM_MEDALLION_SPIRIT); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5; @@ -919,18 +829,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_GRAVEYARD_8; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { Item_Give(play, ITEM_MEDALLION_SHADOW); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_GRAVEYARD_7; diff --git a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c index 3fe7fc689..495ef96b8 100644 --- a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c +++ b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c @@ -7,6 +7,7 @@ #include "z_elf_msg.h" #include "vt.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -110,7 +111,7 @@ void ElfMsg_Destroy(Actor* thisx, PlayState* play) { s32 ElfMsg_GetMessageId(ElfMsg* this) { // Negative message ID forces link to talk to Navi - if (this->actor.params & 0x8000 || CVarGetInteger("gNoForcedNavi", 0) != 0) { + if (this->actor.params & 0x8000) { return (this->actor.params & 0xFF) + 0x100; } else { return -((this->actor.params & 0xFF) + 0x100); @@ -125,8 +126,10 @@ void ElfMsg_CallNaviCuboid(ElfMsg* this, PlayState* play) { (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) && (fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) { - player->naviTextId = ElfMsg_GetMessageId(this); - navi->elfMsg = this; + if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + player->naviTextId = ElfMsg_GetMessageId(this); + navi->elfMsg = this; + } } } @@ -145,8 +148,10 @@ void ElfMsg_CallNaviCylinder(ElfMsg* this, PlayState* play) { if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) && (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) { - player->naviTextId = ElfMsg_GetMessageId(this); - navi->elfMsg = this; + if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + player->naviTextId = ElfMsg_GetMessageId(this); + navi->elfMsg = this; + } } } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index a4d86ff61..e01573c9b 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -3,6 +3,7 @@ #include "soh_assets.h" #include "soh/Enhancements/enhancementTypes.h" #include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -192,10 +193,12 @@ void EnBox_Init(Actor* thisx, PlayState* play2) { SkelAnime_Init(play, &this->skelanime, &gTreasureChestSkel, anim, this->jointTable, this->morphTable, 5); Animation_Change(&this->skelanime, anim, 1.5f, animFrameStart, endFrame, ANIMMODE_ONCE, 0.0f); + this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F); if (IS_RANDO) { - this->getItemEntry = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F); - } else { - this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F); + RandomizerCheck rc = Randomizer_GetCheckFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params); + if (rc != RC_UNKNOWN_CHECK) { + this->getItemEntry = Randomizer_GetItemFromKnownCheck(rc, this->dyna.actor.params >> 5 & 0x7F); + } } EnBox_UpdateSizeAndTexture(this, play); @@ -275,7 +278,9 @@ void EnBox_Fall(EnBox* this, PlayState* play) { this->dyna.actor.shape.rot.z = 0; this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; EnBox_SetupAction(this, EnBox_WaitOpen); - OnePointCutscene_EndCutscene(play, this->unk_1AC); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_EndCutscene(play, this->unk_1AC); + } } Audio_PlaySoundGeneral(NA_SE_EV_COFFIN_CAP_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -445,74 +450,12 @@ void EnBox_WaitOpen(EnBox* this, PlayState* play) { } osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F); Flags_SetTreasure(play, this->dyna.actor.params & 0x1F); - - // treasure chest game rando - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) { - if((this->dyna.actor.params & 0xF) < 2) { - Flags_SetCollectible(play, 0x1B); - } - if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) { - Flags_SetCollectible(play, 0x1C); - } - if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) { - Flags_SetCollectible(play, 0x1D); - } - if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) { - Flags_SetCollectible(play, 0x1E); - } - if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) { - Flags_SetCollectible(play, 0x1F); - } - } - } } else { player = GET_PLAYER(play); func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) { - GetItemEntry sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F); - GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); - - // RANDOTODO treasure chest game rando - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) { - if((this->dyna.actor.params & 0xF) < 2) { - if(Flags_GetCollectible(play, 0x1B)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) { - if(Flags_GetCollectible(play, 0x1C)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) { - if(Flags_GetCollectible(play, 0x1D)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) { - if(Flags_GetCollectible(play, 0x1E)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) { - if(Flags_GetCollectible(play, 0x1F)) { - sItem = blueRupee; - } - } - } - } - // Chests need to have a negative getItemId in order to not immediately give their item - // when approaching. - if (IS_RANDO) { - sItem.getItemId = 0 - sItem.getItemId; - sItem.getItemFrom = ITEM_FROM_CHEST; - GiveItemEntryFromActorWithFixedRange(&this->dyna.actor, play, sItem); - } else { func_8002F554(&this->dyna.actor, play, -(this->dyna.actor.params >> 5 & 0x7F)); - } } if (Flags_GetTreasure(play, this->dyna.actor.params & 0x1F)) { EnBox_SetupAction(this, EnBox_Open); @@ -626,12 +569,9 @@ void EnBox_Update(Actor* thisx, PlayState* play) { Actor_SetFocus(&this->dyna.actor, 40.0f); } - if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) || - (IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) && - this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { - if (!CVarGetInteger("gAddTraps.enabled", 0)) { - EnBox_SpawnIceSmoke(this, play); - } + if ((this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open && + this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { + EnBox_SpawnIceSmoke(this, play); } } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.h b/soh/src/overlays/actors/ovl_En_Box/z_en_box.h index 765779367..0168fc1a8 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.h +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.h @@ -4,6 +4,7 @@ #include #include "global.h" +#define ENBOX_PARAMS(type, itemId, treasureFlag) ((type) << 12 | (itemId) << 5 | (treasureFlag)) #define ENBOX_TREASURE_FLAG_UNK_MIN 20 #define ENBOX_TREASURE_FLAG_UNK_MAX 32 @@ -45,7 +46,7 @@ typedef struct EnBox { /* 0x01F9 */ u8 type; /* 0x01FA */ u8 iceSmokeTimer; /* 0x01FB */ u8 unk_1FB; - /* */ GetItemEntry getItemEntry; + /* */ GetItemEntry getItemEntry; // This is only to determine the Chest Style, randomzier item gives are handled elsewhere /* */ Gfx* boxLidDL; /* */ Gfx* boxBodyDL; } EnBox; // size = 0x01FC diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 04123c7b3..b2bd6d65c 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -6,6 +6,7 @@ #include "z_en_cow.h" #include "objects/object_cow/object_cow.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -18,7 +19,6 @@ void func_809E0070(Actor* thisx, PlayState* play); void func_809DF494(EnCow* this, PlayState* play); void func_809DF6BC(EnCow* this, PlayState* play); -void EnCow_MoveForRandomizer(EnCow* this, PlayState* play); void func_809DF778(EnCow* this, PlayState* play); void func_809DF7D8(EnCow* this, PlayState* play); void func_809DF870(EnCow* this, PlayState* play); @@ -107,10 +107,6 @@ void EnCow_Init(Actor* thisx, PlayState* play) { EnCow* this = (EnCow*)thisx; s32 pad; - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_COWS)) { - EnCow_MoveForRandomizer(thisx, play); - } - ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f); switch (this->actor.params) { case 0: @@ -122,18 +118,15 @@ void EnCow_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit); func_809DEE9C(this); this->actionFunc = func_809DF96C; - if (play->sceneNum == SCENE_LINKS_HOUSE) { - if (!LINK_IS_ADULT && !CVarGetInteger("gCowOfTime", 0)) { - Actor_Kill(&this->actor); - return; - } - if (!Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) { - Actor_Kill(&this->actor); - return; - } + if (GameInteractor_Should(GI_VB_DESPAWN_HORSE_RACE_COW, ( + play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) + ), this)) { + Actor_Kill(&this->actor); + return; } + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_COW, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1); this->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f; this->unk_27A = 0; this->actor.targetMode = 6; @@ -216,30 +209,6 @@ void func_809DF730(EnCow* this, PlayState* play) { } } -void EnCow_MoveForRandomizer(EnCow* this, PlayState* play) { - // Only move the cow body (the tail will be moved with the body) - if (this->actor.params != 0) { - return; - } - - // Move left cow in lon lon tower - if (play->sceneNum == SCENE_LON_LON_BUILDINGS && this->actor.world.pos.x == -108 && this->actor.world.pos.z == -65) { - this->actor.world.pos.x = -229.0f; - this->actor.world.pos.z = 157.0f; - this->actor.shape.rot.y = 15783.0f; - // Move right cow in lon lon stable - } else if (play->sceneNum == SCENE_STABLE && this->actor.world.pos.x == -3 && this->actor.world.pos.z == -254) { - this->actor.world.pos.x += 119.0f; - } -} - -void EnCow_SetCowMilked(EnCow* this, PlayState* play) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - Player* player = GET_PLAYER(play); - player->pendingFlag.flagID = cowIdentity.randomizerInf; - player->pendingFlag.flagType = FLAG_RANDOMIZER_INF; -} - void func_809DF778(EnCow* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; @@ -281,23 +250,6 @@ void func_809DF8FC(EnCow* this, PlayState* play) { func_809DF494(this, play); } -bool EnCow_HasBeenMilked(EnCow* this, PlayState* play) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - return Flags_GetRandomizerInf(cowIdentity.randomizerInf); -} - -void EnCow_GivePlayerRandomizedItem(EnCow* this, PlayState* play) { - if (!EnCow_HasBeenMilked(this, play)) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowIdentity.randomizerCheck, GI_MILK); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 100.0f); - } else { - // once we've gotten the rando reward from the cow, - // return them to the their default action function - this->actionFunc = func_809DF96C; - } -} - void func_809DF96C(EnCow* this, PlayState* play) { if ((play->msgCtx.ocarinaMode == OCARINA_MODE_00) || (play->msgCtx.ocarinaMode == OCARINA_MODE_04)) { if (DREG(53) != 0) { @@ -308,23 +260,14 @@ void func_809DF96C(EnCow* this, PlayState* play) { if ((this->actor.xzDistToPlayer < 150.0f) && (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) { DREG(53) = 0; - // when randomized with cowsanity, if we haven't gotten the - // reward from this cow yet, give that, otherwise use the - // vanilla cow behavior - if (IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) && - !EnCow_HasBeenMilked(this, play)) { - EnCow_SetCowMilked(this, play); - // setting the ocarina mode here prevents intermittent issues - // with the item get not triggering until walking away - play->msgCtx.ocarinaMode = OCARINA_MODE_00; - this->actionFunc = EnCow_GivePlayerRandomizedItem; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_COW, true, this)) { + this->actionFunc = func_809DF8FC; + this->actor.flags |= ACTOR_FLAG_WILL_TALK; + func_8002F2CC(&this->actor, play, 170.0f); + this->actor.textId = 0x2006; + } else { return; } - this->actionFunc = func_809DF8FC; - this->actor.flags |= ACTOR_FLAG_WILL_TALK; - func_8002F2CC(&this->actor, play, 170.0f); - this->actor.textId = 0x2006; } else { this->unk_276 |= 4; } diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h index 63dbbddd3..3cd244388 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h @@ -21,4 +21,6 @@ typedef struct EnCow { /* 0x027C */ EnCowActionFunc actionFunc; } EnCow; // size = 0x0280 +void func_809DEE9C(EnCow* enCow); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 0dd33a8ac..09a5e6cd1 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -16,7 +16,6 @@ void EnDns_Destroy(Actor* thisx, PlayState* play); void EnDns_Update(Actor* thisx, PlayState* play); void EnDns_Draw(Actor* thisx, PlayState* play); -u32 EnDns_RandomizerPurchaseableCheck(EnDns* this); u32 func_809EF5A4(EnDns* this); u32 func_809EF658(EnDns* this); u32 func_809EF70C(EnDns* this); @@ -26,7 +25,6 @@ u32 func_809EF854(EnDns* this); u32 func_809EF8F4(EnDns* this); u32 func_809EF9A4(EnDns* this); -void EnDns_RandomizerPurchase(EnDns* this); void func_809EF9F8(EnDns* this); void func_809EFA28(EnDns* this); void func_809EFA58(EnDns* this); @@ -168,32 +166,6 @@ void EnDns_Init(Actor* thisx, PlayState* play) { this->actor.gravity = -1.0f; this->actor.textId = D_809F040C[this->actor.params]; this->dnsItemEntry = sItemEntries[this->actor.params]; - if (IS_RANDO) { - // Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - this->scrubIdentity = Randomizer_IdentifyScrub(play->sceneNum, this->actor.params, respawnData); - - if ((Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_AFFORDABLE || - Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_RANDOM) && - this->scrubIdentity.itemPrice != -1) { - this->dnsItemEntry->itemPrice = this->scrubIdentity.itemPrice; - } - - if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_EXPENSIVE) { - // temporary workaround: always use 40 rupees as price instead of 70 - if (this->actor.params == 0x0006) { - this->dnsItemEntry->itemPrice = 40; - } - } - - if (this->scrubIdentity.isShuffled) { - this->dnsItemEntry->getItemId = this->scrubIdentity.getItemId; - this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck; - this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase; - this->dnsItemEntry->itemAmount = 1; - this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - } - } this->actionFunc = EnDns_SetupWait; } @@ -216,13 +188,6 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) { /* Item give checking functions */ -u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) { - if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) { - return 0; - } - return 4; -} - u32 func_809EF5A4(EnDns* this) { if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) { return 1; @@ -319,10 +284,6 @@ u32 func_809EF9A4(EnDns* this) { } /* Paying and flagging functions */ -void EnDns_RandomizerPurchase(EnDns* this) { - Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); - Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf); -} void func_809EF9F8(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); @@ -412,44 +373,39 @@ void EnDns_Talk(EnDns* this, PlayState* play) { void func_809EFDD0(EnDns* this, PlayState* play) { u16 pendingGetItemId; - if (!IS_RANDO || !this->scrubIdentity.isShuffled) { - if (this->actor.params == 0x9) { - if (CUR_UPG_VALUE(UPG_STICKS) < 2) { - pendingGetItemId = GI_STICK_UPGRADE_20; - } else { - pendingGetItemId = GI_STICK_UPGRADE_30; - } - } else if (this->actor.params == 0xA) { - if (CUR_UPG_VALUE(UPG_NUTS) < 2) { - pendingGetItemId = GI_NUT_UPGRADE_30; - } else { - pendingGetItemId = GI_NUT_UPGRADE_40; - } + if (this->actor.params == 0x9) { + if (CUR_UPG_VALUE(UPG_STICKS) < 2) { + pendingGetItemId = GI_STICK_UPGRADE_20; } else { - pendingGetItemId = this->dnsItemEntry->getItemId; + pendingGetItemId = GI_STICK_UPGRADE_30; + } + } else if (this->actor.params == 0xA) { + if (CUR_UPG_VALUE(UPG_NUTS) < 2) { + pendingGetItemId = GI_NUT_UPGRADE_30; + } else { + pendingGetItemId = GI_NUT_UPGRADE_40; } - GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } else { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 130.0f, 100.0f); + pendingGetItemId = this->dnsItemEntry->getItemId; } + GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; + func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } void func_809EFEE8(EnDns* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - func_809EFDD0(this, play); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { + func_809EFDD0(this, play); + } this->actionFunc = func_809EFF50; } } void func_809EFF50(EnDns* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { this->actor.parent = NULL; this->actionFunc = func_809EFF98; } else { @@ -533,9 +489,6 @@ void EnDns_Update(Actor* thisx, PlayState* play) { this->dustTimer++; this->actor.textId = D_809F040C[this->actor.params]; - if (IS_RANDO && this->scrubIdentity.isShuffled) { - this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - } Actor_SetFocus(&this->actor, 60.0f); Actor_SetScale(&this->actor, 0.01f); SkelAnime_Update(&this->skelAnime); diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h index bf0a3a167..0e3e50c9b 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h @@ -32,7 +32,10 @@ typedef struct EnDns { /* 0x02BD */ u8 dropCollectible; /* 0x02C0 */ DnsItemEntry* dnsItemEntry; /* 0x02C4 */ f32 yInitPos; - /* */ ScrubIdentity scrubIdentity; + // #region SOH [Randomizer] + /* */ DnsItemEntry sohDnsItemEntry; + /* */ ScrubIdentity sohScrubIdentity; + // #endregion } EnDns; // size = 0x02C8 #endif diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 6da75b1e7..d3a0eadea 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -6,7 +6,7 @@ #include "z_en_ds.h" #include "objects/object_ds/object_ds.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -90,19 +90,12 @@ void EnDs_DisplayOddPotionText(EnDs* this, PlayState* play) { } void EnDs_GiveOddPotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; } else { - u32 itemId = GI_ODD_POTION; - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM); - return; - } - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); + func_8002F434(&this->actor, play, GI_ODD_POTION, 10000.0f, 50.0f); } } @@ -111,13 +104,9 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, PlayState* play) { Message_CloseTextbox(play); this->actionFunc = EnDs_GiveOddPotion; u32 itemId = GI_ODD_POTION; - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM); - return; + if (GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { + func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); } - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); } } @@ -138,7 +127,7 @@ void EnDs_BrewOddPotion2(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion3; - this->brewTimer = IS_RANDO ? 0 : 60; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_UnsetSwitch(play, 0x3F); } } @@ -148,7 +137,7 @@ void EnDs_BrewOddPotion1(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion2; - this->brewTimer = IS_RANDO ? 0 : 20; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 20 : 0; } Math_StepToF(&this->unk_1E4, 1.0f, 0.01f); @@ -162,7 +151,7 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: // yes this->actionFunc = EnDs_BrewOddPotion1; - this->brewTimer = IS_RANDO ? 0 : 60; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_SetSwitch(play, 0x3F); play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; @@ -174,22 +163,10 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { } } -u8 EnDs_RandoCanGetGrannyItem() { - return IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - // Traded odd mushroom when adult trade is on - ((Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) || - // Found claim check when adult trade is off - (!Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && - INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)); -} - s32 EnDs_CheckRupeesAndBottle() { if (gSaveContext.rupees < 100) { return 0; - } else if (EnDs_RandoCanGetGrannyItem()) { // Allow buying the rando item regardless of having a bottle - return 2; - } else if (Inventory_HasEmptyBottle() == 0) { + } else if (GameInteractor_Should(GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, Inventory_HasEmptyBottle() == 0, NULL)) { return 1; } else { return 2; @@ -197,20 +174,11 @@ s32 EnDs_CheckRupeesAndBottle() { } void EnDs_GiveBluePotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { - if (EnDs_RandoCanGetGrannyItem()) { - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP); - } - + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_Talk; } else { - if (EnDs_RandoCanGetGrannyItem()) { - GetItemEntry entry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); - GiveItemEntryFromActor(&this->actor, play, entry, 10000.0f, 50.0f); - } else { - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); - } + func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); } } @@ -229,18 +197,14 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { case 2: // have 100 rupees and empty bottle Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - GetItemEntry itemEntry; - if (EnDs_RandoCanGetGrannyItem()) { - itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - } else { - itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { + GetItemEntry itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; } - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; this->actionFunc = EnDs_GiveBluePotion; return; } @@ -261,10 +225,7 @@ void EnDs_Wait(EnDs* this, PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); player->actor.textId = 0x504A; this->actionFunc = EnDs_OfferOddPotion; - } else if ( - // Always offer blue potion when adult trade is off - (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF) || - Flags_GetItemGetInf(ITEMGETINF_30)) { // Traded odd mushroom + } else if (GameInteractor_Should(GI_VB_OFFER_BLUE_POTION, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // Traded odd mushroom player->actor.textId = 0x500C; this->actionFunc = EnDs_OfferBluePotion; } else { diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index db13ecc54..6f99f070f 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -1,6 +1,7 @@ #include "z_en_du.h" #include "objects/object_du/object_du.h" #include "scenes/overworld/spot18/spot18_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -376,7 +377,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_00; EnDu_SetupAction(this, func_809FE3C0); } else if (play->msgCtx.ocarinaMode >= OCARINA_MODE_06) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaWrongCs); gSaveContext.cutsceneTrigger = 1; } @@ -385,7 +386,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaCorrectCs); gSaveContext.cutsceneTrigger = 1; } @@ -474,10 +475,7 @@ void func_809FE890(EnDu* this, PlayState* play) { Vec3f velocity = { 0.0f, 0.0f, 0.0f }; CsCmdActorAction* csAction; - if (play->csCtx.state == CS_STATE_IDLE || IS_RANDO) { - if (IS_RANDO) { - play->csCtx.state = CS_STATE_IDLE; - } + if (play->csCtx.state == CS_STATE_IDLE) { func_8002DF54(play, &this->actor, 1); EnDu_SetupAction(this, func_809FEB08); return; @@ -556,11 +554,8 @@ void func_809FEB08(EnDu* this, PlayState* play) { EnDu_SetupAction(this, func_809FE3C0); return; } - if ((!IS_RANDO && CUR_UPG_VALUE(UPG_STRENGTH) <= 0) || - (IS_RANDO && !Flags_GetTreasure(play, 0x1E))) { - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1E); - } + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, CUR_UPG_VALUE(UPG_STRENGTH) <= 0, NULL)) { + Flags_SetRandomizerInf(RAND_INF_DARUNIAS_JOY); this->actor.textId = 0x301C; EnDu_SetupAction(this, func_809FEC14); } else { @@ -581,17 +576,13 @@ void func_809FEC14(EnDu* this, PlayState* play) { } void func_809FEC70(EnDu* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_STRENGTH_1, true, NULL)) { this->actor.parent = NULL; EnDu_SetupAction(this, func_809FECE4); } else { f32 xzRange = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_DARUNIAS_JOY, GI_BRACELET); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + + func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 11a7eb026..1c16a0eb0 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -45,7 +45,6 @@ void EnFr_OcarinaMistake(EnFr* this, PlayState* play); void EnFr_SetupReward(EnFr* this, PlayState* play, u8 unkCondition); void EnFr_PrintTextBox(EnFr* this, PlayState* play); void EnFr_TalkBeforeReward(EnFr* this, PlayState* play); -RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex); void EnFr_SetReward(EnFr* this, PlayState* play); // Deactivate @@ -618,7 +617,6 @@ void EnFr_Idle(EnFr* this, PlayState* play) { player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y; this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = EnFr_Activate; } else if (EnFr_IsAboveAndWithin30DistXZ(player, this)) { player->unk_6A8 = &this->actor; @@ -854,7 +852,6 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) { void EnFr_OcarinaMistake(EnFr* this, PlayState* play) { Message_CloseTextbox(play); this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; func_80078884(NA_SE_SY_OCARINA_ERROR); Audio_OcaSetInstrument(0); sEnFrPointers.flags = 12; @@ -939,23 +936,6 @@ void EnFr_TalkBeforeReward(EnFr* this, PlayState* play) { } } -RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) { - switch (songIndex) { - case FROG_ZL: - return RC_ZR_FROGS_ZELDAS_LULLABY; - case FROG_EPONA: - return RC_ZR_FROGS_EPONAS_SONG; - case FROG_SARIA: - return RC_ZR_FROGS_SARIAS_SONG; - case FROG_SUNS: - return RC_ZR_FROGS_SUNS_SONG; - case FROG_SOT: - return RC_ZR_FROGS_SONG_OF_TIME; - default: - return RC_UNKNOWN_CHECK; - } -} - void EnFr_SetReward(EnFr* this, PlayState* play) { u16 songIndex; @@ -963,16 +943,12 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { songIndex = this->songIndex; this->actionFunc = EnFr_Deactivate; this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_RUPEE_PURPLE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_BLUE; @@ -981,11 +957,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_IN_THE_RAIN, GI_HEART_PIECE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_BLUE; @@ -994,11 +967,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_OCARINA_GAME, GI_HEART_PIECE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_PURPLE; @@ -1049,29 +1019,23 @@ void EnFr_Deactivate(EnFr* this, PlayState* play) { this->actionFunc = EnFr_Idle; } else { this->actionFunc = EnFr_GiveReward; - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f); } } } void EnFr_GiveReward(EnFr* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->actor.parent = NULL; this->actionFunc = EnFr_SetIdle; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f); - } + func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); } } void EnFr_SetIdle(EnFr* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || (IS_RANDO && this->reward == RG_ICE_TRAP)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { this->actionFunc = EnFr_Idle; } } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h index 19d612fdd..17b8b162e 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h @@ -73,7 +73,6 @@ typedef struct EnFr { /* 0x03AA */ s16 xyAngleButterfly; // Butterfly Travels along random angles in the x-y plane /* 0x03AC */ Vec3f posButterfly; // Position/Coordinates of the Butterfly /* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo() - /* */ GetItemEntry getItemEntry; } EnFr; // size = 0x03C4 typedef struct { @@ -81,4 +80,7 @@ typedef struct { EnFr* frogs[5]; } EnFrPointers; +void EnFr_Idle(EnFr* enFr, PlayState* play); +void EnFr_GiveReward(EnFr* enFr, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 4986f24f6..22754a87a 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -8,6 +8,7 @@ #include "objects/object_oF1d_map/object_oF1d_map.h" #include "objects/object_gm/object_gm.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -96,10 +97,9 @@ void EnGm_Destroy(Actor* thisx, PlayState* play) { s32 func_80A3D7C8(void) { if (LINK_AGE_IN_YEARS == YEARS_CHILD) { return 0; - } else if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF) && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - return 1; - } else if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)) { // Don't have giant's knife + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, ( + !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) // Don't have giant's knife + ), NULL)) { return 1; } else if (CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE)) { // Have broken giant's knife return 2; @@ -215,11 +215,6 @@ void func_80A3DC44(EnGm* this, PlayState* play) { return; case 1: Flags_SetInfTable(INFTABLE_B1); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - //Resets "Talked to Medigoron" flag in infTable to restore initial conversation state - Flags_UnsetInfTable(INFTABLE_B1); - } case 2: this->actionFunc = EnGm_ProcessChoiceIndex; default: @@ -254,20 +249,10 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { Message_ContinueTextbox(play, 0xC8); this->actionFunc = func_80A3DD7C; } else { - GetItemEntry itemEntry; - - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); - Flags_SetInfTable(INFTABLE_B1); - } else { - itemEntry = ItemTable_Retrieve(GI_SWORD_KNIFE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; this->actionFunc = func_80A3DF00; } break; @@ -280,24 +265,12 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { } void func_80A3DF00(EnGm* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); - } - + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); this->actor.parent = NULL; this->actionFunc = func_80A3DF60; } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); - Flags_SetInfTable(INFTABLE_B1); - } - else { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); - } + func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 3094f2171..7dc67f427 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -3,7 +3,6 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -31,9 +30,11 @@ void func_80A40C78(EnGo* this, PlayState* play); void EnGo_Eyedrops(EnGo* this, PlayState* play); void func_80A40DCC(EnGo* this, PlayState* play); -void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep); -void EnGo_UpdateDust(EnGo* this); -void EnGo_DrawDust(EnGo* this, PlayState* play); + +void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, + f32 scaleStep); +void EnGo_UpdateEffects(EnGo* this); +void EnGo_DrawEffects(EnGo* this, PlayState* play); const ActorInit En_Go_InitVars = { ACTOR_EN_GO, @@ -95,10 +96,10 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { - if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (Environment_GetBgsDayCount() >= 3) { return 0x305E; } else { return 0x305D; @@ -113,8 +114,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { return 0x3053; } case 0x00: - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) { + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { if (Flags_GetInfTable(INFTABLE_10F)) { return 0x3042; } else { @@ -199,7 +199,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { } s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { - s16 unkState = NPC_TALK_STATE_TALKING; + s16 talkState = NPC_TALK_STATE_TALKING; f32 xzRange; f32 yRange = fabsf(thisx->yDistToPlayer) + 1.0f; @@ -210,51 +210,51 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { switch (thisx->textId) { case 0x3008: Flags_SetInfTable(INFTABLE_E0); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x300B: Flags_SetInfTable(INFTABLE_EB); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3014: Flags_SetInfTable(INFTABLE_F0); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3016: Flags_SetInfTable(INFTABLE_F4); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3018: Flags_SetInfTable(INFTABLE_F8); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3036: func_8002F434(thisx, play, GI_TUNIC_GORON, xzRange, yRange); Flags_SetInfTable(INFTABLE_10D); // EnGo exclusive flag - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x3037: Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3041: Flags_SetInfTable(INFTABLE_10F); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3059: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x3052: case 0x3054: case 0x3055: case 0x305A: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x305E: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; default: - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; } break; @@ -272,7 +272,7 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { thisx->textId = 0x300D; } Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; case 0x3034: if (play->msgCtx.choiceIndex == 0) { @@ -287,16 +287,16 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { thisx->textId = 0x3033; } Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; case 0x3054: case 0x3055: if (play->msgCtx.choiceIndex == 0) { - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; } else { thisx->textId = 0x3056; Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; } Flags_SetInfTable(INFTABLE_B4); break; @@ -312,17 +312,17 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { case 0x3033: thisx->textId = 0x3034; Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; default: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; } } break; case TEXT_STATE_DONE: if (Message_ShouldAdvance(play)) { - unkState = NPC_TALK_STATE_ITEM_GIVEN; + talkState = NPC_TALK_STATE_ITEM_GIVEN; } break; case TEXT_STATE_NONE: @@ -332,21 +332,21 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { case TEXT_STATE_9: break; } - return unkState; + return talkState; } -s32 func_80A3ED24(PlayState* play, EnGo* this, NpcInteractInfo* interactInfo, f32 arg3, NpcGetTextIdFunc getTextId, +s32 EnGo_UpdateTalking(PlayState* play, Actor* thisx, s16* talkState, f32 interactRange, NpcGetTextIdFunc getTextId, NpcUpdateTalkStateFunc updateTalkState) { - if (interactInfo->talkState != NPC_TALK_STATE_IDLE) { - interactInfo->talkState = updateTalkState(play, &this->actor); + if (*talkState != NPC_TALK_STATE_IDLE) { + *talkState = updateTalkState(play, thisx); return false; - } else if (Actor_ProcessTalkRequest(&this->actor, play)) { - interactInfo->talkState = NPC_TALK_STATE_TALKING; + } else if (Actor_ProcessTalkRequest(thisx, play)) { + *talkState = NPC_TALK_STATE_TALKING; return true; - } else if (!func_8002F2CC(&this->actor, play, arg3)) { + } else if (!func_8002F2CC(thisx, play, interactRange)) { return false; } else { - this->actor.textId = getTextId(play, &this->actor); + thisx->textId = getTextId(play, thisx); return false; } } @@ -379,7 +379,7 @@ s32 EnGo_IsActorSpawned(EnGo* this, PlayState* play) { } } -f32 EnGo_GetGoronSize(EnGo* this) { +f32 EnGo_GetPlayerTrackingYOffset(EnGo* this) { switch (this->actor.params & 0xF0) { case 0x00: return 10.0f; @@ -398,16 +398,16 @@ f32 EnGo_GetGoronSize(EnGo* this) { void func_80A3F060(EnGo* this, PlayState* play) { Player* player = GET_PLAYER(play); - s16 npcTrackingMode; + s16 trackingMode; if (this->actionFunc != EnGo_BiggoronActionFunc && this->actionFunc != EnGo_FireGenericActionFunc && this->actionFunc != func_80A40B1C) { - npcTrackingMode = NPC_TRACKING_NONE; + trackingMode = NPC_TRACKING_NONE; } this->interactInfo.trackPos = player->actor.world.pos; - this->interactInfo.yOffset = EnGo_GetGoronSize(this); - Npc_TrackPoint(&this->actor, &this->interactInfo, 4, npcTrackingMode); + this->interactInfo.yOffset = EnGo_GetPlayerTrackingYOffset(this); + Npc_TrackPoint(&this->actor, &this->interactInfo, 4, trackingMode); } void func_80A3F0E4(EnGo* this) { @@ -421,23 +421,23 @@ void func_80A3F0E4(EnGo* this) { } s32 EnGo_IsCameraModified(EnGo* this, PlayState* play) { - f32 xyzDist; + f32 xyzDistSq; s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; - Camera* camera = play->cameraPtrs[MAIN_CAM]; + Camera* mainCam = play->cameraPtrs[MAIN_CAM]; if (fabsf(yawDiff) > 10920.0f) { return 0; } - xyzDist = (this->actor.scale.x / 0.01f) * 10000.0f; + xyzDistSq = (this->actor.scale.x / 0.01f) * SQ(100.0f); if ((this->actor.params & 0xF0) == 0x90) { - Camera_ChangeSetting(camera, CAM_SET_DIRECTED_YAW); - xyzDist *= 4.8f; + Camera_ChangeSetting(mainCam, CAM_SET_DIRECTED_YAW); + xyzDistSq *= 4.8f; } - if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDist) { - if (camera->setting == CAM_SET_DIRECTED_YAW) { - Camera_ChangeSetting(camera, CAM_SET_NORMAL0); + if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDistSq) { + if (mainCam->setting == CAM_SET_DIRECTED_YAW) { + Camera_ChangeSetting(mainCam, CAM_SET_NORMAL0); } return 0; } else { @@ -480,7 +480,7 @@ s32 EnGo_FollowPath(EnGo* this, PlayState* play) { pointPos += this->unk_218; xDist = pointPos->x - this->actor.world.pos.x; zDist = pointPos->z - this->actor.world.pos.z; - Math_SmoothStepToS(&this->actor.world.rot.y, (s16)(Math_FAtan2F(xDist, zDist) * ((f32)0x8000 / M_PI)), 10, 1000, 1); + Math_SmoothStepToS(&this->actor.world.rot.y, RADF_TO_BINANG(Math_FAtan2F(xDist, zDist)), 10, 1000, 1); if ((SQ(xDist) + SQ(zDist)) < 600.0f) { this->unk_218++; @@ -536,7 +536,7 @@ s32 EnGo_SpawnDust(EnGo* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 nu accel.z = (Rand_ZeroOne() - 0.5f) * xzAccel; pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x; pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z; - EnGo_AddDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep); + EnGo_SpawnEffectDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep); angle += (s16)(0x10000 / numDustEffects); i--; } @@ -549,7 +549,7 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) { } else if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { return true; } else if (DECR(this->unk_21C)) { - if ((this->unk_21C & 1)) { + if (this->unk_21C & 1) { this->actor.world.pos.y += 1.5f; } else { this->actor.world.pos.y -= 1.5f; @@ -573,29 +573,29 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) { void func_80A3F908(EnGo* this, PlayState* play) { Player* player = GET_PLAYER(play); - f32 float1; - s32 isUnkCondition; + f32 interactRange; + s32 dialogStarted; if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_GoronLinkRolling || this->actionFunc == EnGo_FireGenericActionFunc || this->actionFunc == EnGo_Eyedrops || this->actionFunc == func_80A40DCC || this->actionFunc == EnGo_GetItem || this->actionFunc == func_80A40C78 || this->actionFunc == func_80A40B1C) { - float1 = (this->collider.dim.radius + 30.0f); - float1 *= (this->actor.scale.x / 0.01f); + interactRange = (this->collider.dim.radius + 30.0f); + interactRange *= (this->actor.scale.x / 0.01f); if ((this->actor.params & 0xF0) == 0x90) { - float1 *= 4.8f; + interactRange *= 4.8f; } if ((this->actor.params & 0xF0) == 0x90) { - isUnkCondition = - func_80A3ED24(play, this, &this->interactInfo, float1, EnGo_GetTextID, EnGo_UpdateTalkState); + dialogStarted = + EnGo_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange, EnGo_GetTextID, EnGo_UpdateTalkState); } else { - isUnkCondition = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, float1, + dialogStarted = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange, EnGo_GetTextID, EnGo_UpdateTalkState); } - if (((this->actor.params & 0xF0) == 0x90) && (isUnkCondition == true)) { + if (((this->actor.params & 0xF0) == 0x90) && (dialogStarted == true)) { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { if (func_8002F368(play) == EXCH_ITEM_SWORD_BROKEN) { if (Flags_GetInfTable(INFTABLE_B4)) { @@ -628,7 +628,7 @@ void EnGo_Init(Actor* thisx, PlayState* play) { Vec3f D_80A41BA8 = { 0.0f, 0.0f, 0.0f }; // unused ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, 0, 0, 0); + SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, NULL, NULL, 0); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit); @@ -711,8 +711,8 @@ void EnGo_StopRolling(EnGo* this, PlayState* play) { EnBom* bomb; if (DECR(this->unk_20E) == 0) { - if (this->collider.base.ocFlags2 & 1) { - this->collider.base.ocFlags2 &= ~1; + if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { + this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; play->damagePlayer(play, -4); func_8002F71C(play, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f); this->unk_20E = 0x10; @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, PlayState* play) { void EnGo_BiggoronActionFunc(EnGo* this, PlayState* play) { if (((this->actor.params & 0xF0) == 0x90) && (this->interactInfo.talkState == NPC_TALK_STATE_ACTION)) { - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { @@ -958,45 +958,25 @@ void EnGo_GetItem(EnGo* this, PlayState* play) { this->unk_20C = 0; if ((this->actor.params & 0xF0) == 0x90) { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { - if (!IS_RANDO) { - getItemId = GI_SWORD_BGS; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_SWORD_BGS; this->unk_20C = 1; } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { - if (IS_RANDO) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); - getItemId = getItemEntry.getItemId; - Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS); - } else { - getItemId = GI_CLAIM_CHECK; - } + getItemId = GI_CLAIM_CHECK; } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { - if (IS_RANDO) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN); - getItemId = getItemEntry.getItemId; - } else { - getItemId = GI_PRESCRIPTION; - } + getItemId = GI_PRESCRIPTION; } } if ((this->actor.params & 0xF0) == 0) { getItemId = GI_TUNIC_GORON; + Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT); } yDist = fabsf(this->actor.yDistToPlayer) + 1.0f; xzDist = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, xzDist, yDist); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzDist, yDist); - } + func_8002F434(&this->actor, play, getItemId, xzDist, yDist); } } @@ -1105,32 +1085,30 @@ void EnGo_DrawRolling(EnGo* this, PlayState* play) { s32 EnGo_OverrideLimbDraw(PlayState* play, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { EnGo* this = (EnGo*)thisx; - Vec3s vec1; + Vec3s limbRot; f32 float1; if (limb == 17) { Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY); - vec1 = this->interactInfo.headRot; - float1 = (vec1.y / (f32)0x8000) * M_PI; + limbRot = this->interactInfo.headRot; + float1 = (limbRot.y / (f32)0x8000) * M_PI; Matrix_RotateX(float1, MTXMODE_APPLY); - float1 = (vec1.x / (f32)0x8000) * M_PI; + float1 = (limbRot.x / (f32)0x8000) * M_PI; Matrix_RotateZ(float1, MTXMODE_APPLY); Matrix_Translate(-2800.0f, 0.0f, 0.0f, MTXMODE_APPLY); } if (limb == 10) { - vec1 = this->interactInfo.torsoRot; - float1 = (vec1.y / (f32)0x8000) * M_PI; + limbRot = this->interactInfo.torsoRot; + float1 = (limbRot.y / (f32)0x8000) * M_PI; Matrix_RotateY(float1, MTXMODE_APPLY); - float1 = (vec1.x / (f32)0x8000) * M_PI; + float1 = (limbRot.x / (f32)0x8000) * M_PI; Matrix_RotateX(float1, MTXMODE_APPLY); } if ((limb == 10) || (limb == 11) || (limb == 14)) { - float1 = Math_SinS(this->jointTable[limb]); - rot->y += float1 * 200.0f; - float1 = Math_CosS(this->morphTable[limb]); - rot->z += float1 * 200.0f; + rot->y += Math_SinS(this->jointTable[limb]) * 200.0f; + rot->z += Math_CosS(this->morphTable[limb]) * 200.0f; } return 0; @@ -1150,9 +1128,9 @@ void EnGo_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - EnGo_UpdateDust(this); + EnGo_UpdateEffects(this); Matrix_Push(); - EnGo_DrawDust(this, play); + EnGo_DrawEffects(this, play); Matrix_Pop(); if (this->actionFunc == EnGo_CurledUp) { @@ -1167,39 +1145,36 @@ void EnGo_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(gGoronCsMouthNeutralTex)); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnGo_OverrideLimbDraw, EnGo_PostLimbDraw, &this->actor); - EnGo_DrawDust(this, play); + EnGo_DrawEffects(this, play); } CLOSE_DISPS(play->state.gfxCtx); } -void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) { - EnGoEffect* dustEffect = this->dustEffects; +void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) { + EnGoEffect* dustEffect = this->effects; s16 i; - s16 timer; - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type != 1) { dustEffect->epoch++; dustEffect->scale = scale; dustEffect->scaleStep = scaleStep; - timer = initialTimer; - dustEffect->timer = timer; + dustEffect->initialTimer = dustEffect->timer = initialTimer; dustEffect->type = 1; - dustEffect->initialTimer = initialTimer; dustEffect->pos = *pos; dustEffect->accel = *accel; dustEffect->velocity = *velocity; - return; + break; } } } -void EnGo_UpdateDust(EnGo* this) { - EnGoEffect* dustEffect = this->dustEffects; +void EnGo_UpdateEffects(EnGo* this) { + EnGoEffect* dustEffect = this->effects; f32 randomNumber; s16 i; - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type) { dustEffect->timer--; if (dustEffect->timer == 0) { @@ -1220,24 +1195,24 @@ void EnGo_UpdateDust(EnGo* this) { } } -void EnGo_DrawDust(EnGo* this, PlayState* play) { +void EnGo_DrawEffects(EnGo* this, PlayState* play) { static void* dustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex }; - EnGoEffect* dustEffect = this->dustEffects; + EnGoEffect* dustEffect = this->effects; s16 alpha; - s16 firstDone; + s16 materialFlag; s16 index; s16 i; OPEN_DISPS(play->state.gfxCtx); - firstDone = false; + materialFlag = false; Gfx_SetupDL_25Xlu(play->state.gfxCtx); - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type) { - if (!firstDone) { + if (!materialFlag) { POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0); gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD40); gDPSetEnvColor(POLY_XLU_DISP++, 100, 60, 20, 0); - firstDone = true; + materialFlag = true; } FrameInterpolation_RecordOpenChild(dustEffect, dustEffect->epoch); diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.h b/soh/src/overlays/actors/ovl_En_Go/z_en_go.h index 7b3224aec..1b1320988 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.h +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.h @@ -16,12 +16,13 @@ typedef s16 (*callback2_80A3ED24)(PlayState*, struct EnGo*); // /* 0x20 */ GORON1_DMT_DC_ENTRANCE, // /* 0x30 */ GORON1_DMT_ROLLING_SMALL, // /* 0x40 */ GORON1_DMT_BOMB_FLOWER, -// /* 0x50 */ GORON1_CITY_ENTRANCE, +// /* 0x50 */ GORON1_CITY_ENTRANCE, // /* 0x60 */ GORON1_CITY_ISLAND, -// /* 0x70 */ GORON1_CITY_LOST_WOODS, +// /* 0x70 */ GORON1_CITY_LOST_WOODS, // /* 0x80 */ // Not Used // /* 0x90 */ GORON1_DMT_BIGGORON, +#define EN_GO_EFFECT_COUNT 20 typedef struct { /* 0x0000 */ u8 type; @@ -56,7 +57,7 @@ typedef struct EnGo { /* 0x021E */ s16 unk_21E; /* 0x0220 */ s16 jointTable[18]; /* 0x0244 */ s16 morphTable[18]; - /* 0x0268 */ EnGoEffect dustEffects[20]; + /* 0x0268 */ EnGoEffect effects[EN_GO_EFFECT_COUNT]; } EnGo; // size = 0x06C8 #endif diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index a4aede2e5..86d1b488a 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -3,7 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -335,7 +335,8 @@ u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) { u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Flags_GetInfTable(INFTABLE_11E)) { return 0x3013; - } else if ((CUR_CAPACITY(UPG_BOMB_BAG) >= 20 || IS_RANDO) && this->waypoint > 7 && this->waypoint < 12) { + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 2, this) + && this->waypoint > 7 && this->waypoint < 12) { return 0x3012; } else { return 0x3011; @@ -350,13 +351,14 @@ s16 EnGo2_UpdateTalkStateGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Message_ShouldAdvance(play)) { if (this->actor.textId == 0x3012) { this->actionFunc = EnGo2_SetupGetItem; - if(!IS_RANDO) { + if(GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD, true, this)) { EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30); } else { - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40)); + this->actionFunc = EnGo2_SetGetItem; } Message_CloseTextbox(play); Flags_SetInfTable(INFTABLE_11E); + Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_CHILD); return NPC_TALK_STATE_ACTION; } else { return NPC_TALK_STATE_ACTION; @@ -416,11 +418,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtRollingSmall(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronDmtDcEntrance(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE) ? 0x3021 : Flags_GetInfTable(INFTABLE_E0) ? 0x302A : 0x3008; @@ -439,11 +439,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtDcEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityEntrance(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F0) ? 0x3015 : 0x3014; @@ -462,11 +460,9 @@ s16 EnGo2_UpdateTalkStateGoronCityEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityIsland(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F4) ? 0x3017 : 0x3016; @@ -485,11 +481,9 @@ s16 EnGo2_UpdateTalkStateGoronCityIsland(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityLowestFloor(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C @@ -511,18 +505,10 @@ s16 EnGo2_UpdateTalkStateGoronCityLowestFloor(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) { - // For rando, prioritize opening the doors in GC when Link the goron has been stopped when - // the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved - if (IS_RANDO) { - if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { - return 0x3030; - } else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { - return 0x3036; - } else if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { - return 0x3041; - } else { - return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; - } + // In case a hook neglects to set the override, fall back to the first dialogue + u16 overrideTextId = 0x3030; + if (GameInteractor_Should(GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, false, &overrideTextId)) { + return overrideTextId; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { @@ -543,20 +529,15 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { case TEXT_STATE_CLOSING: switch (this->actor.textId) { case 0x3036: - if (!IS_RANDO) { + Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT); + this->interactInfo.talkState = NPC_TALK_STATE_IDLE; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT, true, this)) { EnGo2_GetItem(this, play, GI_TUNIC_GORON); this->actionFunc = EnGo2_SetupGetItem; return NPC_TALK_STATE_ACTION; } else { - if (Flags_GetTreasure(play, 0x1F)) { - return NPC_TALK_STATE_IDLE; - } - - Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON)); - this->actionFunc = EnGo2_SetupGetItem; - Flags_SetTreasure(play, 0x1F); - return NPC_TALK_STATE_ACTION; + this->actionFunc = EnGo2_SetGetItem; + return this->interactInfo.talkState; } case 0x3037: Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK); @@ -605,7 +586,7 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(PlayState* play, EnGo2* this) { Player* player = GET_PLAYER(play); - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { @@ -627,17 +608,17 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { switch (EnGo2_GetDialogState(this, play)) { case TEXT_STATE_DONE: if (this->actor.textId == 0x305E) { - if((!IS_RANDO && gSaveContext.bgsFlag) || (IS_RANDO && Flags_GetTreasure(play, 0x1F))) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { return NPC_TALK_STATE_IDLE; } - - if(IS_RANDO) { - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); - Flags_SetTreasure(play, 0x1F); - } else { + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + if (GameInteractor_Should(GI_VB_TRADE_CLAIM_CHECK, true, this)) { EnGo2_GetItem(this, play, GI_SWORD_BGS); + this->actionFunc = EnGo2_SetupGetItem; + } else { + this->actionFunc = EnGo2_SetGetItem; } - this->actionFunc = EnGo2_SetupGetItem; + return NPC_TALK_STATE_ACTION; } else { return NPC_TALK_STATE_IDLE; @@ -663,16 +644,13 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { if (Message_ShouldAdvance(play)) { if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) { if (play->msgCtx.choiceIndex == 0) { - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN); - EnGo2_GetItemEntry(this, play, getItemEntry); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD); + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD); + if (GameInteractor_Should(GI_VB_TRADE_BROKEN_SWORD, true, this)) { + EnGo2_GetItem(this, play, GI_PRESCRIPTION); + this->actionFunc = EnGo2_SetupGetItem; } else { - u32 getItemId = GI_PRESCRIPTION; - EnGo2_GetItem(this, play, getItemId); + this->actionFunc = EnGo2_SetGetItem; } - this->actionFunc = EnGo2_SetupGetItem; return NPC_TALK_STATE_ACTION; } this->actor.textId = 0x3056; @@ -1070,7 +1048,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { u16 textId; if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { - if ((!IS_RANDO && gSaveContext.bgsFlag)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { this->actor.textId = 0x3003; } else { @@ -1080,18 +1058,14 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { } else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { - if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { - textId = 0x3003; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x305E; } else { textId = 0x305D; } this->actor.textId = textId; } else { - if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { - textId = 0x305E; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x3002; } else { textId = 0x305D; @@ -1219,8 +1193,7 @@ s32 EnGo2_IsCameraModified(EnGo2* this, PlayState* play) { (this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON || (this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) { return true; - } else if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { return true; } else { @@ -1278,8 +1251,7 @@ void EnGo2_SelectGoronWakingUp(EnGo2* this) { EnGo2_BiggoronWakingUp(this); break; case GORON_CITY_LINK: - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { EnGo2_WakingUp(this); break; @@ -1624,8 +1596,7 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { case GORON_CITY_LOWEST_FLOOR: case GORON_CITY_STAIRWELL: case GORON_CITY_LOST_WOODS: - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { Actor_Kill(&this->actor); } this->actionFunc = EnGo2_CurledUp; @@ -1640,8 +1611,7 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { if ((Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED))) { Path_CopyLastPoint(this->path, &this->actor.world.pos); this->actor.home.pos = this->actor.world.pos; - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { EnGo2_GetItemAnimation(this, play); } else { @@ -1862,11 +1832,7 @@ void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnGo2_SetGetItem; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } } @@ -1874,47 +1840,27 @@ void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - // For randomizer, handle updating the states for the gorons after receiving the item based on - // the goron type rather then the item being received - if (IS_RANDO) { - switch (this->actor.params & 0x1F) { - case GORON_DMT_BIGGORON: - // Resolves #1301. unk_13EE is used to set the opacity of the HUD. The trade sequence discussion with Biggoron - // sets the HUD to transparent, and it is restored at z_message_PAL:3549, but by specifically watching for - // trade sequence items, this leaves it transparent for non-trade sequence items (in rando) so we fix that here - gSaveContext.unk_13EE = 0x32; - return; - case GORON_CITY_LINK: + if (GameInteractor_Should(GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, true, this)) { + switch (this->getItemId) { + case GI_CLAIM_CHECK: + Environment_ClearBgsDayCount(); EnGo2_GetItemAnimation(this, play); return; - case GORON_CITY_ROLLING_BIG: + case GI_TUNIC_GORON: + Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); + EnGo2_GetItemAnimation(this, play); + return; + case GI_SWORD_BGS: + gSaveContext.bgsFlag = true; + break; + case GI_BOMB_BAG_30: + case GI_BOMB_BAG_40: EnGo2_RollingAnimation(this, play); this->actionFunc = EnGo2_GoronRollingBigContinueRolling; return; } this->actionFunc = func_80A46B40; - return; } - - switch (this->getItemId) { - case GI_CLAIM_CHECK: - Environment_ClearBgsDayCount(); - EnGo2_GetItemAnimation(this, play); - return; - case GI_TUNIC_GORON: - Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); - EnGo2_GetItemAnimation(this, play); - return; - case GI_SWORD_BGS: - gSaveContext.bgsFlag = true; - break; - case GI_BOMB_BAG_30: - case GI_BOMB_BAG_40: - EnGo2_RollingAnimation(this, play); - this->actionFunc = EnGo2_GoronRollingBigContinueRolling; - return; - } - this->actionFunc = func_80A46B40; } } @@ -1925,12 +1871,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; this->actor.shape.rot.y += 0x5B0; this->trackingMode = NPC_TRACKING_NONE; - this->animTimer = IS_RANDO ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer + this->animTimer = !GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL) ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer this->eyeMouthTexState = 2; this->unk_20C = 0; this->goronState++; func_800F483C(0x28, 5); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL)) { OnePointCutscene_Init(play, 4190, -99, &this->actor, MAIN_CAM); } break; @@ -1959,16 +1905,15 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->trackingMode = NPC_TRACKING_HEAD_AND_TORSO; this->skelAnime.playSpeed = 0.0f; this->skelAnime.curFrame = this->skelAnime.endFrame; - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); - Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS); - EnGo2_GetItemEntry(this, play, getItemEntry); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS); - } else { + + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS); + if(GameInteractor_Should(GI_VB_TRADE_EYEDROPS, true, this)) { u32 getItemId = GI_CLAIM_CHECK; EnGo2_GetItem(this, play, getItemId); + this->actionFunc = EnGo2_SetupGetItem; + } else { + this->actionFunc = EnGo2_SetGetItem; } - this->actionFunc = EnGo2_SetupGetItem; this->goronState = 0; } break; diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h index 86ac0c32e..185a036f4 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h @@ -107,4 +107,9 @@ typedef struct EnGo2 { /* */ GetItemEntry getItemEntry; } EnGo2; // size = 0x05A0 +void EnGo2_GetItemAnimation(EnGo2* enGo2, PlayState* play); +void EnGo2_RollingAnimation(EnGo2* enGo2, PlayState* play); +void EnGo2_GoronRollingBigContinueRolling(EnGo2* enGo2, PlayState* play); +void func_80A46B40(EnGo2* enGo2, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index 14b3703b8..c8d70fe1f 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -7,7 +7,7 @@ #include "z_en_hs.h" #include "vt.h" #include "objects/object_hs/object_hs.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -79,25 +79,7 @@ void EnHs_Init(Actor* thisx, PlayState* play) { // "chicken shop (adult era)" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST); func_80A6E3A0(this, func_80A6E9AC); - bool shouldSpawn; - bool tradedMushroom = Flags_GetItemGetInf(ITEMGETINF_30); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { - // To explain the logic because Fado and Grog are linked: - // - If you have Cojiro, then spawn Grog and not Fado. - // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. - // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. - // - If you don't have either but have traded the mushroom, don't spawn either. - if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { - shouldSpawn = true; - } else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) { - shouldSpawn = false; - } else { - shouldSpawn = !tradedMushroom; - } - } else { - shouldSpawn = !tradedMushroom; - } - if (!shouldSpawn) { + if (GameInteractor_Should(GI_VB_DESPAWN_GROG, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // "chicken shop closed" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST); Actor_Kill(&this->actor); @@ -148,11 +130,11 @@ void func_80A6E5EC(EnHs* this, PlayState* play) { void func_80A6E630(EnHs* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_TRADE_TIMER_ODD_MUSHROOM, true, NULL)) { func_80088AA0(180); + gSaveContext.eventInf[1] &= ~1; } func_80A6E3A0(this, func_80A6E6B0); - gSaveContext.eventInf[1] &= ~1; } this->unk_2A8 |= 1; @@ -175,19 +157,12 @@ void func_80A6E70C(EnHs* this, PlayState* play) { } void func_80A6E740(EnHs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { this->actor.parent = NULL; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); func_80A6E3A0(this, func_80A6E630); } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); - Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); - } else { - s32 itemId = GI_ODD_MUSHROOM; - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); - } + func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } this->unk_2A8 |= 1; @@ -198,14 +173,8 @@ void func_80A6E7BC(EnHs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: func_80A6E3A0(this, func_80A6E740); - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); - Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); - } else { - s32 itemId = GI_ODD_MUSHROOM; - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { + func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } break; case 1: diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index 50be2e458..793017d3d 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -6,6 +6,7 @@ #include "z_en_js.h" #include "objects/object_js/object_js.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -127,23 +128,15 @@ void func_80A8910C(EnJs* this, PlayState* play) { } void func_80A89160(EnJs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) { this->actor.parent = NULL; En_Js_SetupAction(this, func_80A8910C); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); - } else { - GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); - } + GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; + func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 25299f5b0..c801356c9 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -10,7 +10,7 @@ #include "objects/object_km1/object_km1.h" #include "objects/object_kw1/object_kw1.h" #include "vt.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -1027,20 +1027,9 @@ s32 EnKo_CanSpawn(EnKo* this, PlayState* play) { } case SCENE_LOST_WOODS: - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { - // To explain the logic because Fado and Grog are linked: - // - If you have Cojiro, then spawn Grog and not Fado. - // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. - // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. - // - If you don't have either but have traded the mushroom, don't spawn either. - if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { - return false; - } else { - return PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION); - } - } else { - return (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false; - } + return GameInteractor_Should(GI_VB_SPAWN_LW_FADO, ( + (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false + ), this); default: return false; } @@ -1186,18 +1175,10 @@ void func_80A99048(EnKo* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELF, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3); if (ENKO_TYPE == ENKO_TYPE_CHILD_3) { - if (!IS_RANDO) { - if (!CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - this->collider.dim.height += 200; - this->actionFunc = func_80A995CC; - return; - } - } else { - if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { - this->collider.dim.height += 200; - this->actionFunc = func_80A995CC; - return; - } + if (!GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { + this->collider.dim.height += 200; + this->actionFunc = func_80A995CC; + return; } Path_CopyLastPoint(this->path, &this->actor.world.pos); } @@ -1230,18 +1211,11 @@ void func_80A99438(EnKo* this, PlayState* play) { } void func_80A99504(EnKo* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_POTION, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 120.0f, 10.0f); - } else { - s32 itemId = GI_SAW; - func_8002F434(&this->actor, play, itemId, 120.0f, 10.0f); - } + func_8002F434(&this->actor, play, GI_SAW, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h index c247f53b9..5deeef465 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h @@ -57,4 +57,8 @@ typedef enum { ENKO_FQS_ADULT_SAVED } KokiriForestQuestState; +void func_80A995CC(EnKo* actor, PlayState* play); +void func_80A99384(EnKo* actor, PlayState* play); +void func_80A99560(EnKo* actor, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index ad3bd0ab5..3d5c2c354 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -6,7 +6,7 @@ #include "z_en_kz.h" #include "objects/object_kz/object_kz.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -73,12 +73,9 @@ static AnimationInfo sAnimationInfo[] = { u16 EnKz_GetTextNoMaskChild(PlayState* play, EnKz* this) { Player* player = GET_PLAYER(play); - if ((IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) || - (!IS_RANDO && CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) { - // Allow turning in Ruto's letter even if you have already rescued her - if (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - player->exchangeItemId = EXCH_ITEM_LETTER_RUTO; - } + if (GameInteractor_Should(GI_VB_KING_ZORA_THANK_CHILD, ( + CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) + ), this)) { return 0x402B; } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { return 0x401C; @@ -94,8 +91,10 @@ u16 EnKz_GetTextNoMaskAdult(PlayState* play, EnKz* this) { // this works because both ITEM_NONE and later trade items are > ITEM_FROG if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_FROG) { if (!Flags_GetInfTable(INFTABLE_139)) { - if (!IS_RANDO) { - return CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012; + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, ( + !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) + ), this)) { + return 0x401F; } else { return 0x4012; } @@ -243,7 +242,9 @@ void func_80A9CB18(EnKz* this, PlayState* play) { Player* player = GET_PLAYER(play); if (func_80A9C95C(play, this, &this->interactInfo.talkState, 340.0f, EnKz_GetText, func_80A9C6C0)) { - if (((IS_RANDO && LINK_IS_CHILD) || this->actor.textId == 0x401A) && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + if (GameInteractor_Should(GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, (this->actor.textId == 0x401A), this) && + !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) + { if (func_8002F368(play) == EXCH_ITEM_LETTER_RUTO) { this->actor.textId = 0x401B; this->sfxPlayed = false; @@ -257,7 +258,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) { if (LINK_IS_ADULT) { if ((INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) && (func_8002F368(play) == EXCH_ITEM_PRESCRIPTION)) { - if (!IS_RANDO || !Flags_GetTreasure(play, 0x1F)) { + if (GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) { this->actor.textId = 0x4014; this->sfxPlayed = false; player->actor.textId = this->actor.textId; @@ -271,11 +272,11 @@ void func_80A9CB18(EnKz* this, PlayState* play) { this->actor.textId = CHECK_QUEST_ITEM(QUEST_SONG_SERENADE) ? 0x4045 : 0x401A; player->actor.textId = this->actor.textId; } else { - if (!IS_RANDO) { - this->actor.textId = CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012; - } else { - this->actor.textId = 0x4012; - } + this->actor.textId = + !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + (!CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)), this) + ? 0x401F + : 0x4012; player->actor.textId = this->actor.textId; } @@ -344,29 +345,10 @@ void EnKz_Init(Actor* thisx, PlayState* play) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; Animation_ChangeByInfo(&this->skelanime, sAnimationInfo, ENKZ_ANIM_0); - if (!IS_RANDO) { - if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - } else { - int zorasFountain = Randomizer_GetSettingValue(RSK_ZORAS_FOUNTAIN); - switch (zorasFountain) { - case 0: - if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - break; - case 1: - if (LINK_IS_ADULT) { - EnKz_SetMovedPos(this, play); - } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - break; - case 2: - EnKz_SetMovedPos(this, play); - break; - } + if (GameInteractor_Should(GI_VB_KING_ZORA_BE_MOVED, ( + Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) + ), this)) { + EnKz_SetMovedPos(this, play); } if (LINK_IS_ADULT) { @@ -465,37 +447,29 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { f32 xzRange; f32 yRange; - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || ( + (this->isTrading && !GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) || + (!this->isTrading && !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, true, this)) + )) { this->actor.parent = NULL; this->interactInfo.talkState = NPC_TALK_STATE_TALKING; this->actionFunc = EnKz_StartTimer; - } else { - if (IS_RANDO) { - if (this->isTrading) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); - getItemId = getItemEntry.getItemId; - Randomizer_ConsumeAdultTradeItem(play, ITEM_PRESCRIPTION); - Flags_SetTreasure(play, 0x1F); - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); - getItemId = getItemEntry.getItemId; - } + if (!this->isTrading) { + Flags_SetRandomizerInf(RAND_INF_KING_ZORA_THAWED); } else { - getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION); } + } else { + getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; yRange = fabsf(this->actor.yDistToPlayer) + 1.0f; xzRange = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, xzRange, yRange); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, yRange); - } + func_8002F434(&this->actor, play, getItemId, xzRange, yRange); } } void EnKz_StartTimer(EnKz* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !IS_RANDO) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && GameInteractor_Should(GI_VB_TRADE_TIMER_FROG, true, NULL)) { func_80088AA0(180); // start timer2 with 3 minutes gSaveContext.eventInf[1] &= ~1; } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h index 37feb841a..c97732356 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h @@ -28,4 +28,6 @@ typedef struct EnKz { /* 0x02BE */ s16 unk_2BE[12]; } EnKz; // size = 0x02D8 +void EnKz_SetupGetItem(EnKz* enKz, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 8a11eb668..75db192cf 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -6,6 +6,7 @@ #include "z_en_ma1.h" #include "objects/object_ma1/object_ma1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -25,7 +26,6 @@ void func_80AA106C(EnMa1* this, PlayState* play); void func_80AA10EC(EnMa1* this, PlayState* play); void func_80AA1150(EnMa1* this, PlayState* play); void EnMa1_DoNothing(EnMa1* this, PlayState* play); -void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play); const ActorInit En_Ma1_InitVars = { ACTOR_EN_MA1, @@ -90,25 +90,16 @@ static void* sEyeTextures[] = { gMalonChildEyeClosedTex, }; -bool Randomizer_ObtainedMalonHCReward() { - return Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); -} - u16 EnMa1_GetText(PlayState* play, Actor* thisx) { - // Special case for Malon Hyrule Castle Text. Placing it here at the beginning - // has the added benefit of circumventing mask text if wearing bunny hood. - if (IS_RANDO && play->sceneNum == SCENE_HYRULE_CASTLE) { - return Randomizer_ObtainedMalonHCReward() ? 0x2044 : 0x2043; - } + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); u16 faceReaction = Text_GetFaceReaction(play, 0x17); if (faceReaction != 0) { return faceReaction; } - if (!IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) { - return 0x204A; - } + if (malonTaughtEponasSong) { + return 0x204A; } if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) { return 0x2049; @@ -120,7 +111,7 @@ u16 EnMa1_GetText(PlayState* play, Actor* thisx) { return 0x2048; } } - if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { + if (malonReturnedFromCastle) { return 0x2047; } if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) { @@ -194,6 +185,8 @@ s16 func_80AA0778(PlayState* play, Actor* thisx) { } s32 func_80AA08C4(EnMa1* this, PlayState* play) { + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + if ((this->actor.shape.rot.z == 3) && (gSaveContext.sceneSetupIndex == 5)) { return 1; } @@ -202,32 +195,24 @@ s32 func_80AA08C4(EnMa1* this, PlayState* play) { } // Causes Malon to appear in the market if you haven't met her yet. if (((play->sceneNum == SCENE_MARKET_NIGHT) || (play->sceneNum == SCENE_MARKET_DAY)) && - !Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + !malonReturnedFromCastle && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { return 1; } - if ((play->sceneNum == SCENE_HYRULE_CASTLE) && // if we're at hyrule castle - (!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || // and talon hasn't left - (IS_RANDO && - !Randomizer_ObtainedMalonHCReward()))) { // or we're rando'd and haven't gotten malon's HC check - if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { // if we've met malon - return 1; // make her appear at the castle - } else { // if we haven't met malon - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // set the flag for meeting malon - return 0; // don't make her appear at the castle + if ((play->sceneNum == SCENE_HYRULE_CASTLE) && !malonReturnedFromCastle) { + if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + return 1; + } else { + Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + return 0; } } - // Malon asleep in her bed if Talon has left Hyrule Castle and it is nighttime. - if ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) { + if ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && malonReturnedFromCastle) { return 1; } - // Don't spawn Malon if none of the above are true and we are not in Lon Lon Ranch. if (play->sceneNum != SCENE_LON_LON_RANCH) { return 0; } - // If we've gotten this far, we're in Lon Lon Ranch. Spawn Malon if it is daytime, Talon has left Hyrule Castle, and - // either we are not randomized, or we are and we have received Malon's item at Hyrule Castle. - if ((this->actor.shape.rot.z == 3) && IS_DAY && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) && - ((IS_RANDO && Randomizer_ObtainedMalonHCReward()) || !IS_RANDO)) { + if ((this->actor.shape.rot.z == 3) && IS_DAY && malonReturnedFromCastle) { return 1; } return 0; @@ -284,6 +269,8 @@ void func_80AA0B74(EnMa1* this) { void EnMa1_Init(Actor* thisx, PlayState* play) { EnMa1* this = (EnMa1*)thisx; + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); s32 pad; ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 18.0f); @@ -292,12 +279,6 @@ void EnMa1_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit); - if (IS_RANDO) { // Skip Malon's multiple textboxes before getting an item - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); - Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); - } - if (!func_80AA08C4(this, play)) { Actor_Kill(&this->actor); return; @@ -308,21 +289,10 @@ void EnMa1_Init(Actor* thisx, PlayState* play) { this->actor.targetMode = 6; this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - // To avoid missing a check, we want Malon to have the actionFunc for singing, but not reacting to Ocarina, if any of - // the following are true. - // 1. Talon has not left Hyrule Castle. - // 2. We are Randomized and have not obtained Malon's Weird Egg Check. - // 3. We are not Randomized and have obtained Epona's Song - if (!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward()) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO) || - (IS_RANDO && Flags_GetTreasure(play, 0x1F))) { + if (!malonReturnedFromCastle || malonTaughtEponasSong) { this->actionFunc = func_80AA0D88; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); - // If none of the above conditions were true, set Malon up to teach Epona's Song. } else { - if (IS_RANDO) { // Skip straight to "let's sing it together" textbox in the ranch - Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); - } - this->actionFunc = func_80AA0F44; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); } @@ -336,6 +306,9 @@ void EnMa1_Destroy(Actor* thisx, PlayState* play) { } void func_80AA0D88(EnMa1* this, PlayState* play) { + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); + if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (this->skelAnime.animation != &gMalonChildIdleAnim) { EnMa1_ChangeAnim(this, ENMA1_ANIM_1); @@ -346,16 +319,9 @@ void func_80AA0D88(EnMa1* this, PlayState* play) { } } - // We want to Kill Malon's Actor outside of randomizer when Talon is freed. In Randomizer we don't kill Malon's - // Actor here, otherwise if we wake up Talon first and then get her check she will spontaneously - // disappear. - if ((play->sceneNum == SCENE_HYRULE_CASTLE) && (!IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) { + if ((play->sceneNum == SCENE_HYRULE_CASTLE) && malonReturnedFromCastle) { Actor_Kill(&this->actor); - // We want Malon to give the Weird Egg Check (see function below) in the following situations: - // 1. Talon as not left Hyrule Castle (Vanilla) OR - // 2. We haven't obtained Malon's Weird Egg Check (Randomizer only) OR - // 3. We have Epona's Song? (Vanilla only, not sure why it's here but I didn't write that one) - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward())) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO)) { + } else if (!malonReturnedFromCastle || malonTaughtEponasSong) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { this->actionFunc = func_80AA0EA0; play->msgCtx.stateTimer = 4; @@ -365,21 +331,16 @@ void func_80AA0D88(EnMa1* this, PlayState* play) { } void func_80AA0EA0(EnMa1* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->actor.parent = NULL; this->actionFunc = func_80AA0EFC; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, GI_WEIRD_EGG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 10.0f); - } + func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); } } void func_80AA0EFC(EnMa1* this, PlayState* play) { - if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN) { + if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->actionFunc = func_80AA0D88; Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); @@ -387,24 +348,6 @@ void func_80AA0EFC(EnMa1* this, PlayState* play) { } } -void GivePlayerRandoRewardMalon(EnMa1* malon, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_EPONAS_SONG); - // Prevents flag from getting set if we weren't able to get the item (i.e. Player is holding shield - // when closing the textbox). - if (malon->actor.parent != NULL && malon->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - // puts malon in the action that vanilla has her in after learning the song - // (confirmed via breakpoints in a vanilla save). - malon->actionFunc = func_80AA0D88; - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&malon->actor, play, getItemEntry, 10000.0f, 100.0f); - } - // make malon sing again after giving the item. - malon->interactInfo.talkState = NPC_TALK_STATE_IDLE; - malon->unk_1E0 = 1; -} - void func_80AA0F44(EnMa1* this, PlayState* play) { Player* player = GET_PLAYER(play); @@ -419,7 +362,6 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { } if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) { - // When the player pulls out the Ocarina while close to Malon if (player->stateFlags2 & 0x1000000) { player->stateFlags2 |= 0x2000000; player->unk_6A8 = &this->actor; @@ -427,19 +369,10 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->interactInfo.talkState = NPC_TALK_STATE_TALKING; this->actor.flags |= ACTOR_FLAG_WILL_TALK; - // when rando'ed, skip to the Item Giving. Otherwise go to the song teaching code. - this->actionFunc = IS_RANDO ? func_80AA1150 : func_80AA106C; + this->actionFunc = func_80AA106C; } else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) { - // somehow flags that the player is close to malon so that pulling out the Ocarina - // triggers the code above this. player->stateFlags2 |= 0x800000; } - // If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina - // in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory. - if (IS_RANDO && (Actor_TextboxIsClosing(&this->actor, play) && play->msgCtx.textId == 0x2049) && - (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE)) { - this->actionFunc = EnMa1_WaitForSongGive; - } } } @@ -461,48 +394,16 @@ void func_80AA10EC(EnMa1* this, PlayState* play) { } } -void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play) { - // Actually give the song check. - GivePlayerRandoRewardMalon(this, play, RC_SONG_FROM_MALON); -} - -// Sets an Ocarina State necessary to not softlock in rando. -// This function should only be called in rando. -void EnMa1_EndTeachSong(EnMa1* this, PlayState* play) { - if (play->csCtx.state == CS_STATE_IDLE) { - this->actionFunc = func_80AA0F44; - play->msgCtx.ocarinaMode = OCARINA_MODE_04; - } - - if (IS_RANDO) { - // Transition to the giving the song check on the next update run. - this->actionFunc = EnMa1_WaitForSongGive; - } -} - void func_80AA1150(EnMa1* this, PlayState* play) { GET_PLAYER(play)->stateFlags2 |= 0x800000; - // When rando'ed, trigger the "song learned" Ocarina mode. - if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) { - play->msgCtx.ocarinaMode = OCARINA_MODE_03; - } - if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (!IS_RANDO) { - play->nextEntranceIndex = ENTR_LON_LON_RANCH_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; - play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST); - play->transitionTrigger = TRANS_TRIGGER_START; - this->actionFunc = EnMa1_DoNothing; - } else { - // When rando'ed, skip the cutscene, play the chime, reset some flags, - // and give the song on next update. - func_80078884(NA_SE_SY_CORRECT_CHIME); - this->actionFunc = EnMa1_EndTeachSong; - this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - play->msgCtx.ocarinaMode = OCARINA_MODE_00; - } + Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + play->nextEntranceIndex = ENTR_LON_LON_RANCH_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; + play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST); + play->transitionTrigger = TRANS_TRIGGER_START; + this->actionFunc = EnMa1_DoNothing; } } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h index 55b53bd72..f06f220c9 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h @@ -20,4 +20,7 @@ typedef struct EnMa1 { /* 0x01E8 */ NpcInteractInfo interactInfo; } EnMa1; // size = 0x0210 +void func_80AA106C(EnMa1* enMa1, PlayState* play); +void func_80AA0D88(EnMa1* enMa1, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index 14d9cbb7b..6fb9119bf 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -7,6 +7,7 @@ #include "z_en_md.h" #include "objects/object_md/object_md.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -372,11 +373,7 @@ u16 EnMd_GetTextKokiriForest(PlayState* play, EnMd* this) { this->unk_208 = 0; this->unk_209 = TEXT_STATE_NONE; - // In rando, skip talking about the tree being dead so we can have the prompt for sword and shield instead - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || - (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && - Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH))) { + if (GameInteractor_Should(GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { return 0x1045; } @@ -486,25 +483,6 @@ s16 func_80AAAF04(PlayState* play, Actor* thisx) { } u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) { - // In rando, Mido's spawn logic is adjusted to support closed deku/forest options - // He will spawn in the forest if you haven't showed the sword and shield, and will remain - // in the forest until you've obtained Zelda's letter or Deku Tree dies - // This is to ensure Deku Tree can still be opened in dungeon entrance rando even if Ghoma is defeated - if (IS_RANDO) { - if (play->sceneNum == SCENE_LOST_WOODS) { - return 1; - } - - if (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && - Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && - (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) || - Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD))) { - return play->sceneNum == SCENE_MIDOS_HOUSE && !LINK_IS_ADULT; - } - - return play->sceneNum == SCENE_KOKIRI_FOREST; - } - if (play->sceneNum == SCENE_KOKIRI_FOREST) { if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) { return 1; @@ -512,7 +490,7 @@ u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) { } if (play->sceneNum == SCENE_MIDOS_HOUSE) { - if (((Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH)) != 0) || ((Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) != 0)) { + if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) || Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) { if (!LINK_IS_ADULT) { return 1; } @@ -681,9 +659,8 @@ void EnMd_Init(Actor* thisx, PlayState* play) { this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, FAIRY_KOKIRI); if (((play->sceneNum == SCENE_KOKIRI_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || - ((play->sceneNum == SCENE_KOKIRI_FOREST) && (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && - ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)))) || + ((play->sceneNum == SCENE_KOKIRI_FOREST) && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && + CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || ((play->sceneNum == SCENE_LOST_WOODS) && !Flags_GetEventChkInf(EVENTCHKINF_PLAYED_SARIAS_SONG_FOR_MIDO_AS_ADULT))) { this->actor.home.pos = this->actor.world.pos; this->actionFunc = func_80AAB948; @@ -745,10 +722,11 @@ void func_80AAB948(EnMd* this, PlayState* play) { this->skelAnime.playSpeed = CLAMP(temp, 1.0f, 3.0f); } - if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || - IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && + if ( + (GameInteractor_Should(GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, this->interactInfo.talkState == NPC_TALK_STATE_ACTION, this) && play->sceneNum == SCENE_KOKIRI_FOREST) || + this->interactInfo.talkState == NPC_TALK_STATE_ACTION + ) { + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && (play->sceneNum == SCENE_KOKIRI_FOREST)) { play->msgCtx.msgMode = MSGMODE_PAUSED; } @@ -815,9 +793,7 @@ void func_80AABD0C(EnMd* this, PlayState* play) { return; } - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || - IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && (play->sceneNum == SCENE_KOKIRI_FOREST)) { Message_CloseTextbox(play); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH); diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index e5501858c..54e48bfc2 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -6,7 +6,7 @@ #include "z_en_mk.h" #include "objects/object_mk/object_mk.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -93,37 +93,24 @@ void func_80AACA40(EnMk* this, PlayState* play) { } void func_80AACA94(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) != 0) { + if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; - if (!IS_RANDO) { + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); + if (GameInteractor_Should(GI_VB_TRADE_TIMER_EYEDROPS, true, NULL)) { func_80088AA0(240); gSaveContext.eventInf[1] &= ~1; } } else { - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); - Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - } else { - s32 getItemID = GI_EYEDROPS; - func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f); - } + func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } void func_80AACB14(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACA94; - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); - Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - } else { - s32 getItemID = GI_EYEDROPS; - func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { + func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } } @@ -150,7 +137,7 @@ void func_80AACC04(EnMk* this, PlayState* play) { if (this->timer > 0) { this->timer--; } else { - this->timer = IS_RANDO ? 0 : 16; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; this->actionFunc = func_80AACBAC; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); @@ -163,7 +150,7 @@ void func_80AACCA0(EnMk* this, PlayState* play) { this->timer--; this->actor.shape.rot.y += 0x800; } else { - this->timer = IS_RANDO ? 0 : 120; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 120 : 0; this->actionFunc = func_80AACC04; Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f); @@ -179,7 +166,7 @@ void func_80AACD48(EnMk* this, PlayState* play) { this->actionFunc = func_80AACCA0; play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; - this->timer = IS_RANDO ? 0 : 16; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); this->flags &= ~2; @@ -213,29 +200,20 @@ void func_80AACEE8(EnMk* this, PlayState* play) { } void func_80AACFA0(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; Flags_SetItemGetInf(ITEMGETINF_10); } else { - // not sure when/how/if this is getting called - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } void func_80AAD014(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACFA0; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } @@ -255,9 +233,9 @@ void EnMk_Wait(EnMk* this, PlayState* play) { player->actor.textId = this->actor.textId; this->actionFunc = func_80AACA40; } else { - // Skip eye drop text on rando if Link went in the water, so you can still receive the dive check - if (INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS && - (!IS_RANDO || this->swimFlag == 0)) { + if (GameInteractor_Should(GI_VB_USE_EYEDROP_DIALOGUE, ( + INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS + ), this)) { player->actor.textId = 0x4032; this->actionFunc = func_80AACA40; } else { diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index b1d453f00..04b8166f7 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -6,6 +6,7 @@ #include "z_en_ms.h" #include "objects/object_ms/object_ms.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -127,20 +128,16 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } else if (Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - if (gSaveContext.rupees < - ((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) - ? 60 - : sPrices[BEANS_BOUGHT])) { + if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, ( + gSaveContext.rupees >= sPrices[BEANS_BOUGHT]), this)) { Message_ContinueTextbox(play, 0x4069); // not enough rupees text return; } - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f); - } else { + + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) { func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + this->actionFunc = EnMs_Sell; } - this->actionFunc = EnMs_Sell; return; case 1: // no Message_ContinueTextbox(play, 0x4068); @@ -152,23 +149,14 @@ void EnMs_Talk(EnMs* this, PlayState* play) { void EnMs_Sell(EnMs* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { - Rupees_ChangeBy((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sPrices[BEANS_BOUGHT]); + Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]); this->actor.parent = NULL; - this->actionFunc = - (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase; + this->actionFunc = EnMs_TalkAfterPurchase; } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); - BEANS_BOUGHT = 10; - } else { - GetItemEntry entry = ItemTable_Retrieve(GI_BEAN); - gSaveContext.pendingSaleMod = entry.modIndex; - gSaveContext.pendingSale = entry.itemId; - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); - } + GetItemEntry entry = ItemTable_Retrieve(GI_BEAN); + gSaveContext.pendingSaleMod = entry.modIndex; + gSaveContext.pendingSale = entry.itemId; + func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h index 70b105073..e626056f0 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h @@ -18,4 +18,7 @@ typedef struct EnMs { /* 0x024C */ s16 activeTimer; } EnMs; // size = 0x0250 +void EnMs_TalkAfterPurchase(EnMs* enMs, PlayState* play); +void EnMs_Wait(EnMs* enMs, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c index a519209aa..9a3990cf8 100644 --- a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c +++ b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_nb/object_nb.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -326,7 +327,9 @@ void EnNb_GiveMedallion(EnNb* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xC); - Item_Give(play, ITEM_MEDALLION_SPIRIT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SPIRIT); + } } void EnNb_ComeUpImpl(EnNb* this, PlayState* play) { @@ -342,7 +345,9 @@ void EnNb_SetupChamberCsImpl(EnNb* this, PlayState* play) { this->action = NB_CHAMBER_UNDERGROUND; play->csCtx.segment = &D_80AB431C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_SPIRIT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SPIRIT); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } } diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 8ddf52fad..b4e6d8892 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -3,7 +3,7 @@ #include "objects/object_os_anime/object_os_anime.h" #include "overlays/actors/ovl_En_Niw/z_en_niw.h" #include "vt.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -204,7 +204,9 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) { EnNiw* currentCucco; s32 phi_s1; - this->cuccosInPen = IS_RANDO ? (7 - Randomizer_GetSettingValue(RSK_CUCCO_COUNT)) : 0; + if (GameInteractor_Should(GI_VB_SET_CUCCO_COUNT, true, this)) { + this->cuccosInPen = 0; + } currentCucco = (EnNiw*)play->actorCtx.actorLists[ACTORCAT_PROP].head; while (currentCucco != NULL) { if (currentCucco->actor.id == ACTOR_EN_NIW) { @@ -239,9 +241,11 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) { phi_s1 = 7; } } + // Completed minigame and then threw Cucco(s) out of the pen if ((this->unk_26C != 0) && (phi_s1 < 7)) { phi_s1 = 9; } + this->actor.textId = sMissingCuccoTextIds[phi_s1]; if (Text_GetFaceReaction(play, 8) != 0) { this->actor.textId = Text_GetFaceReaction(play, 8); @@ -308,16 +312,18 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) { if (!Flags_GetItemGetInf(ITEMGETINF_0C)) { this->actor.parent = NULL; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) { this->getItemId = GI_BOTTLE; func_8002F434(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_CHILD, GI_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 100.0f, 50.0f); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } this->actionFunc = func_80ABAC00; return; + } if (this->unk_26C == 1) { this->getItemId = GI_RUPEE_PURPLE; @@ -398,15 +404,15 @@ void func_80ABA9B8(EnNiwLady* this, PlayState* play) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) { func_8002F434(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); + this->actionFunc = func_80ABAC00; } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - Flags_SetItemGetInf(ITEMGETINF_2C); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } - this->actionFunc = func_80ABAC00; break; case 1: this->actor.textId = sTradeItemTextIds[3]; @@ -433,15 +439,14 @@ void func_80ABAB08(EnNiwLady* this, PlayState* play) { case 0: Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_TRADE_POCKET_CUCCO, true, this)) { func_8002F434(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); + this->actionFunc = func_80ABAC00; } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO); - Randomizer_ConsumeAdultTradeItem(play, ITEM_POCKET_CUCCO); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - Flags_SetItemGetInf(ITEMGETINF_2E); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } - this->actionFunc = func_80ABAC00; break; case 1: Message_CloseTextbox(play); @@ -462,12 +467,6 @@ void func_80ABAC00(EnNiwLady* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80ABAC84; } else { - if (IS_RANDO) { - getItemId = this->getItemEntry.getItemId; - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - return; - } - getItemId = this->getItemId; if (LINK_IS_ADULT) { getItemId = !Flags_GetItemGetInf(ITEMGETINF_2C) ? GI_POCKET_EGG : GI_COJIRO; @@ -482,8 +481,7 @@ void func_80ABAC84(EnNiwLady* this, PlayState* play) { } osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (LINK_IS_ADULT) { - // Flags for randomizer gives are set in the original message prompt choice handling - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, true, this)) { if (!Flags_GetItemGetInf(ITEMGETINF_2C)) { Flags_SetItemGetInf(ITEMGETINF_2C); } else { diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 303c58819..4ae7d366f 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -10,6 +10,7 @@ #include "scenes/overworld/spot16/spot16_scene.h" #include "vt.h" #include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -42,6 +43,7 @@ void func_80ACAF74(EnOwl* this, PlayState* play); void func_80ACC30C(EnOwl* this, PlayState* play); void func_80ACB4FC(EnOwl* this, PlayState* play); void func_80ACB680(EnOwl* this, PlayState* play); +void func_80ACA62C(EnOwl* this, PlayState* play); void func_80ACC460(EnOwl* this); void func_80ACBEA0(EnOwl*, PlayState*); @@ -137,9 +139,7 @@ void EnOwl_Init(Actor* thisx, PlayState* play) { // "conversation owl %4x no = %d, sv = %d" osSyncPrintf(VT_FGCOL(CYAN) " 会話フクロウ %4x no = %d, sv = %d\n" VT_RST, this->actor.params, owlType, switchFlag); - if (((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) || - // Owl shortcuts at SPOT06: Lake Hylia and SPOT16: Death Mountain Trail - (IS_RANDO && !(play->sceneNum == SCENE_LAKE_HYLIA || play->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL))) { + if ((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) { osSyncPrintf("savebitでフクロウ退避\n"); // "Save owl with savebit" Actor_Kill(&this->actor); return; @@ -283,7 +283,7 @@ s32 EnOwl_CheckInitTalk(EnOwl* this, PlayState* play, u16 textId, f32 targetDist } else { this->actor.textId = textId; distCheck = (flags & 2) ? 200.0f : 1000.0f; - if (this->actor.xzDistToPlayer < targetDist) { + if (GameInteractor_Should(GI_VB_OWL_INTERACTION, this->actor.xzDistToPlayer < targetDist, this)) { this->actor.flags |= ACTOR_FLAG_WILL_TALK; func_8002F1C4(&this->actor, play, targetDist, distCheck, 0); } diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h index 7a20eaa3a..a898dce2a 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h @@ -43,4 +43,6 @@ typedef struct EnOwl { /* 0x0410 */ OwlFunc unk_410; } EnOwl; // size = 0x0414 +void func_80ACA62C(EnOwl* enOwl, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c index 73996d58f..eafa8b82e 100644 --- a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c +++ b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c @@ -7,6 +7,7 @@ #include "z_en_rl.h" #include "vt.h" #include "objects/object_rl/object_rl.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -126,7 +127,9 @@ void func_80AE7590(EnRl* this, PlayState* play) { pos.y = player->actor.world.pos.y + 80.0f; pos.z = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true); - Item_Give(play, ITEM_MEDALLION_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_LIGHT); + } this->lightMedallionGiven = 1; } } diff --git a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c index fe4a77724..93d1fd99c 100644 --- a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c +++ b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c @@ -8,6 +8,7 @@ #include "objects/object_ru2/object_ru2.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -260,7 +261,9 @@ void func_80AF2A38(EnRu2* this, PlayState* play) { f32 posZ = player->actor.world.pos.z; Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 10); - Item_Give(play, ITEM_MEDALLION_WATER); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_WATER); + } } void func_80AF2AB4(EnRu2* this, PlayState* play) { @@ -273,7 +276,9 @@ void func_80AF2AB4(EnRu2* this, PlayState* play) { this->action = 1; play->csCtx.segment = &D_80AF411C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_WATER); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_WATER); + } temp = this->actor.world.rot.y + 0x8000; player->actor.shape.rot.y = temp; player->actor.world.rot.y = temp; diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index 9e09a705c..f2b2db3f9 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -3,6 +3,7 @@ #include "objects/object_sa/object_sa.h" #include "scenes/overworld/spot04/spot04_scene.h" #include "scenes/overworld/spot05/spot05_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -390,13 +391,10 @@ s32 func_80AF5DFC(EnSa* this, PlayState* play) { return 1; } if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW && (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER))) { - if (IS_RANDO) { - return 5; - } - return CHECK_QUEST_ITEM(QUEST_SONG_SARIA) ? 2 : 5; + return GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, !CHECK_QUEST_ITEM(QUEST_SONG_SARIA), NULL) ? 5 : 2; } if (play->sceneNum == SCENE_KOKIRI_FOREST && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - if (Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + if (GameInteractor_Should(GI_VB_NOT_BE_GREETED_BY_SARIA, Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA), NULL)) { return 1; } return 4; @@ -622,28 +620,17 @@ void func_80AF67D0(EnSa* this, PlayState* play) { } } -void GivePlayerRandoRewardSaria(EnSa* saria, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SARIAS_SONG); - if (saria->actor.parent != NULL && saria->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&saria->actor, play, getItemEntry, 10000.0f, 100.0f); - } -} - void func_80AF683C(EnSa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (!(player->actor.world.pos.z >= -2220.0f) && !Play_InCsMode(play)) { - if (IS_RANDO) { - GivePlayerRandoRewardSaria(this, play, RC_SONG_FROM_SARIA); - return; + // SOH [General] This flag was previously unused, but was named accordingly so we will make use of it. (Normally we should opt for soh_inf) + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); + if (GameInteractor_Should(GI_VB_PLAY_SARIAS_SONG_CS, true, this)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730); + gSaveContext.cutsceneTrigger = 1; + this->actionFunc = func_80AF68E4; } - - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730); - gSaveContext.cutsceneTrigger = 1; - this->actionFunc = func_80AF68E4; } } @@ -721,7 +708,9 @@ void func_80AF68E4(EnSa* this, PlayState* play) { void func_80AF6B20(EnSa* this, PlayState* play) { if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW) { - Item_Give(play, ITEM_SONG_SARIA); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) { + Item_Give(play, ITEM_SONG_SARIA); + } EnSa_ChangeAnim(this, ENSA_ANIM1_6); } diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h index 2965f04ab..56d368f13 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h @@ -30,4 +30,6 @@ typedef struct EnSa { /* 0x0286 */ Vec3s morphTable[17]; } EnSa; // size = 0x02EC +void func_80AF6B20(EnSa* enSa, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index 6f48314ff..0f300d16f 100644 --- a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -1,5 +1,6 @@ #include "z_en_shopnuts.h" #include "objects/object_shopnuts/object_shopnuts.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) @@ -69,18 +70,11 @@ void EnShopnuts_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); Collider_UpdateCylinder(&this->actor, &this->collider); - if (IS_RANDO) { - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(play->sceneNum, this->actor.params, respawnData); - - if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) { - Actor_Kill(&this->actor); - } - } - - if (((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || + if (GameInteractor_Should(GI_VB_BUSINESS_SCRUB_DESPAWN, + ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) || - ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))) { + ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))), + this)) { Actor_Kill(&this->actor); } else { EnShopnuts_SetupWait(this); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 49e88f903..8eb669d2d 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -7,9 +7,6 @@ #include "z_en_si.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -extern void func_8083C148(Player*, PlayState*); -extern void func_80078884(uint16_t); - #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOOKSHOT_DRAGS) void EnSi_Init(Actor* thisx, PlayState* play); @@ -21,13 +18,6 @@ s32 func_80AFB748(EnSi* this, PlayState* play); void func_80AFB768(EnSi* this, PlayState* play); void func_80AFB89C(EnSi* this, PlayState* play); void func_80AFB950(EnSi* this, PlayState* play); -void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play); -void Randomizer_GiveSkullReward(EnSi* this, PlayState* play); - -s32 textId = 0xB4; -s32 giveItemId = ITEM_SKULL_TOKEN; -s32 getItemId; -GetItemEntry getItem; static ColliderCylinderInit sCylinderInit = { { @@ -104,36 +94,12 @@ void func_80AFB768(EnSi* this, PlayState* play) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; - - if (IS_RANDO) { - Randomizer_UpdateSkullReward(this, play); - } else { - Item_Give(play, giveItemId); - } - if ((!CVarGetInteger("gSkulltulaFreeze", 0) || giveItemId != ITEM_SKULL_TOKEN) && - getItemId != RG_ICE_TRAP) { - player->actor.freezeTimer = 20; - } - - if (getItemId == RG_ICE_TRAP && Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + Item_Give(play, ITEM_SKULL_TOKEN); player->actor.freezeTimer = 10; - } - - Message_StartTextbox(play, textId, NULL); - - if (IS_RANDO) { - if (getItemId != RG_ICE_TRAP) { - Randomizer_GiveSkullReward(this, play); - Audio_PlayFanfare_Rando(getItem); - } else { - gSaveContext.pendingIceTrapCount++; - Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - } - } else { + Message_StartTextbox(play, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } - - player->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = func_80AFB950; } else { Collider_UpdateCylinder(&this->actor, &this->collider); @@ -146,32 +112,18 @@ void func_80AFB768(EnSi* this, PlayState* play) { void func_80AFB89C(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); + Math_SmoothStepToF(&this->actor.scale.x, 0.25f, 0.4f, 1.0f, 0.0f); Actor_SetScale(&this->actor, this->actor.scale.x); this->actor.shape.rot.y += 0x400; if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_HOOKSHOT_ATTACHED)) { - if (IS_RANDO) { - Randomizer_UpdateSkullReward(this, play); - } else { - Item_Give(play, giveItemId); - } - - Message_StartTextbox(play, textId, NULL); - - if (IS_RANDO) { - if (getItemId != RG_ICE_TRAP) { - Randomizer_GiveSkullReward(this, play); - Audio_PlayFanfare_Rando(getItem); - } else { - gSaveContext.pendingIceTrapCount++; - Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - } - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + Item_Give(play, ITEM_SKULL_TOKEN); + player->actor.freezeTimer = 10; + Message_StartTextbox(play, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } - - player->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = func_80AFB950; } } @@ -179,19 +131,12 @@ void func_80AFB89C(EnSi* this, PlayState* play) { void func_80AFB950(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && - (!CVarGetInteger("gSkulltulaFreeze", 0) || getItemId == RG_ICE_TRAP || giveItemId != ITEM_SKULL_TOKEN)) { + if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); GameInteractor_ExecuteOnFlagSet(FLAG_GS_TOKEN, this->actor.params); Actor_Kill(&this->actor); - if (gSaveContext.pendingIceTrapCount > 0 && player->heldItemId == 11) { - player->actor.freezeTimer = 0; - func_8083C148(GET_PLAYER(play), play); - func_80078884(NA_SE_SY_CAMERA_ZOOM_UP); - player->currentYaw = player->actor.shape.rot.y; - } } } @@ -210,44 +155,6 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (this->actionFunc != func_80AFB950) { func_8002ED80(&this->actor, play, 0); func_8002EBCC(&this->actor, play, 0); - if (!IS_RANDO) { - GetItem_Draw(play, GID_SKULL_TOKEN_2); - } else { - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); - EnItem00_CustomItemsParticles(&this->actor, play, getItem); - if (getItem.itemId != ITEM_SKULL_TOKEN) { - f32 mtxScale = 1.5f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - } - GetItemEntry_Draw(play, getItem); - } - } -} - -void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); - getItemId = getItem.getItemId; - if (getItemId == RG_ICE_TRAP) { - textId = 0xF8; - } else { - textId = getItem.textId; - giveItemId = getItem.itemId; - } - player->getItemEntry = getItem; -} - -void Randomizer_GiveSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - if (getItem.modIndex == MOD_NONE) { - // RANDOTOD: Move this into Item_Give() or some other more central location - if (getItem.getItemId == GI_SWORD_BGS) { - gSaveContext.bgsFlag = true; - } - Item_Give(play, giveItemId); - } else if (getItem.modIndex == MOD_RANDOMIZER) { - Randomizer_Item_Give(play, getItem); + GetItem_Draw(play, GID_SKULL_TOKEN_2); } } diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.h b/soh/src/overlays/actors/ovl_En_Si/z_en_si.h index dc0a3b400..318876289 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.h +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.h @@ -13,6 +13,9 @@ typedef struct EnSi { /* 0x014C */ EnSiActionFunc actionFunc; /* 0x0150 */ ColliderCylinder collider; /* 0x019C */ u8 unk_19C; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohGetItemEntry; + // #endregion } EnSi; // size = 0x01A0 #endif diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 0eb3e9095..2f47f7c2a 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -7,6 +7,7 @@ #include "z_en_ta.h" #include "vt.h" #include "objects/object_ta/object_ta.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -466,7 +467,7 @@ void func_80B14B6C(EnTa* this, PlayState* play) { func_80B13AA0(this, func_80B14AF4, func_80B167C0); this->unk_2CC = 5; Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); - if (IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_EndCutscene(play, csCamIdx); } Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim); diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index 55fbed824..342eed149 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -8,12 +8,9 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_tk/object_tk.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) -#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19 -#define ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE 0x1000 - -bool heartPieceSpawned; void EnTk_Init(Actor* thisx, PlayState* play); void EnTk_Destroy(Actor* thisx, PlayState* play); @@ -408,10 +405,6 @@ s32 EnTk_ChooseReward(EnTk* this) { f32 luck; s32 reward; - if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { - return 3; - } - luck = Rand_ZeroOne(); if (luck < 0.4f) { @@ -502,12 +495,7 @@ void EnTk_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (CVarGetInteger("gDampeAllNight", 0)) { - if (!!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) { - Actor_Kill(&this->actor); - return; - } - } else if (gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || !!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) { + if (GameInteractor_Should(GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD, this)) { Actor_Kill(&this->actor); return; } @@ -519,7 +507,6 @@ void EnTk_Init(Actor* thisx, PlayState* play) { this->currentReward = -1; this->currentSpot = NULL; this->actionFunc = EnTk_Rest; - heartPieceSpawned = false; } void EnTk_Destroy(Actor* thisx, PlayState* play) { @@ -599,7 +586,11 @@ void EnTk_Dig(EnTk* this, PlayState* play) { Vec3f rewardOrigin; Vec3f rewardPos; s32 rewardParams[] = { - ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, ITEM00_HEART_PIECE, + ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, + // #region SOH [General] Typically this heart piece would have no collectible flag set when it's picked up, but for both randomizer + // and gGravediggingTourFix we want to set one, and rely on it instead of the ItemGetInf flag that is set when the heart is spawned + ((COLLECTFLAG_GRAVEDIGGING_HEART_PIECE & 0x3F) << 8) | ITEM00_HEART_PIECE, + // #endregion }; EnTk_DigEff(this); @@ -610,7 +601,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->rewardTimer = 0; - if (this->validDigHere == 1 || IS_RANDO || CVarGetInteger("gDampeWin", 0)) { + if (GameInteractor_Should(GI_VB_BE_VALID_GRAVEDIGGING_SPOT, this->validDigHere == 1, this)) { rewardOrigin.x = 0.0f; rewardOrigin.y = 0.0f; rewardOrigin.z = -40.0f; @@ -624,51 +615,24 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->currentReward = EnTk_ChooseReward(this); - if (this->currentReward == 3) { - if (IS_RANDO || CVarGetInteger("gDampeWin", 0)) { - /* - * Upgrade the purple rupee reward to the heart piece if this - * is the first grand prize dig. - */ - if (!Flags_GetItemGetInf(ITEMGETINF_1C) && !(IS_RANDO || CVarGetInteger("gDampeWin", 0))) { - Flags_SetItemGetInf(ITEMGETINF_1C); - this->currentReward = 4; - } else if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { - this->currentReward = 4; - } - } + if (GameInteractor_Should(GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, this->currentReward == 3, this)) { /* - * Upgrade the purple rupee reward to the heart piece if this - * is the first grand prize dig. - */ - // If vanilla itemGetInf flag is not set, it's impossible for the new flag to be set, so return true. - // Otherwise if the gGravediggingTourFix is enabled and the new flag hasn't been set, return true. - // If true, spawn the heart piece and set the vanilla itemGetInf flag and new temp clear flag. - if (!heartPieceSpawned && - (!(gSaveContext.itemGetInf[1] & ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE) || - CVarGetInteger("gGravediggingTourFix", 0) && - !Flags_GetCollectible(play, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE))) { + * Upgrade the purple rupee reward to the heart piece if this + * is the first grand prize dig. + */ + if (GameInteractor_Should(GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, !Flags_GetItemGetInf(ITEMGETINF_1C), this)) { + Flags_SetItemGetInf(ITEMGETINF_1C); this->currentReward = 4; - gSaveContext.itemGetInf[1] |= ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE; - heartPieceSpawned = true; } } - if (IS_RANDO && this->currentReward == 4) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, rewardPos.x, rewardPos.y, rewardPos.z, 0, 0, 0, 0x1906, true); - this->heartPieceSpawned = 1; - } else { - EnItem00* reward = Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]); - if (this->currentReward == 4) { - reward->collectibleFlag = COLLECTFLAG_GRAVEDIGGING_HEART_PIECE; - } - } + Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]); } } if (this->skelAnime.curFrame >= 32.0f && this->rewardTimer == 10) { /* Play a reward sound shortly after digging */ - if (!(IS_RANDO || CVarGetInteger("gDampeWin", 0)) && this->validDigHere == 0) { + if (this->validDigHere == 0) { /* Bad dig spot */ Audio_PlayActorSound2(&this->actor, NA_SE_SY_ERROR); } else if (this->currentReward == 4) { diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h index c60cb5200..c2dee0fce 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h @@ -8,6 +8,8 @@ /* Dirt particle effect */ struct EnTkEff; +#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19 + typedef struct EnTkEff { /* 0x0000 */ u8 active; /* 0x0001 */ u8 timeLeft; diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index d52b82d8d..c2ac2861b 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -6,7 +6,7 @@ #include "z_en_toryo.h" #include "objects/object_toryo/object_toryo.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -291,10 +291,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { s16 sp32; s16 sp30; - // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw - // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. - bool checkAnim = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? play->animationCtx.animationCount <= 1 : true; - if (this->unk_1E4 == 3 && checkAnim) { + if (this->unk_1E4 == 3 && !GameInteractor_Should(GI_VB_FIX_SAW_SOFTLOCK, false, NULL)) { Actor_ProcessTalkRequest(&this->actor, play); Message_ContinueTextbox(play, this->actor.textId); this->unk_1E4 = 1; @@ -315,19 +312,12 @@ void func_80B20768(EnToryo* this, PlayState* play) { } if (this->unk_1E4 == 4) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_SAW, true, this)) { this->actor.parent = NULL; this->unk_1E4 = 5; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SAW); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 100.0f, 10.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); - } else { - s32 itemId = GI_SWORD_BROKEN; - func_8002F434(&this->actor, play, itemId, 100.0f, 10.0f); - } + func_8002F434(&this->actor, play, GI_SWORD_BROKEN, 100.0f, 10.0f); } return; } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index 2b90e1ff7..658dd63f8 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -6,6 +6,7 @@ #include "z_en_wonder_talk2.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_LOCKON) @@ -194,7 +195,9 @@ void func_80B3A3D4(EnWonderTalk2* this, PlayState* play) { this->unk_15A = true; } this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED); - func_8002DF54(play, NULL, 7); + if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { + func_8002DF54(play, NULL, 7); + } this->unk_156 = true; this->actionFunc = func_80B3A4F8; break; @@ -252,42 +255,12 @@ void func_80B3A4F8(EnWonderTalk2* this, PlayState* play) { } this->unk_158 = 0; if (!this->unk_156) { - // Whether or not to skip the text in rando - bool randoSkipText = false; - if (IS_RANDO) { - // Scenes for which all of this type of wonder talk should be skipped. - switch (play->sceneNum) { - case SCENE_SHADOW_TEMPLE: // Shadow Temple - randoSkipText = true; - break; - case SCENE_GERUDO_TRAINING_GROUND: // Gerudo Training Grounds - randoSkipText = true; - break; - case SCENE_THIEVES_HIDEOUT: // Inside Gerudo Fortress - randoSkipText = true; - break; - default: - break; - } - // individual textIds that should be skipped, or that should be preserved - // in a scene that otherwise has all wonder talk skipped. - //switch (this->actor.textId) { - // case: 0x023c //textId we want to skip - // randoSkipText = true; - // break; - // case 0x023c: // textId in a skipped scene that we don't want to skip - // randoSkipText = false; - // break; - // default: - // break; - //} - } - if (!(randoSkipText)) { + if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { Message_StartTextbox(play, this->actor.textId, NULL); func_8002DF54(play, NULL, 8); - this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; - this->actionFunc = func_80B3A3D4; } + this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; + this->actionFunc = func_80B3A3D4; } } else { diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 83f799877..6436df29f 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -13,6 +13,7 @@ #include "scenes/indoors/tokinoma/tokinoma_scene.h" #include "scenes/dungeons/ice_doukutu/ice_doukutu_scene.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -277,6 +278,7 @@ void func_80B3C9EC(EnXc* this) { this->action = SHEIK_ACTION_BLOCK_PEDESTAL; this->drawMode = SHEIK_DRAW_DEFAULT; this->unk_30C = 1; + // SOH [Randomizer] We don't want sheik blocking the pedestal in randomizer if (IS_RANDO) { Actor_Kill(&this->actor); } @@ -292,24 +294,6 @@ void func_80B3CA38(EnXc* this, PlayState* play) { } } -void GivePlayerRandoRewardSheikSong(EnXc* sheik, PlayState* play, RandomizerCheck check, int sheikType, GetItemID ogSongId) { - Player* player = GET_PLAYER(play); - if (!(gSaveContext.eventChkInf[5] & sheikType)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, ogSongId); - if (check == RC_SHEIK_AT_TEMPLE && !Flags_GetTreasure(play, 0x1F)) { - if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - } else if (check != RC_SHEIK_AT_TEMPLE) { - if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } - } - } -} - s32 EnXc_MinuetCS(EnXc* this, PlayState* play) { if (this->actor.params == SHEIK_TYPE_MINUET) { Player* player = GET_PLAYER(play); @@ -317,16 +301,17 @@ s32 EnXc_MinuetCS(EnXc* this, PlayState* play) { if (z < -2225.0f) { if (!Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gMinuetCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST); - Item_Give(play, ITEM_SONG_MINUET); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_FOREST, 1, RG_MINUET_OF_FOREST); - return false; } - return true; + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) { + Item_Give(play, ITEM_SONG_MINUET); + } + if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { + return true; + } } } return false; @@ -353,16 +338,17 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { if ((posRot->pos.x > -784.0f) && (posRot->pos.x < -584.0f) && (posRot->pos.y > 447.0f) && (posRot->pos.y < 647.0f) && (posRot->pos.z > -446.0f) && (posRot->pos.z < -246.0f) && !Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gDeathMountainCraterBoleroCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE); - Item_Give(play, ITEM_SONG_BOLERO); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_CRATER, 2, RG_BOLERO_OF_FIRE); - return false; } - return true; + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) { + Item_Give(play, ITEM_SONG_BOLERO); + } + if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { + return true; + } } return false; } @@ -370,13 +356,8 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { } void EnXc_SetupSerenadeAction(EnXc* this, PlayState* play) { - if (IS_RANDO) { - this->action = SHEIK_ACTION_SERENADE; - return; - } - // Player is adult and does not have iron boots and has not learned Serenade - if ((!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT, NULL)) { this->action = SHEIK_ACTION_SERENADE; osSyncPrintf("水のセレナーデ シーク誕生!!!!!!!!!!!!!!!!!!\n"); } else { @@ -389,22 +370,20 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { if (this->actor.params == SHEIK_TYPE_SERENADE) { Player* player = GET_PLAYER(play); s32 stateFlags = player->stateFlags1; - - if (((CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !IS_RANDO) || - (Flags_GetTreasure(play, 2) && IS_RANDO)) && - !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !(stateFlags & 0x20000000) && - !Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), NULL) && + !(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && !Play_InCsMode(play)) { + if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { Cutscene_SetSegment(play, &gIceCavernSerenadeCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag + } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) { Item_Give(play, ITEM_SONG_SERENADE); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_ICE_CAVERN, 4, RG_SERENADE_OF_WATER); - return false; } osSyncPrintf("ブーツを取った!!!!!!!!!!!!!!!!!!\n"); - return true; + if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { + return true; + } } osSyncPrintf("はやくブーツを取るべし!!!!!!!!!!!!!!!!!!\n"); return false; @@ -415,7 +394,7 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { void EnXc_DoNothing(EnXc* this, PlayState* play) { } -void EnXc_RandoStand(EnXc* this, PlayState* play) { +void SoH_EnXc_RandoStand(EnXc* this, PlayState* play) { //Replaces Ganondorf Light Arrow hint. also stands in ToT if (play->sceneNum == SCENE_TEMPLE_OF_TIME) { EnXc_ChangeAnimation(this, &gSheikArmsCrossedIdleAnim, ANIMMODE_LOOP, 0.0f, false); @@ -2209,22 +2188,21 @@ void EnXc_InitTempleOfTime(EnXc* this, PlayState* play) { if (LINK_IS_ADULT) { if (!Flags_GetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL)) { Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs); - gSaveContext.cutsceneTrigger = 1; + if (GameInteractor_Should(GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, true, NULL)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs); + gSaveContext.cutsceneTrigger = 1; + } func_80B3EBF0(this, play); - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) && - !IS_RANDO) || - (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && - IS_RANDO)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) { Item_Give(play, ITEM_SONG_PRELUDE); + } + if (GameInteractor_Should(GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimePreludeCs); gSaveContext.cutsceneTrigger = 1; - this->action = SHEIK_ACTION_30; - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT); } + this->action = SHEIK_ACTION_30; // Not sure what this does exactly } else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) { func_80B3C9EC(this); } else { @@ -2378,14 +2356,6 @@ void EnXc_Update(Actor* thisx, PlayState* play) { EnXc* this = (EnXc*)thisx; s32 action = this->action; - if (this->actor.params == SHEIK_TYPE_9) { - if (IS_RANDO && LINK_IS_ADULT) { - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT); - } - } - } - if ((action < 0) || (action >= ARRAY_COUNT(sActionFuncs)) || (sActionFuncs[action] == NULL)) { osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); } else { @@ -2433,7 +2403,7 @@ void EnXc_Init(Actor* thisx, PlayState* play) { EnXc_DoNothing(this, play); break; case SHEIK_TYPE_RANDO: - EnXc_RandoStand(this, play); + SoH_EnXc_RandoStand(this, play); break; default: osSyncPrintf(VT_FGCOL(RED) " En_Oa2 の arg_data がおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); diff --git a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c index 4a47b456e..9bc53169b 100644 --- a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c +++ b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c @@ -10,6 +10,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "objects/object_zl2/object_zl2.h" #include "objects/object_zl2_anime1/object_zl2_anime1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -633,7 +634,9 @@ void EnZl2_GiveLightArrows(EnZl2* this, PlayState* play) { posY = player->actor.world.pos.y + 80.0f; posZ = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true); - Item_Give(play, ITEM_ARROW_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + Item_Give(play, ITEM_ARROW_LIGHT); + } this->unk_244 = 1; } } diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index 08c3857e0..f805e2fb5 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -7,6 +7,7 @@ #include "z_en_zl4.h" #include "objects/object_zl4/object_zl4.h" #include "scenes/indoors/nakaniwa/nakaniwa_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -227,20 +228,6 @@ u16 EnZl4_GetText(PlayState* play, Actor* thisx) { return ret; } -void GivePlayerRandoRewardZeldaChild(EnZl4* zelda, PlayState* play, RandomizerCheck check) { - if (zelda->actor.parent != NULL && zelda->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1E)) { - Flags_SetTreasure(play, 0x1E); - } else if (!Flags_GetTreasure(play, 0x1E) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA) && Actor_TextboxIsClosing(&zelda->actor, play) && - (play->msgCtx.textId == 0x703C || play->msgCtx.textId == 0x703D)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, GI_LETTER_ZELDA); - GiveItemEntryFromActor(&zelda->actor, play, getItemEntry, 10000.0f, 100.0f); - } else if (Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, GET_PLAYER(play))) { - gSaveContext.unk_13EE = 0x32; - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); - } -} - s16 func_80B5B9B0(PlayState* play, Actor* thisx) { EnZl4* this = (EnZl4*)thisx; @@ -389,12 +376,6 @@ void EnZl4_Init(Actor* thisx, PlayState* play) { this->actor.textId = -1; this->eyeExpression = this->mouthExpression = ZL4_MOUTH_NEUTRAL; - if (IS_RANDO) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); - this->actionFunc = EnZl4_Idle; - return; - } - if (gSaveContext.sceneSetupIndex >= 4) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->actionFunc = EnZl4_TheEnd; @@ -1127,14 +1108,16 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { Camera_ChangeSetting(GET_ACTIVE_CAM(play), 1); this->talkState = 7; play->talkWithPlayer(play, &this->actor); - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { + func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); + } play->msgCtx.stateTimer = 4; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; } break; case 7: - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->talkState++; } else { @@ -1225,11 +1208,6 @@ void EnZl4_Idle(EnZl4* this, PlayState* play) { Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 60.0f, EnZl4_GetText, func_80B5B9B0); func_80B5BB78(this, play); - - if (IS_RANDO) { - GivePlayerRandoRewardZeldaChild(this, play, RC_HC_ZELDAS_LETTER); - return; - } } void EnZl4_TheEnd(EnZl4* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h index 601ed6905..4b14121c6 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h @@ -31,4 +31,9 @@ typedef struct EnZl4 { /* 0x0284 */ Vec3s morphTable[18]; } EnZl4; // size = 0x02F0 +s16 func_80B5B9B0(PlayState* play, Actor* actor); +void func_80B5BB78(EnZl4* enZl4, PlayState* play); +void EnZl4_Cutscene(EnZl4* enZl4, PlayState* play); +s32 EnZl4_SetNextAnim(EnZl4* enZl4, s32 nextAnim); + #endif diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index abb65c191..f511d5bbf 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -59,12 +59,7 @@ void ItemBHeart_Update(Actor* thisx, PlayState* play) { Flags_SetCollectible(play, 0x1F); Actor_Kill(&this->actor); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_HEART_CONTAINER_2); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 40.0f); - } + func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); } } @@ -98,23 +93,18 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { actorIt = actorIt->next; } - if (IS_RANDO) { - GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id, - play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); + if (flag) { + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); } else { - if (flag) { - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); - } else { - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); - } + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h index d9483b48c..434aa775b 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h @@ -13,6 +13,11 @@ typedef struct ItemBHeart { /* 0x015C */ char unk_15C[0x8]; /* 0x0164 */ s16 unk_164; /* 0x0166 */ char unk_166[0x6]; + // #region SOH [Randomizer] Cached for drawing for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } ItemBHeart; // size = 0x016C +void func_80B85264(ItemBHeart* itemBHeart, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index a9cd36446..dba879115 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -6,6 +6,7 @@ #include "z_item_ocarina.h" #include "scenes/overworld/spot00/spot00_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -169,31 +170,27 @@ void ItemOcarina_DoNothing(ItemOcarina* this, PlayState* play) { void ItemOcarina_StartSoTCutscene(ItemOcarina* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - if (!IS_RANDO) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs); - gSaveContext.cutsceneTrigger = 1; - } else { - play->transitionTrigger = TRANS_TRIGGER_START; - play->transitionType = TRANS_TYPE_FADE_WHITE; - gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; - play->nextEntranceIndex = ENTR_HYRULE_FIELD_16; - gSaveContext.nextCutsceneIndex = 0; - } + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs); + gSaveContext.cutsceneTrigger = 1; } } void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if ( + Actor_HasParent(&this->actor, play) || + ( + !GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL) && + (this->actor.xzDistToPlayer < 20.0f) && (fabsf(this->actor.yDistToPlayer) < 10.0f) && + GET_PLAYER(play)->stateFlags2 & PLAYER_STATE2_DIVING + ) + ) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_OCARINA_OF_TIME); Flags_SetSwitch(play, 3); this->actionFunc = ItemOcarina_StartSoTCutscene; this->actor.draw = NULL; } else { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) { func_8002F434(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); } if ((play->gameplayFrames & 13) == 0) { diff --git a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c index 34defede5..9220c6be4 100644 --- a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c +++ b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c @@ -7,6 +7,7 @@ #include "z_obj_switch.h" #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -249,10 +250,12 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) { subType = (this->dyna.actor.params >> 4 & 7); Flags_SetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); - if (subType == 0 || subType == 4) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); - } else { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (subType == 0 || subType == 4) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + } else { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } } this->cooldownOn = true; @@ -266,7 +269,9 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); if ((this->dyna.actor.params >> 4 & 7) == 1) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } this->cooldownOn = true; } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 7489fa8fa..456955956 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -31,6 +31,7 @@ #include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "soh/Enhancements/randomizer/fishsanity.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #include @@ -6658,7 +6659,14 @@ s32 func_8083E5A8(Player* this, PlayState* play) { uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO; // Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies. - uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || + uint8_t isDropToSkip = + ( + interactedActor->id == ACTOR_EN_ITEM00 && + interactedActor->params != ITEM00_HEART_PIECE && + interactedActor->params != ITEM00_SMALL_KEY && + interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY && + interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI + ) || interactedActor->id == ACTOR_EN_KAREBABA || interactedActor->id == ACTOR_EN_DEKUBABA; @@ -6716,8 +6724,10 @@ s32 func_8083E5A8(Player* this, PlayState* play) { } func_80836898(play, this, func_8083A434); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, &giEntry)) { this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; func_8083AE40(this, giEntry.objectId); + } this->actor.world.pos.x = chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); this->actor.world.pos.z = @@ -10087,7 +10097,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { if ((sp50 == 0) || (sp50 < -1)) { titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart; - if (gSaveContext.showTitleCard) { + if (GameInteractor_Should(GI_VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard, NULL)) { if ((gSaveContext.sceneSetupIndex < 4) && (gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field & ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) && @@ -13393,7 +13403,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { play->msgCtx.msgMode = MSGMODE_TEXT_DONE; } else { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { - if (this->getItemId == GI_GAUNTLETS_SILVER && !IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_NABOORU_CAPTURED_CS, this->getItemId == GI_GAUNTLETS_SILVER, NULL)) { play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.nextCutsceneIndex = 0xFFF1; @@ -13409,11 +13419,13 @@ s32 func_8084DFF4(PlayState* play, Player* this) { this->unk_862 = 0; } + // #region SOH [Randomizer] TODO Better Ice trap handling? if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) { this->unk_862 = 0; gSaveContext.pendingIceTrapCount++; Player_SetPendingFlag(this, play); } + // #endregion this->getItemId = GI_NONE; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; @@ -15675,6 +15687,7 @@ void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80852944(play, this, arg2); } else if (this->unk_850 == 0) { + // This is when link picks up the sword in the Ganon fight Item_Give(play, ITEM_SWORD_MASTER); func_80846720(play, this, 0); } else { From 8a14fea94c07332bcf61a135076d930073e1d2da Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 8 Feb 2024 20:28:02 -0500 Subject: [PATCH 052/300] support LUS archivemanager refactor (#3912) --- OTRExporter | 2 +- libultraship | 2 +- soh/soh/Enhancements/debugger/dlViewer.cpp | 4 +- soh/soh/Enhancements/tts/tts.cpp | 16 +++--- soh/soh/OTRGlobals.cpp | 59 +++++++++++----------- soh/soh/SohMenuBar.cpp | 3 +- soh/soh/resource/importer/SceneFactory.cpp | 2 +- soh/soh/z_message_OTR.cpp | 2 +- 8 files changed, 44 insertions(+), 46 deletions(-) diff --git a/OTRExporter b/OTRExporter index 44adc47b4..d8f3c4dd4 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 44adc47b4da529e72d968b14cab94aefd8260f22 +Subproject commit d8f3c4dd4a46fb46c4f69cd387afadfa711606e9 diff --git a/libultraship b/libultraship index 0833afad6..825bd1275 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 0833afad66e96d2ec4bbc410186d7247dc243ee2 +Subproject commit 825bd1275bc26a8532f07a887db5141cd635df13 diff --git a/soh/soh/Enhancements/debugger/dlViewer.cpp b/soh/soh/Enhancements/debugger/dlViewer.cpp index 9ed250615..da44a908a 100644 --- a/soh/soh/Enhancements/debugger/dlViewer.cpp +++ b/soh/soh/Enhancements/debugger/dlViewer.cpp @@ -66,7 +66,7 @@ std::map cmdMap = { }; void PerformDisplayListSearch() { - auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles("*" + std::string(searchString) + "*DL*"); + auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); std::regex dlSearch(".*((DL)|(DL_.*))$"); @@ -134,7 +134,7 @@ void DLViewerWindow::DrawElement() { try { auto res = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); - if (res->GetInitData()->Type != LUS::ResourceType::DisplayList) { + if (res->GetInitData()->Type != static_cast(LUS::ResourceType::DisplayList)) { ImGui::Text("Resource type is not a Display List. Please choose another."); ImGui::End(); return; diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 0b46cd18f..1ed6eafa5 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -1037,24 +1037,24 @@ void InitTTSBank() { break; } - auto sceneFile = LUS::Context::GetInstance()->GetResourceManager()->LoadFile("accessibility/texts/scenes" + languageSuffix); + auto sceneFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/scenes" + languageSuffix); if (sceneFile != nullptr) { - sceneMap = nlohmann::json::parse(sceneFile->Buffer, nullptr, true, true); + sceneMap = nlohmann::json::parse(*sceneFile->Buffer.get(), nullptr, true, true); } - auto miscFile = LUS::Context::GetInstance()->GetResourceManager()->LoadFile("accessibility/texts/misc" + languageSuffix); + auto miscFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/misc" + languageSuffix); if (miscFile != nullptr) { - miscMap = nlohmann::json::parse(miscFile->Buffer, nullptr, true, true); + miscMap = nlohmann::json::parse(*miscFile->Buffer.get(), nullptr, true, true); } - auto kaleidoFile = LUS::Context::GetInstance()->GetResourceManager()->LoadFile("accessibility/texts/kaleidoscope" + languageSuffix); + auto kaleidoFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/kaleidoscope" + languageSuffix); if (kaleidoFile != nullptr) { - kaleidoMap = nlohmann::json::parse(kaleidoFile->Buffer, nullptr, true, true); + kaleidoMap = nlohmann::json::parse(*kaleidoFile->Buffer.get(), nullptr, true, true); } - auto fileChooseFile = LUS::Context::GetInstance()->GetResourceManager()->LoadFile("accessibility/texts/filechoose" + languageSuffix); + auto fileChooseFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/filechoose" + languageSuffix); if (fileChooseFile != nullptr) { - fileChooseMap = nlohmann::json::parse(fileChooseFile->Buffer, nullptr, true, true); + fileChooseMap = nlohmann::json::parse(*fileChooseFile->Buffer.get(), nullptr, true, true); } } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 283d35e53..62a8bdd3d 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -319,19 +319,19 @@ OTRGlobals::OTRGlobals() { SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_PlayerAnimation, "PlayerAnimation", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Room, "Room", std::make_shared()); // Is room scene? maybe? - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_CollisionHeader, "CollisionHeader", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Skeleton, "Skeleton", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_SkeletonLimb, "SkeletonLimb", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Path, "Path", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Cutscene, "Cutscene", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Text, "Text", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_AudioSample, "AudioSample", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_AudioSoundFont, "AudioSoundFont", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_AudioSequence, "AudioSequence", std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Background, "Background", std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Animation), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_PlayerAnimation), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Room), std::make_shared()); // Is room scene? maybe? + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_CollisionHeader), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Skeleton), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_SkeletonLimb), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Path), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Cutscene), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Text), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSample), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSoundFont), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSequence), std::make_shared()); + context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Background), std::make_shared()); gSaveStateMgr = std::make_shared(); gRandomizer = std::make_shared(); @@ -354,7 +354,7 @@ OTRGlobals::OTRGlobals() { cameraStrings[i] = dup; } - auto versions = context->GetResourceManager()->GetArchive()->GetGameVersions(); + auto versions = context->GetResourceManager()->GetArchiveManager()->GetGameVersions(); for (uint32_t version : versions) { if (!ValidHashes.contains(version)) { @@ -836,7 +836,7 @@ extern "C" RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID) { } extern "C" void OTRExtScanner() { - auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles("*").get(); + auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles().get(); for (auto& rPath : lst) { std::vector raw = StringHelper::Split(rPath, "."); @@ -859,11 +859,11 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { OTRVersion version = {}; // Use a temporary archive instance to load the otr and read the version file - auto archive = std::make_shared(otrPath, "", std::unordered_set(), false); - if (archive->IsMainMPQValid()) { - auto t = archive->LoadFile("portVersion", false); + auto archive = LUS::OtrArchive(otrPath); + if (archive.LoadRaw()) { + auto t = archive.LoadFileRaw("portVersion"); if (t != nullptr && t->IsLoaded) { - auto stream = std::make_shared(t->Buffer.data(), t->Buffer.size()); + auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); auto reader = std::make_shared(stream); LUS::Endianness endianness = (LUS::Endianness)reader->ReadUByte(); reader->SetEndianness(endianness); @@ -871,10 +871,9 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { version.minor = reader->ReadUInt16(); version.patch = reader->ReadUInt16(); } + archive.UnloadRaw(); } - archive = nullptr; - return version; } @@ -1412,15 +1411,15 @@ extern "C" uint16_t OTRGetPixelDepth(float x, float y) { } extern "C" uint32_t ResourceMgr_GetNumGameVersions() { - return LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->GetGameVersions().size(); + return LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions().size(); } extern "C" uint32_t ResourceMgr_GetGameVersion(int index) { - return LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->GetGameVersions()[index]; + return LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; } extern "C" uint32_t ResourceMgr_GetGamePlatform(int index) { - uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->GetGameVersions()[index]; + uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; switch (version) { case OOT_NTSC_US_10: @@ -1443,7 +1442,7 @@ extern "C" uint32_t ResourceMgr_GetGamePlatform(int index) { } extern "C" uint32_t ResourceMgr_GetGameRegion(int index) { - uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->GetGameVersions()[index]; + uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; switch (version) { case OOT_NTSC_US_10: @@ -1529,7 +1528,7 @@ extern "C" void ResourceMgr_UnloadResource(const char* resName) { // OTRTODO: There is probably a more elegant way to go about this... // Kenix: This is definitely leaking memory when it's called. extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) { - auto lst = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles(searchMask); + auto lst = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(searchMask); char** result = (char**)malloc(lst->size() * sizeof(char*)); for (size_t i = 0; i < lst->size(); i++) { @@ -1619,7 +1618,7 @@ extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) { extern "C" uint8_t ResourceMgr_ResourceIsBackground(char* texPath) { auto res = GetResourceByNameHandlingMQ(texPath); - return res->GetInitData()->Type == LUS::ResourceType::SOH_Background; + return res->GetInitData()->Type == static_cast(LUS::ResourceType::SOH_Background); } extern "C" char* ResourceMgr_LoadJPEG(char* data, size_t dataSize) @@ -1667,9 +1666,9 @@ extern "C" uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); extern "C" char* ResourceMgr_LoadTexOrDListByName(const char* filePath) { auto res = GetResourceByNameHandlingMQ(filePath); - if (res->GetInitData()->Type == LUS::ResourceType::DisplayList) + if (res->GetInitData()->Type == static_cast(LUS::ResourceType::DisplayList)) return (char*)&((std::static_pointer_cast(res))->Instructions[0]); - else if (res->GetInitData()->Type == LUS::ResourceType::Array) + else if (res->GetInitData()->Type == static_cast(LUS::ResourceType::Array)) return (char*)(std::static_pointer_cast(res))->Vertices.data(); else { return (char*)GetResourceDataByNameHandlingMQ(filePath); @@ -1679,7 +1678,7 @@ extern "C" char* ResourceMgr_LoadTexOrDListByName(const char* filePath) { extern "C" char* ResourceMgr_LoadIfDListByName(const char* filePath) { auto res = GetResourceByNameHandlingMQ(filePath); - if (res->GetInitData()->Type == LUS::ResourceType::DisplayList) + if (res->GetInitData()->Type == static_cast(LUS::ResourceType::DisplayList)) return (char*)&((std::static_pointer_cast(res))->Instructions[0]); return nullptr; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f59e3a343..f8dc26ad4 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -201,8 +201,7 @@ void DrawSettingsMenu() { static std::unordered_map audioBackendNames = { { LUS::AudioBackend::WASAPI, "Windows Audio Session API" }, - { LUS::AudioBackend::PULSE, "PulseAudio" }, - { LUS::AudioBackend::SDL, "SDL" }, + { LUS::AudioBackend::SDL, "SDL" } }; ImGui::Text("Audio API (Needs reload)"); diff --git a/soh/soh/resource/importer/SceneFactory.cpp b/soh/soh/resource/importer/SceneFactory.cpp index 01066ffc1..b71f78a2c 100644 --- a/soh/soh/resource/importer/SceneFactory.cpp +++ b/soh/soh/resource/importer/SceneFactory.cpp @@ -109,7 +109,7 @@ std::shared_ptr SceneFactoryV0::ParseSceneCommand(std::shared_ptr if (commandFactory != nullptr) { auto initData = std::make_shared(); initData->Id = scene->GetInitData()->Id; - initData->Type = ResourceType::SOH_SceneCommand; + initData->Type = static_cast(ResourceType::SOH_SceneCommand); initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index); initData->ResourceVersion = scene->GetInitData()->ResourceVersion; result = std::static_pointer_cast(commandFactory->ReadResource(initData, reader)); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index a4255d08a..ce594879a 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -23,7 +23,7 @@ static void SetMessageEntry(MessageTableEntry& entry, const LUS::MessageEntry& m } static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEntry*& table, size_t tableSize) { - auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles(folderPath).get(); + auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(folderPath).get(); for (auto& tPath : lst) { auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); From bea3c6dae04b92b0c10991ccaf387051adec396b Mon Sep 17 00:00:00 2001 From: Taw Date: Fri, 9 Feb 2024 14:17:17 -0800 Subject: [PATCH 053/300] GameInteractor hooks for adult and child shooting gallery --- .../game-interactor/GameInteractor.h | 6 +++ .../Enhancements/randomizer/hook_handlers.cpp | 21 ++++++++++ .../Enhancements/randomizer/location_list.cpp | 4 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 39 +++++-------------- .../ovl_En_Syateki_Man/z_en_syateki_man.h | 1 - 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index c6fb7c721..bffed5458 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -203,6 +203,9 @@ typedef enum { GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, // Opt: *EnGo2 GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, + // Opt: *EnSyatekiMan + // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) + GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, /*** Play Cutscenes ***/ @@ -269,6 +272,9 @@ typedef enum { // Opt: *EnFr GI_VB_GIVE_ITEM_FROM_FROGS, + // Opt: *EnSyatekiMan + GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, + GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, GI_VB_GIVE_ITEM_LIGHT_ARROW, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index bf236a3ba..6e9a6809a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -23,6 +23,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Go2/z_en_go2.h" #include "src/overlays/actors/ovl_En_Ms/z_en_ms.h" #include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" +#include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -775,6 +776,26 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should &= !EnDs_RandoCanGetGrannyItem(); break; } + case GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY: { + EnSyatekiMan* enSyatekiMan = static_cast(optionalArg); + enSyatekiMan->getItemId = GI_RUPEE_PURPLE; + if (LINK_IS_ADULT) { + // Give purple rupee if we've already obtained the reward OR we don't have a bow + *should = Flags_GetItemGetInf(ITEMGETINF_0E) || CUR_UPG_VALUE(UPG_QUIVER) == 0; + } else { + // Give purple rupee if we've already obtained the reward + *should = Flags_GetItemGetInf(ITEMGETINF_0D); + } + break; + } + case GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD: { + *should = CUR_UPG_VALUE(UPG_QUIVER) > 0; + if (!*should) { + // In Rando without a quiver, display a message reminding the player to come back with a bow + Message_StartTextbox(gPlayState, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); + } + break; + } case GI_VB_TRADE_CLAIM_CHECK: case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 28ca3b85a..67b2b35ed 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -672,7 +672,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(13), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); @@ -692,7 +692,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0E), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 6ab91ddc0..d84298800 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -4,6 +4,7 @@ #include "objects/object_ossan/object_ossan.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_LOCKON) @@ -180,7 +181,6 @@ void EnSyatekiMan_Init(Actor* thisx, PlayState* play) { this->blinkFunc = EnSyatekiMan_BlinkWait; this->actor.colChkInfo.cylRadius = 100; this->actionFunc = EnSyatekiMan_Start; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } void EnSyatekiMan_Destroy(Actor* thisx, PlayState* play) { @@ -355,11 +355,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->tempGallery = this->actor.parent; this->actor.parent = NULL; if (!LINK_IS_ADULT) { - if(IS_RANDO && !Flags_GetTreasure(play, 0x1E)) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_SHOOTING_GALLERY_REWARD, GI_BULLET_BAG_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1E); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0D)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0D)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Pachinko ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_BULLET_BAG)); if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { @@ -368,16 +364,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->getItemId = GI_BULLET_BAG_50; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } else { // Only give the adult rando reward when the player has a quiver - if (IS_RANDO && !Flags_GetTreasure(play, 0x1F) && CUR_UPG_VALUE(UPG_QUIVER) > 0) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1F); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0E)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0E)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Bow ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_QUIVER)); switch (CUR_UPG_VALUE(UPG_QUIVER)) { @@ -392,14 +383,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { break; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } this->actionFunc = EnSyatekiMan_GivePrize; break; @@ -426,33 +414,26 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { } } } -} +} void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { this->actionFunc = EnSyatekiMan_FinishPrize; - } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); - } + } else { + func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } void EnSyatekiMan_FinishPrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (!LINK_IS_ADULT) { Flags_SetItemGetInf(ITEMGETINF_0D); - } else if ((this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)) { + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50), this)) { Flags_SetItemGetInf(ITEMGETINF_0E); - } else if (IS_RANDO && LINK_IS_ADULT && CUR_UPG_VALUE(UPG_QUIVER) == 0) { - // In Rando without a quiver, display a message reminding the player to come back with a bow - Message_StartTextbox(play, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); } this->gameResult = SYATEKI_RESULT_NONE; this->actor.parent = this->tempGallery; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h index eaeec0429..b65364ae4 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h @@ -28,7 +28,6 @@ typedef struct EnSyatekiMan { /* 0x0220 */ Actor* tempGallery; /* 0x0224 */ EnSyatekiManOtherFunc blinkFunc; // Seems to be part of a blink system with unk_20C and unk_20E, but it's unused. /* 0x0228 */ s16 csCam; - /* */ GetItemEntry getItemEntry; } EnSyatekiMan; // size = 0x022C #endif From 4e5b92fdf385e34da94049071233dbe9c872cbca Mon Sep 17 00:00:00 2001 From: Taw Date: Sat, 10 Feb 2024 09:06:34 -0800 Subject: [PATCH 054/300] Man On Roof --- .../Enhancements/game-interactor/GameInteractor.h | 1 + soh/soh/Enhancements/randomizer/hook_handlers.cpp | 1 + soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c | 13 ++++--------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index c6fb7c721..e615e5954 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -268,6 +268,7 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, // Opt: *EnFr GI_VB_GIVE_ITEM_FROM_FROGS, + GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index bf236a3ba..6b29ac567 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -782,6 +782,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: + case GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF: case GI_VB_GIVE_ITEM_SKULL_TOKEN: case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: case GI_VB_GIVE_ITEM_FAIRY_OCARINA: diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 15ebd759c..5093d47d2 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -6,6 +6,7 @@ #include "z_en_ani.h" #include "objects/object_ani/object_ani.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -119,7 +120,7 @@ void func_809B0524(EnAni* this, PlayState* play) { } void func_809B0558(EnAni* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { this->actor.parent = NULL; if (!LINK_IS_ADULT) { EnAni_SetupAction(this, func_809B04F0); @@ -128,11 +129,8 @@ void func_809B0558(EnAni* this, PlayState* play) { } Flags_SetItemGetInf(ITEMGETINF_15); } else { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f); } } } @@ -142,11 +140,8 @@ void func_809B05F0(EnAni* this, PlayState* play) { EnAni_SetupAction(this, func_809B0558); } - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f); } } From ceb5b740b5af02862b778591b3bfe852c8a992f5 Mon Sep 17 00:00:00 2001 From: Taw Date: Mon, 12 Feb 2024 14:26:10 -0800 Subject: [PATCH 055/300] fix include --- soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 5093d47d2..3fe4e2a22 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -6,7 +6,7 @@ #include "z_en_ani.h" #include "objects/object_ani/object_ani.h" -#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) From c1eb0a897019993f16b9f0603b51b136a1ea7bcc Mon Sep 17 00:00:00 2001 From: Archez Date: Tue, 13 Feb 2024 20:55:33 -0500 Subject: [PATCH 056/300] Bump latest LUS and Fix ship menu bar icon (#3935) * fix ship menu bar icon * update cmake in wiiu/switch * different cmake install * wrong arch --- .github/workflows/generate-builds.yml | 6 ++++++ libultraship | 2 +- soh/soh/SohMenuBar.cpp | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 6f7134282..582022dbd 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -221,6 +221,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y ninja-build + sudo apt-get remove -y cmake + wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh + sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir - name: Fix dubious ownership error if: ${{ vars.LINUX_RUNNER }} run: git config --global --add safe.directory '*' @@ -264,6 +267,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y ninja-build + sudo apt-get remove -y cmake + wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh + sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir - uses: actions/checkout@v3 with: submodules: true diff --git a/libultraship b/libultraship index 825bd1275..d5a39635a 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 825bd1275bc26a8532f07a887db5141cd635df13 +Subproject commit d5a39635a118f814613c0fdd1601f80c809a742d diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f8dc26ad4..858c12da7 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -111,11 +111,11 @@ namespace SohGui { void DrawMenuBarIcon() { static bool gameIconLoaded = false; if (!gameIconLoaded) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTexture("Game_Icon", "textures/icons/gIcon.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Game_Icon", "textures/icons/gIcon.png"); gameIconLoaded = true; } - if (LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon")) { + if (LUS::Context::GetInstance()->GetWindow()->GetGui()->HasTextureByName("Game_Icon")) { #ifdef __SWITCH__ ImVec2 iconSize = ImVec2(20.0f, 20.0f); float posScale = 1.0f; From 3187564f5b4120e159f5e506b4a3db88716b56aa Mon Sep 17 00:00:00 2001 From: mckinlee Date: Thu, 15 Feb 2024 20:13:54 -0500 Subject: [PATCH 057/300] Pause Warp Enhancement (#3223) * Pause Warp Enhancement This commit introduces the PauseWarp mod, a feature that allows players to warp to different locations in the game directly from the pause menu. - Add PauseWarpState structure to manage flags and cooldowns for the pause warp feature. - Implement IsStateValid function for state validation. - Implement ResetStateFlags function to reset all state flags to default values. - Add InitiateWarp function to handle the initiation of warp sequences. - Implement HandleWarpConfirmation function to confirm and execute warp actions. - Implement HandleCooldowns function to manage various cooldown timers. - Add PauseWarp_Main function as the main logic, called every frame to handle pause warp functionality. - Map warp song messages to in-game text messages. * Warp Song Check -Now if you do not have a warp song you won't be able to select the empty slot and still teleport. * Added Audio Fanfares and Changed stateFlag1 to PLAYER_STATE1_IN_CUTSCENE -When selecting a warp song the audio for the applicable warp song will now play for a extra vanilla feel. -Changed the stateFlag1 because previously it just disabled input allowing enemies to harm you. Now that won't happen because the game is put into a cutscene state. * Feedback Update -A new hook was created 'OnPauseMenu' so now PauseWarp_Main is only called when the pause menu is open -Moved pauswarp.c to the Enhancements folder -Removed from graph.c PR Change: Changing to the main branch instead of sulu * Feedback Update #2 -Introduced new function 'PauseWarp_Idle' now that 'PauseWarp_Main' is no longer called every frame -Added C wrapper to access 'GameInteractor::IsSaveLoaded' and scrapped the 'IsStateValid' function -Added 'PauseWarp_Idle' to the the 'RegisterPauseWarp' function -Refactored the code some * Linux Compile Issue -Added a missing header that was causing a compile issue for linux -Hopefully, it won't crash * Minor Bug Fix -Now link won't get soft locked when warping to the same location twice * Update libultraship * Revert "Update libultraship" This reverts commit 746fc234795c06261a4fb69484f4656676f1eaaa. * Bug Fix -Added more checks to ensure vanilla behavior when a Ocarina is not in the players inventory. * WIP * Done unless I'm missing headers * now we done * clean up, these arn't needed anymore * Rename OnPauseMenu to OnKaleidoUpdate --- soh/include/functions.h | 4 + .../game-interactor/GameInteractor.h | 1 + .../game-interactor/GameInteractor_Hooks.cpp | 6 ++ .../game-interactor/GameInteractor_Hooks.h | 3 + soh/soh/Enhancements/mods.cpp | 18 ++++ soh/soh/Enhancements/pausewarp.c | 92 +++++++++++++++++++ soh/soh/SohMenuBar.cpp | 2 + soh/src/code/z_kaleido_scope_call.c | 3 + 8 files changed, 129 insertions(+) create mode 100644 soh/soh/Enhancements/pausewarp.c diff --git a/soh/include/functions.h b/soh/include/functions.h index 3898ea63d..2c4fe9b15 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2467,6 +2467,10 @@ void Message_DrawText(PlayState* play, Gfx** gfxP); void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH); void Interface_RandoRestoreSwordless(void); +//Pause Warp +void PauseWarp_HandleSelection(); +void PauseWarp_Execute(); + // #endregion #ifdef __cplusplus diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index be27e74a2..3e70da37a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -221,6 +221,7 @@ public: DEFINE_HOOK(OnFileDropped, void(std::string filePath)); DEFINE_HOOK(OnAssetAltChange, void()); + DEFINE_HOOK(OnKaleidoUpdate, void()); // Helpers static bool IsSaveLoaded(); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 4bd5354a6..911c47a71 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -187,3 +187,9 @@ void GameInteractor_ExecuteOnSetGameLanguage() { void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) { GameInteractor::Instance->RegisterGameHook(fn); } + +//MARK: Pause Menu + +void GameInteractor_ExecuteOnKaleidoUpdate() { + GameInteractor::Instance->ExecuteHooks(); +} diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 7b7b226fa..5c86cb39b 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -60,6 +60,9 @@ void GameInteractor_ExecuteOnSetGameLanguage(); // MARK: - System void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); +//Mark: - Pause Menu +void GameInteractor_ExecuteOnKaleidoUpdate(); + #ifdef __cplusplus } #endif diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index f829d767f..8b65cdcbe 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1304,6 +1304,23 @@ void RegisterToTMedallions() { }); } +void RegisterPauseMenuHooks() { + static bool pauseWarpHooksRegistered = false; + GameInteractor::Instance->RegisterGameHook([&]() { + if (!GameInteractor::IsSaveLoaded() || !CVarGetInteger("gPauseWarp", 0)) { + pauseWarpHooksRegistered = false; + return; + } + if (!pauseWarpHooksRegistered) { + GameInteractor::Instance->RegisterGameHook([]() {PauseWarp_HandleSelection();}); + GameInteractor::Instance->RegisterGameHook([]() { + PauseWarp_Execute(); + }); + pauseWarpHooksRegistered = true; + } + }); +} + void InitMods() { RegisterTTS(); RegisterInfiniteMoney(); @@ -1340,4 +1357,5 @@ void InitMods() { NameTag_RegisterHooks(); RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); + RegisterPauseMenuHooks(); } diff --git a/soh/soh/Enhancements/pausewarp.c b/soh/soh/Enhancements/pausewarp.c new file mode 100644 index 000000000..e0fd97e24 --- /dev/null +++ b/soh/soh/Enhancements/pausewarp.c @@ -0,0 +1,92 @@ +#include "custom-message/CustomMessageTypes.h" +#include "global.h" +#include "z64.h" +#include "game-interactor/GameInteractor.h" + +static const int songMessageMap[] = { + TEXT_WARP_MINUET_OF_FOREST, + TEXT_WARP_BOLERO_OF_FIRE, + TEXT_WARP_SERENADE_OF_WATER, + TEXT_WARP_REQUIEM_OF_SPIRIT, + TEXT_WARP_NOCTURNE_OF_SHADOW, + TEXT_WARP_PRELUDE_OF_LIGHT +}; + +static const int ocarinaSongMap[] = { + OCARINA_SONG_MINUET, + OCARINA_SONG_BOLERO, + OCARINA_SONG_SERENADE, + OCARINA_SONG_REQUIEM, + OCARINA_SONG_NOCTURNE, + OCARINA_SONG_PRELUDE +}; + +static const int entranceIndexMap[] = { + ENTR_SACRED_FOREST_MEADOW_2, // Minuet + ENTR_DEATH_MOUNTAIN_CRATER_4, // Bolero + ENTR_LAKE_HYLIA_8, // Serenade + ENTR_DESERT_COLOSSUS_5, // Requiem + ENTR_GRAVEYARD_7, // Nocturne + ENTR_TEMPLE_OF_TIME_7 // Prelude +}; + +static const int songAudioMap[] = { + NA_BGM_OCA_MINUET, + NA_BGM_OCA_BOLERO, + NA_BGM_OCA_SERENADE, + NA_BGM_OCA_REQUIEM, + NA_BGM_OCA_NOCTURNE, + NA_BGM_OCA_LIGHT +}; + +static bool isWarpActive = false; + +void PauseWarp_Execute() { + if (!isWarpActive || gPlayState->msgCtx.msgMode != MSGMODE_NONE) { + return; + } + isWarpActive = false; + GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; + if (gPlayState->msgCtx.choiceIndex != 0) { + return; + } + if (IS_RANDO) { + Entrance_SetWarpSongEntrance(); + return; + } + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gPlayState->transitionType = TRANS_TYPE_FADE_WHITE_FAST; + for (int i = 0; i < ARRAY_COUNT(ocarinaSongMap); i++) { + if (gPlayState->msgCtx.lastPlayedSong == ocarinaSongMap[i]) { + gPlayState->nextEntranceIndex = entranceIndexMap[i]; + return; + } + } + gPlayState->transitionTrigger = TRANS_TRIGGER_OFF; +} + +void ActivateWarp(PauseContext* pauseCtx, int song) { + Audio_OcaSetInstrument(0); + Interface_SetDoAction(gPlayState, DO_ACTION_NONE); + pauseCtx->state = 0x12; + WREG(2) = -6240; + func_800F64E0(0); + pauseCtx->unk_1E4 = 0; + int idx = song - QUEST_SONG_MINUET; + gPlayState->msgCtx.lastPlayedSong = ocarinaSongMap[idx]; + Audio_SetSoundBanksMute(0x20); + Audio_PlayFanfare(songAudioMap[idx]); + Message_StartTextbox(gPlayState, songMessageMap[idx], NULL); + GET_PLAYER(gPlayState)->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; + isWarpActive = true; +} + +void PauseWarp_HandleSelection() { + if (gSaveContext.inventory.items[SLOT_OCARINA] != ITEM_NONE) { + int aButtonPressed = CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_A); + int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST]; + if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE) { + ActivateWarp(&gPlayState->pauseCtx, song); + } + } +} diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 858c12da7..c2a300877 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -644,6 +644,8 @@ void DrawEnhancementsMenu() { "- Obtained the Master Sword\n" "- Not within range of Time Block\n" "- Not within range of Ocarina playing spots"); + UIWidgets::PaddedEnhancementCheckbox("Pause Warp", "gPauseWarp", true, false); + UIWidgets::Tooltip("Selection of warp song in pause menu initiates warp. Disables song playback."); ImGui::EndTable(); ImGui::EndMenu(); diff --git a/soh/src/code/z_kaleido_scope_call.c b/soh/src/code/z_kaleido_scope_call.c index dd7e3fdd9..82922acd0 100644 --- a/soh/src/code/z_kaleido_scope_call.c +++ b/soh/src/code/z_kaleido_scope_call.c @@ -1,5 +1,6 @@ #include "global.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" void (*sKaleidoScopeUpdateFunc)(PlayState* play); void (*sKaleidoScopeDrawFunc)(PlayState* play); @@ -56,6 +57,8 @@ void KaleidoScopeCall_Update(PlayState* play) { KaleidoMgrOverlay* kaleidoScopeOvl = &gKaleidoMgrOverlayTable[KALEIDO_OVL_KALEIDO_SCOPE]; PauseContext* pauseCtx = &play->pauseCtx; + GameInteractor_ExecuteOnKaleidoUpdate(); + if (!gSaveContext.sohStats.gameComplete && (!IS_BOSS_RUSH || !gSaveContext.isBossRushPaused)) { gSaveContext.sohStats.pauseTimer++; From 13fce8258d92e80ea09900f83d338ccba2e7b1f9 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 15 Feb 2024 20:14:24 -0500 Subject: [PATCH 058/300] [Rando] Add Mix and Decouple support to Boss Entrances (#3261) * initial support for mixing boss entrances in the mixed pool * support decouple for boss entrances * missed decouple change * add blue warp exits to boss rooms in location access * add entrance get helper methods * fix assumed targets not using root in entrance name * add dedicated blue warp entrances and handle blue warp changes during generation * change bluewarp handling in game to use unique blue warp entrances * handle blue warps in entrance tracker * fix overriding all jabu and water temple rooms * fix grotto returns when exiting boss rooms/dungeons * fix blue warp logic by tracking original connected region key * use entrance enums * remove unneeded entrance values * fix decouple generation crash * fix jabu mq backwards logic --- .../randomizer/3drando/entrance.cpp | 172 ++++++++++++--- .../randomizer/3drando/entrance.hpp | 22 +- .../Enhancements/randomizer/3drando/fill.cpp | 7 +- .../randomizer/3drando/location_access.cpp | 13 ++ .../randomizer/3drando/location_access.hpp | 1 + .../location_access/locacc_deku_tree.cpp | 1 + .../locacc_dodongos_cavern.cpp | 1 + .../location_access/locacc_fire_temple.cpp | 1 + .../location_access/locacc_forest_temple.cpp | 1 + .../locacc_jabujabus_belly.cpp | 15 +- .../location_access/locacc_shadow_temple.cpp | 1 + .../location_access/locacc_spirit_temple.cpp | 1 + .../location_access/locacc_water_temple.cpp | 1 + .../randomizer/3drando/settings.cpp | 14 ++ .../randomizer/3drando/settings.hpp | 2 + .../randomizer/3drando/spoiler_log.cpp | 17 +- .../Enhancements/randomizer/randomizer.cpp | 21 +- .../Enhancements/randomizer/randomizerTypes.h | 1 + .../randomizer/randomizer_entrance.c | 200 ++++++++---------- .../randomizer/randomizer_entrance.h | 18 +- .../randomizer_entrance_tracker.cpp | 13 ++ soh/soh/SaveManager.cpp | 4 +- soh/src/code/z_room.c | 13 +- .../actors/ovl_player_actor/z_player.c | 4 +- 24 files changed, 349 insertions(+), 195 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp index 5df67bb87..8dd8b4c63 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp @@ -26,7 +26,6 @@ typedef struct { AreaKey parentRegion; AreaKey connectedRegion; int16_t index; - int16_t blueWarp; } EntranceLinkInfo; EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, NONE, NONE, -1}; @@ -40,6 +39,11 @@ using EntranceInfoPair = std::pair; using EntrancePair = std::pair; using EntrancePools = std::map>; +// Construct entrance name from parent and connected region keys +std::string EntranceNameByRegions(uint32_t parentRegion, uint32_t connectedRegion) { + return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName; +} + //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 @@ -77,26 +81,22 @@ void SetAllEntrancesData(std::vector& entranceShuffleTable) { //set data Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion); forwardEntrance->SetIndex(forwardEntry.index); - forwardEntrance->SetBlueWarp(forwardEntry.blueWarp); forwardEntrance->SetType(forwardEntry.type); forwardEntrance->SetAsPrimary(); - // When decouple entrances is on, mark it for entrances except boss rooms - if (Settings::DecoupleEntrances && forwardEntry.type != EntranceType::ChildBoss && - forwardEntry.type != EntranceType::AdultBoss) { + // When decouple entrances is on, mark the forward entrance + if (Settings::DecoupleEntrances) { forwardEntrance->SetDecoupled(); } 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); // Mark reverse entrance as decoupled - if (Settings::DecoupleEntrances && returnEntry.type != EntranceType::ChildBoss && - returnEntry.type != EntranceType::AdultBoss) { + if (Settings::DecoupleEntrances) { returnEntrance->SetDecoupled(); } } @@ -687,31 +687,31 @@ int ShuffleAllEntrances() { curNumRandomizedEntrances = 0; std::vector entranceShuffleTable = { - //Parent Region Connected Region index blue warp + //Parent Region Connected Region index {{EntranceType::Dungeon, KF_OUTSIDE_DEKU_TREE, DEKU_TREE_ENTRYWAY, 0x0000}, - {EntranceType::Dungeon, DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457}}, + {EntranceType::Dungeon, DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE, 0x0209}}, {{EntranceType::Dungeon, DEATH_MOUNTAIN_TRAIL, DODONGOS_CAVERN_ENTRYWAY, 0x0004}, - {EntranceType::Dungeon, DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A}}, + {EntranceType::Dungeon, DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL, 0x0242}}, {{EntranceType::Dungeon, ZORAS_FOUNTAIN, JABU_JABUS_BELLY_ENTRYWAY, 0x0028}, - {EntranceType::Dungeon, JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN, 0x0221, 0x010E}}, + {EntranceType::Dungeon, JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN, 0x0221}}, {{EntranceType::Dungeon, SACRED_FOREST_MEADOW, FOREST_TEMPLE_ENTRYWAY, 0x0169}, - {EntranceType::Dungeon, FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW, 0x0215, 0x0608}}, + {EntranceType::Dungeon, FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW, 0x0215}}, {{EntranceType::Dungeon, DMC_CENTRAL_LOCAL, FIRE_TEMPLE_ENTRYWAY, 0x0165}, - {EntranceType::Dungeon, FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL, 0x024A, 0x0564}}, + {EntranceType::Dungeon, FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL, 0x024A}}, {{EntranceType::Dungeon, LAKE_HYLIA, WATER_TEMPLE_ENTRYWAY, 0x0010}, - {EntranceType::Dungeon, WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA, 0x021D, 0x060C}}, + {EntranceType::Dungeon, WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA, 0x021D}}, {{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082}, - {EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610}}, + {EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1}}, {{EntranceType::Dungeon, GRAVEYARD_WARP_PAD_REGION, SHADOW_TEMPLE_ENTRYWAY, 0x0037}, - {EntranceType::Dungeon, SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580}}, + {EntranceType::Dungeon, SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION, 0x0205}}, {{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098}, {EntranceType::Dungeon, BOTTOM_OF_THE_WELL_ENTRYWAY, KAKARIKO_VILLAGE, 0x02A6}}, {{EntranceType::Dungeon, ZORAS_FOUNTAIN, ICE_CAVERN_ENTRYWAY, 0x0088}, {EntranceType::Dungeon, ICE_CAVERN_ENTRYWAY, ZORAS_FOUNTAIN, 0x03D4}}, {{EntranceType::Dungeon, GERUDO_FORTRESS, GERUDO_TRAINING_GROUNDS_ENTRYWAY, 0x0008}, {EntranceType::Dungeon, GERUDO_TRAINING_GROUNDS_ENTRYWAY, GERUDO_FORTRESS, 0x03A8}}, - {{EntranceType::GanonDungeon, GANONS_CASTLE_LEDGE, GANONS_CASTLE_ENTRYWAY, 0x0467}, - {EntranceType::GanonDungeon, GANONS_CASTLE_ENTRYWAY, CASTLE_GROUNDS_FROM_GANONS_CASTLE, 0x023D}}, + {{EntranceType::GanonDungeon, GANONS_CASTLE_LEDGE, GANONS_CASTLE_ENTRYWAY, 0x0467}, + {EntranceType::GanonDungeon, GANONS_CASTLE_ENTRYWAY, CASTLE_GROUNDS_FROM_GANONS_CASTLE, 0x023D}}, {{EntranceType::Interior, KOKIRI_FOREST, KF_MIDOS_HOUSE, 0x0433}, {EntranceType::Interior, KF_MIDOS_HOUSE, KOKIRI_FOREST, 0x0443}}, @@ -947,21 +947,30 @@ int ShuffleAllEntrances() { {{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE}, {{EntranceType::ChildBoss, DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, 0x040F}, - {EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457}}, + {EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252}}, {{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, 0x040B}, - {EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A}}, + {EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5}}, {{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, 0x0301}, - {EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E}}, + {EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407}}, {{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, 0x000C}, - {EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608}}, + {EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E}}, {{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ENTRYWAY, FIRE_TEMPLE_BOSS_ROOM, 0x0305}, - {EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564}}, + {EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175}}, {{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, 0x0417}, - {EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C}}, + {EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423}}, {{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ENTRYWAY, SPIRIT_TEMPLE_BOSS_ROOM, 0x008D}, - {EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610}}, + {EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5}}, {{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ENTRYWAY, SHADOW_TEMPLE_BOSS_ROOM, 0x0413}, - {EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580}}, + {EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2}}, + + {{EntranceType::BlueWarp, DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE, 0x0457}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL, 0x047A}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN, 0x010E}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW, 0x0608}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL, 0x0564}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA, 0x060C}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS, 0x0610}, NO_RETURN_ENTRANCE}, + {{EntranceType::BlueWarp, SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION, 0x0580}, NO_RETURN_ENTRANCE}, }; std::map priorityEntranceTable = { @@ -1011,6 +1020,11 @@ int ShuffleAllEntrances() { FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY && entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;}); } + if (Settings::DecoupleEntrances) { + for (Entrance* entrance : entrancePools[EntranceType::Boss]) { + entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse()); + } + } } else { entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); @@ -1019,6 +1033,14 @@ int ShuffleAllEntrances() { FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY && entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;}); } + if (Settings::DecoupleEntrances) { + for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) { + entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse()); + } + for (Entrance* entrance : entrancePools[EntranceType::AdultBoss]) { + entrancePools[EntranceType::AdultBossReverse].push_back(entrance->GetReverse()); + } + } } } @@ -1082,10 +1104,13 @@ int ShuffleAllEntrances() { SetShuffledEntrances(oneWayEntrancePools); //combine entrance pools if mixing pools. Only continue if more than one pool is selected. - int totalMixedPools = (Settings::MixDungeons ? 1 : 0) + (Settings::MixOverworld ? 1 : 0) + (Settings::MixInteriors ? 1 : 0) + (Settings::MixGrottos ? 1 : 0); + int totalMixedPools = (Settings::MixDungeons ? 1 : 0) + (Settings::MixBosses ? 1 : 0) + + (Settings::MixOverworld ? 1 : 0) + (Settings::MixInteriors ? 1 : 0) + + (Settings::MixGrottos ? 1 : 0); if (totalMixedPools < 2) { Settings::MixedEntrancePools.SetSelectedIndex(OFF); Settings::MixDungeons.SetSelectedIndex(OFF); + Settings::MixBosses.SetSelectedIndex(OFF); Settings::MixOverworld.SetSelectedIndex(OFF); Settings::MixInteriors.SetSelectedIndex(OFF); Settings::MixGrottos.SetSelectedIndex(OFF); @@ -1099,6 +1124,12 @@ int ShuffleAllEntrances() { poolsToMix.insert(EntranceType::DungeonReverse); } } + if (Settings::MixBosses) { + poolsToMix.insert(EntranceType::Boss); + if (Settings::DecoupleEntrances) { + poolsToMix.insert(EntranceType::BossReverse); + } + } if (Settings::MixOverworld) { poolsToMix.insert(EntranceType::Overworld); } @@ -1232,6 +1263,87 @@ int ShuffleAllEntrances() { } } + // Determine blue warp targets + if (true /* Settings.BlueWarps.Is(BLUEWARPS_DUNGEON) */) { // RANDOTODO: add bluewarp shuffle + // If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance + std::map bossExits = { + { EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE)) }, + { EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL)) }, + { EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN)) }, + { EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW)) }, + { EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL)) }, + { EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA)) }, + { EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY)) }, + { EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION)) }, + }; + + // If a boss room is inside a dungeon entrance (or inside a dungeon which is inside a dungeon entrance), make the blue warp go to that dungeon's blue warp target + std::map dungeonExits = { + { EntranceNameByRegions(DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE), + GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE)) }, + { EntranceNameByRegions(DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL), + GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL)) }, + { EntranceNameByRegions(JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN), + GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN)) }, + { EntranceNameByRegions(FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW), + GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW)) }, + { EntranceNameByRegions(FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL), + GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL)) }, + { EntranceNameByRegions(WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA), + GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA)) }, + { EntranceNameByRegions(SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY), + GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS)) }, + { EntranceNameByRegions(SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION), + GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION)) }, + }; + + // Pair + std::vector bossRoomExitPairs = { + { GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE)), + GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL)), + GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN)), + GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW)), + GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL)), + GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA)), + GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS)), + GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION)), + GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY)) }, + }; + + for (EntrancePair pair : bossRoomExitPairs) { + Entrance* target = pair.second->GetReplacement() != nullptr ? pair.second->GetReplacement() : pair.second; + + if (!Settings::DecoupleEntrances) { + while (bossExits.find(target->GetName()) != bossExits.end()) { + Entrance* next = bossExits.at(target->GetName()); + target = next->GetReplacement() != nullptr ? next->GetReplacement() : next; + } + + if (dungeonExits.find(target->GetName()) != dungeonExits.end()) { + target = dungeonExits.at(target->GetName()); + } + } + + pair.first->Connect(target->GetOriginalConnectedRegionKey()); + pair.first->SetReplacement(target); + } + } + // Validate the world one last time to ensure all special conditions are still valid if (!ValidateWorld(nullptr)) { return ENTRANCE_SHUFFLE_FAILURE; @@ -1259,8 +1371,8 @@ void CreateEntranceOverrides() { auto message = "Setting " + entrance->to_string() + "\n"; SPDLOG_DEBUG(message); + uint8_t type = (uint8_t)entrance->GetType(); int16_t originalIndex = entrance->GetIndex(); - int16_t originalBlueWarp = entrance->GetBlueWarp(); int16_t replacementIndex = entrance->GetReplacement()->GetIndex(); int16_t destinationIndex = -1; @@ -1274,9 +1386,9 @@ void CreateEntranceOverrides() { } entranceOverrides.push_back({ + .type = type, .index = originalIndex, .destination = destinationIndex, - .blueWarp = originalBlueWarp, .override = replacementIndex, .overrideDestination = replacementDestinationIndex, }); diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp b/soh/soh/Enhancements/randomizer/3drando/entrance.hpp index b6a5cb432..e99b418d8 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.hpp @@ -18,12 +18,16 @@ enum class EntranceType { OwlDrop, Spawn, WarpSong, + BlueWarp, Dungeon, GanonDungeon, DungeonReverse, Boss, + BossReverse, ChildBoss, + ChildBossReverse, AdultBoss, + AdultBossReverse, Interior, InteriorReverse, SpecialInterior, @@ -40,6 +44,7 @@ public: Entrance(uint32_t connectedRegion_, std::vector conditions_met_) : connectedRegion(connectedRegion_) { + originalConnectedRegion = connectedRegion_; conditions_met.resize(2); for (size_t i = 0; i < conditions_met_.size(); i++) { conditions_met[i] = conditions_met_[i]; @@ -134,6 +139,10 @@ public: return connectedRegion; } + uint32_t GetOriginalConnectedRegionKey() const { + return originalConnectedRegion; + } + Area* GetConnectedRegion() const { return AreaTable(connectedRegion); } @@ -198,14 +207,6 @@ public: index = newIndex; } - int16_t GetBlueWarp() const { - return blueWarp; - } - - void SetBlueWarp(int16_t newBlueWarp) { - blueWarp = newBlueWarp; - } - Entrance* GetAssumed() const { return assumed; } @@ -251,7 +252,7 @@ public: AreaTable(ROOT)->AddExit(ROOT, connectedRegion, []{return true;}); Entrance* targetEntrance = AreaTable(ROOT)->GetExit(connectedRegion); targetEntrance->SetReplacement(this); - targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName); + targetEntrance->SetName(AreaTable(ROOT)->regionName + " -> " + GetConnectedRegion()->regionName); return targetEntrance; } @@ -266,6 +267,7 @@ public: private: uint32_t parentRegion; uint32_t connectedRegion; + uint32_t originalConnectedRegion; std::vector conditions_met; //Entrance Randomizer stuff @@ -275,7 +277,6 @@ private: Entrance* assumed = nullptr; Entrance* replacement = nullptr; int16_t index = 0xFFFF; - int16_t blueWarp = 0; bool shuffled = false; bool primary = false; bool addedToPool = false; @@ -285,6 +286,7 @@ private: int ShuffleAllEntrances(); void CreateEntranceOverrides(); +std::string EntranceNameByRegions(uint32_t parentRegion, uint32_t connectedRegion); extern std::vector> playthroughEntrances; extern bool noRandomEntrances; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 7063a3191..7c8d027f2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -294,7 +294,12 @@ std::vector GetAccessibleLocations(const std::vector& allowe } // Add shuffled entrances to the entrance playthrough - if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !noRandomEntrances) { + // Include bluewarps when unshuffled but dungeon or boss shuffle is on + if (mode == SearchMode::GeneratePlaythrough && + (exit.IsShuffled() || (exit.GetType() == EntranceType::BlueWarp && + (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) || + Settings::ShuffleBossEntrances.IsNot(SHUFFLEBOSSES_OFF)))) && + !exit.IsAddedToPool() && !noRandomEntrances) { entranceSphere.push_back(&exit); exit.AddToPool(); // Don't list a two-way coupled entrance from both directions diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index 6be67ea84..684dd16e1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -503,3 +503,16 @@ std::vector GetShuffleableEntrances(EntranceType type, bool onlyPrima } return entrancesToShuffle; } + +// Get the specific entrance by name +Entrance* GetEntrance(const std::string name) { + for (uint32_t area : Areas::GetAllAreas()) { + for (auto& exit : AreaTable(area)->exits) { + if (exit.GetName() == name) { + return &exit; + } + } + } + + return nullptr; +} diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 60529a2f6..672a97f5c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -242,6 +242,7 @@ namespace Areas { void AreaTable_Init(); Area* AreaTable(const uint32_t areaKey); std::vector GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true); +Entrance* GetEntrance(const std::string name); // Overworld void AreaTable_Init_LostWoods(); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index 2224df4ca..c1231b29e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -267,5 +267,6 @@ void AreaTable_Init_DekuTree() { { // Exits Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }), + Entrance(KF_OUTSIDE_DEKU_TREE, { [] { return DekuTreeClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index 9f8effbcc..dc88b1b2c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -309,5 +309,6 @@ void AreaTable_Init_DodongosCavern() { { // Exits Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }), + Entrance(DEATH_MOUNTAIN_TRAIL, { [] { return DodongosCavernClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index ff2fb885c..107028872 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -420,5 +420,6 @@ void AreaTable_Init_FireTemple() { { // Exits Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(DMC_CENTRAL_LOCAL, { [] { return FireTempleClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index fea9fda6f..f9bc752cb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -433,5 +433,6 @@ void AreaTable_Init_ForestTemple() { { // Exits Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(SACRED_FOREST_MEADOW, { [] { return ForestTempleClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 108b69ccc..c8e38bb61 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -179,17 +179,17 @@ void AreaTable_Init_JabuJabusBelly() { //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_COMPASS_CHEST, {[]{return (IsChild || CanDive || CanUse(IRON_BOOTS) || LogicJabuAlcoveJumpDive) && (CanUse(SLINGSHOT) || CanUse(BOW) || CanUse(HOOKSHOT) || HasBombchus || (LogicJabuMQRangJump && CanUse(BOOMERANG)));}}), + LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return CanUse(SLINGSHOT);}}), + LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return CanUse(SLINGSHOT);}}), 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_BOOMERANG_CHEST, {[]{return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || CanUse(SLINGSHOT) || CanUse(BOW) || CanUse(STICKS) || Bombs;}}), LocationAccess(JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG));}}), //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);}}), + Entrance(JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && CanUse(SLINGSHOT) && CanUse(BOOMERANG);}}), }); areaTable[JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { @@ -209,8 +209,8 @@ void AreaTable_Init_JabuJabusBelly() { }, { //Locations LocationAccess(JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}), - LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}), - LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}), + LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return CanUse(SLINGSHOT);}}), + LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return CanUse(BOOMERANG) || (LogicJabuNearBossRanged && CanUse(HOOKSHOT));}}), }, { //Exits Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), @@ -245,5 +245,6 @@ void AreaTable_Init_JabuJabusBelly() { { // Exits Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(ZORAS_FOUNTAIN, { [] { return JabuJabusBellyClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp index a3dda7521..61778d563 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp @@ -209,5 +209,6 @@ void AreaTable_Init_ShadowTemple() { { // Exits Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(GRAVEYARD_WARP_PAD_REGION, { [] { return ShadowTempleClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index 2aa0c0516..f676c3c91 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -271,5 +271,6 @@ void AreaTable_Init_SpiritTemple() { { // Exits Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(DESERT_COLOSSUS, { [] { return SpiritTempleClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp index 559b6c20c..f1c86abb0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp @@ -331,5 +331,6 @@ void AreaTable_Init_WaterTemple() { { // Exits Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + Entrance(LAKE_HYLIA, { [] { return WaterTempleClear; } }), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 684e3ec9a..5dcd5a792 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -94,6 +94,7 @@ namespace Settings { Option ShuffleOverworldSpawns = Option::Bool("Overworld Spawns", {"Off", "On"}); Option MixedEntrancePools = Option::Bool("Mixed Entrance Pools", {"Off", "On"}); Option MixDungeons = Option::Bool("Mix Dungeons", {"Off", "On"}); + Option MixBosses = Option::Bool("Mix Bosses", {"Off", "On"}); Option MixOverworld = Option::Bool("Mix Overworld", {"Off", "On"}); Option MixInteriors = Option::Bool("Mix Interiors", {"Off", "On"}); Option MixGrottos = Option::Bool("Mix Grottos", {"Off", "On"}); @@ -135,6 +136,7 @@ namespace Settings { &ShuffleOverworldSpawns, &MixedEntrancePools, &MixDungeons, + &MixBosses, &MixOverworld, &MixInteriors, &MixGrottos, @@ -1298,6 +1300,7 @@ namespace Settings { ctx.shuffleOverworldSpawns = (ShuffleOverworldSpawns) ? 1 : 0; ctx.mixedEntrancePools = (MixedEntrancePools) ? 1 : 0; ctx.mixDungeons = (MixDungeons) ? 1 : 0; + ctx.mixBosses = (MixBosses) ? 1 : 0; ctx.mixOverworld = (MixOverworld) ? 1 : 0; ctx.mixInteriors = (MixInteriors) ? 1 : 0; ctx.mixGrottos = (MixGrottos) ? 1 : 0; @@ -1891,6 +1894,13 @@ namespace Settings { MixDungeons.SetSelectedIndex(OFF); } + if (ShuffleBossEntrances.Is(SHUFFLEBOSSES_FULL)) { + MixBosses.Unhide(); + } else { + MixBosses.Hide(); + MixBosses.SetSelectedIndex(OFF); + } + if (ShuffleOverworldEntrances) { MixOverworld.Unhide(); } else { @@ -1914,6 +1924,8 @@ namespace Settings { } else { MixDungeons.Hide(); MixDungeons.SetSelectedIndex(OFF); + MixBosses.Hide(); + MixBosses.SetSelectedIndex(OFF); MixOverworld.Hide(); MixOverworld.SetSelectedIndex(OFF); MixInteriors.Hide(); @@ -2190,6 +2202,7 @@ namespace Settings { if (!MixedEntrancePools) { MixDungeons.SetSelectedIndex(OFF); + MixBosses.SetSelectedIndex(OFF); MixOverworld.SetSelectedIndex(OFF); MixInteriors.SetSelectedIndex(OFF); MixGrottos.SetSelectedIndex(OFF); @@ -2344,6 +2357,7 @@ namespace Settings { ShuffleOverworldSpawns.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS]); MixedEntrancePools.SetSelectedIndex(cvarSettings[RSK_MIXED_ENTRANCE_POOLS]); MixDungeons.SetSelectedIndex(cvarSettings[RSK_MIX_DUNGEON_ENTRANCES]); + MixBosses.SetSelectedIndex(cvarSettings[RSK_MIX_BOSS_ENTRANCES]); MixOverworld.SetSelectedIndex(cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES]); MixInteriors.SetSelectedIndex(cvarSettings[RSK_MIX_INTERIOR_ENTRANCES]); MixGrottos.SetSelectedIndex(cvarSettings[RSK_MIX_GROTTO_ENTRANCES]); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.hpp b/soh/soh/Enhancements/randomizer/3drando/settings.hpp index 12e6443a4..17ea1f0ee 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.hpp @@ -397,6 +397,7 @@ typedef struct { uint8_t shuffleOverworldSpawns; uint8_t mixedEntrancePools; uint8_t mixDungeons; + uint8_t mixBosses; uint8_t mixOverworld; uint8_t mixInteriors; uint8_t mixGrottos; @@ -784,6 +785,7 @@ void UpdateSettings(std::unordered_map cvarSettin extern Option ShuffleOverworldSpawns; extern Option MixedEntrancePools; extern Option MixDungeons; + extern Option MixBosses; extern Option MixOverworld; extern Option MixInteriors; extern Option MixGrottos; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 0011d3a70..ce885aec5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -307,35 +307,36 @@ static void WriteLocation( static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) { int16_t originalIndex = entrance->GetIndex(); int16_t destinationIndex = -1; - int16_t originalBlueWarp = entrance->GetBlueWarp(); - int16_t replacementBlueWarp = -1; int16_t replacementIndex = entrance->GetReplacement()->GetIndex(); int16_t replacementDestinationIndex = -1; std::string name = entrance->GetName(); std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName; - if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { + // Track the reverse destination, useful for savewarp handling + if (entrance->GetReverse() != nullptr) { destinationIndex = entrance->GetReverse()->GetIndex(); - replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex(); - replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp(); + // When decouple is off we track the replacement's reverse destination, useful for recording visited entrances + if (!entrance->IsDecoupled()) { + replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex(); + } } json entranceJson = json::object({ + {"type", entrance->GetType()}, {"index", originalIndex}, {"destination", destinationIndex}, - {"blueWarp", originalBlueWarp}, {"override", replacementIndex}, {"overrideDestination", replacementDestinationIndex}, }); jsonData["entrances"].push_back(entranceJson); - // When decoupled entrances is off, handle saving reverse entrances with blue warps + // When decoupled entrances is off, handle saving reverse entrances if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { json reverseEntranceJson = json::object({ + {"type", entrance->GetReverse()->GetType()}, {"index", replacementDestinationIndex}, {"destination", replacementIndex}, - {"blueWarp", replacementBlueWarp}, {"override", destinationIndex}, {"overrideDestination", originalIndex}, }); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 984c20bb2..db287fdff 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -315,6 +315,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "World Settings:Overworld Spawns", RSK_SHUFFLE_OVERWORLD_SPAWNS }, { "World Settings:Mixed Entrance Pools", RSK_MIXED_ENTRANCE_POOLS }, { "World Settings:Mix Dungeons", RSK_MIX_DUNGEON_ENTRANCES }, + { "World Settings:Mix Bosses", RSK_MIX_BOSS_ENTRANCES }, { "World Settings:Mix Overworld", RSK_MIX_OVERWORLD_ENTRANCES }, { "World Settings:Mix Interiors", RSK_MIX_INTERIOR_ENTRANCES }, { "World Settings:Mix Grottos", RSK_MIX_GROTTO_ENTRANCES }, @@ -899,6 +900,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_SHUFFLE_OVERWORLD_SPAWNS: case RSK_MIXED_ENTRANCE_POOLS: case RSK_MIX_DUNGEON_ENTRANCES: + case RSK_MIX_BOSS_ENTRANCES: case RSK_MIX_OVERWORLD_ENTRANCES: case RSK_MIX_INTERIOR_ENTRANCES: case RSK_MIX_GROTTO_ENTRANCES: @@ -1562,9 +1564,9 @@ void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent) // set all the entrances to be 0 to indicate an unshuffled entrance for (auto &entranceOveride : gSaveContext.entranceOverrides) { + entranceOveride.type = 0; entranceOveride.index = 0; entranceOveride.destination = 0; - entranceOveride.blueWarp = 0; entranceOveride.override = 0; entranceOveride.overrideDestination = 0; } @@ -1579,12 +1581,12 @@ void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent) json entranceJson = *it; for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) { - if (entranceIt.key() == "index") { + if (entranceIt.key() == "type") { + gSaveContext.entranceOverrides[i].type = entranceIt.value(); + } else if (entranceIt.key() == "index") { gSaveContext.entranceOverrides[i].index = entranceIt.value(); } else if (entranceIt.key() == "destination") { gSaveContext.entranceOverrides[i].destination = entranceIt.value(); - } else if (entranceIt.key() == "blueWarp") { - gSaveContext.entranceOverrides[i].blueWarp = entranceIt.value(); } else if (entranceIt.key() == "override") { gSaveContext.entranceOverrides[i].override = entranceIt.value(); } else if (entranceIt.key() == "overrideDestination") { @@ -3008,6 +3010,7 @@ void GenerateRandomizerImgui(std::string seed = "") { cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF); cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF); cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger("gRandomizeMixDungeons", RO_GENERIC_OFF); + cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger("gRandomizeMixBosses", RO_GENERIC_OFF); cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger("gRandomizeMixOverworld", RO_GENERIC_OFF); cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger("gRandomizeMixInteriors", RO_GENERIC_OFF); cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger("gRandomizeMixGrottos", RO_GENERIC_OFF); @@ -3706,7 +3709,8 @@ void RandomizerSettingsWindow::DrawElement() { // Mixed Entrance Pools UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", "gRandomizeMixedEntrances"); UIWidgets::InsertHelpHoverText( - "Shuffle entrances into a mixed pool instead of separate ones.\n" + "Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose " + "entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n" "\n" "For example, enabling the settings to shuffle grotto, dungeon, and overworld entrances and " "selecting grotto and dungeon entrances here will allow a dungeon to be inside a grotto or " @@ -3720,6 +3724,13 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::EnhancementCheckbox("Mix Dungeons", "gRandomizeMixDungeons"); UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool"); } + if (CVarGetInteger("gRandomizeShuffleBossEntrances", RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == + RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL) { + UIWidgets::Spacer(0); + ImGui::SetCursorPosX(20); + UIWidgets::EnhancementCheckbox("Mix Bosses", "gRandomizeMixBosses"); + UIWidgets::InsertHelpHoverText("Boss entrances will be part of the mixed pool"); + } if (CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 700cddf76..37dc57cef 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1467,6 +1467,7 @@ typedef enum { RSK_SHUFFLE_OVERWORLD_SPAWNS, RSK_MIXED_ENTRANCE_POOLS, RSK_MIX_DUNGEON_ENTRANCES, + RSK_MIX_BOSS_ENTRANCES, RSK_MIX_OVERWORLD_ENTRANCES, RSK_MIX_INTERIOR_ENTRANCES, RSK_MIX_GROTTO_ENTRANCES, diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index ee65d99e4..563873304 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -39,17 +39,12 @@ s16 dynamicExitList[] = { // Owl Flights : 0x492064 and 0x492080 static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0}; -// Boss scenes (normalize boss scene range to 0 on lookup) to the replaced dungeon scene it is connected to -static s16 dungeonBossSceneOverrides[SHUFFLEABLE_BOSS_COUNT] = {0}; +// Boss scenes (normalize boss scene range to 0 on lookup) mapped to save/death warp entrance +static s16 bossSceneSaveDeathWarps[SHUFFLEABLE_BOSS_COUNT] = {0}; static ActorEntry modifiedLinkActorEntry = {0}; EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0}; -typedef struct { - s16 blueWarp; - s16 destination; -} BlueWarpReplacement; - typedef struct { s16 entryway; s16 exit; @@ -61,40 +56,25 @@ typedef struct { } DungeonEntranceInfo; static DungeonEntranceInfo dungeons[] = { - //entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene - { DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, ENTR_KOKIRI_FOREST_11, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS }, - { DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, ENTR_DEATH_MOUNTAIN_TRAIL_5, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS }, - { JABU_JABUS_BELLY_ENTRANCE, ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, ENTR_ZORAS_FOUNTAIN_0, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS }, - { FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, ENTR_SACRED_FOREST_MEADOW_3, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS }, - { FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, ENTR_DEATH_MOUNTAIN_CRATER_5, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS }, - { WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, ENTR_LAKE_HYLIA_9, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS }, - { SPIRIT_TEMPLE_ENTRANCE, ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, ENTR_DESERT_COLOSSUS_8, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS }, - { SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, ENTR_GRAVEYARD_8, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS }, + //entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene + { ENTR_DEKU_TREE_0, ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, ENTR_KOKIRI_FOREST_11, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS }, + { ENTR_DODONGOS_CAVERN_0, ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, ENTR_DEATH_MOUNTAIN_TRAIL_5, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS }, + { ENTR_JABU_JABU_0, ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, ENTR_ZORAS_FOUNTAIN_0, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS }, + { ENTR_FOREST_TEMPLE_0, ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, ENTR_SACRED_FOREST_MEADOW_3, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS }, + { ENTR_FIRE_TEMPLE_0, ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, ENTR_DEATH_MOUNTAIN_CRATER_5, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS }, + { ENTR_WATER_TEMPLE_0, ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, ENTR_LAKE_HYLIA_9, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS }, + { ENTR_SPIRIT_TEMPLE_0, ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, ENTR_DESERT_COLOSSUS_8, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS }, + { ENTR_SHADOW_TEMPLE_0, ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, ENTR_GRAVEYARD_8, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS }, }; -//These variables store the new entrance indices for dungeons so that -//savewarping and game overs respawn players at the proper entrance. -//By default, these will be their vanilla values. -static s16 newDekuTreeEntrance = DEKU_TREE_ENTRANCE; -static s16 newDodongosCavernEntrance = DODONGOS_CAVERN_ENTRANCE; -static s16 newJabuJabusBellyEntrance = JABU_JABUS_BELLY_ENTRANCE; -static s16 newForestTempleEntrance = FOREST_TEMPLE_ENTRANCE; -static s16 newFireTempleEntrance = FIRE_TEMPLE_ENTRANCE; -static s16 newWaterTempleEntrance = WATER_TEMPLE_ENTRANCE; -static s16 newSpiritTempleEntrance = SPIRIT_TEMPLE_ENTRANCE; -static s16 newShadowTempleEntrance = SHADOW_TEMPLE_ENTRANCE; -static s16 newBottomOfTheWellEntrance = BOTTOM_OF_THE_WELL_ENTRANCE; -static s16 newGerudoTrainingGroundsEntrance = GERUDO_TRAINING_GROUNDS_ENTRANCE; -static s16 newIceCavernEntrance = ICE_CAVERN_ENTRANCE; - static s8 hasCopiedEntranceTable = 0; static s8 hasModifiedEntranceTable = 0; void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance); u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) { - return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0 - && entranceOverride->override == 0 && entranceOverride->overrideDestination == 0; + return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->override == 0 && + entranceOverride->overrideDestination == 0; } static void Entrance_SeparateOGCFairyFountainExit(void) { @@ -113,6 +93,28 @@ static void Entrance_SeparateAdultSpawnAndPrelude() { } } +// Fix Adult dungeon blue warps as Child by assigning the child values for the warp pads +static void Entrance_ReplaceChildTempleWarps() { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || + Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) { + // Forest Temple + gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2]; + gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3_1] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2_1]; + // Fire Temple + gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4]; + gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5_1] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4_1]; + // Water Temple + gEntranceTable[ENTR_LAKE_HYLIA_9] = gEntranceTable[ENTR_LAKE_HYLIA_8]; + gEntranceTable[ENTR_LAKE_HYLIA_9_1] = gEntranceTable[ENTR_LAKE_HYLIA_8_1]; + // Shadow Temple + gEntranceTable[ENTR_GRAVEYARD_8] = gEntranceTable[ENTR_GRAVEYARD_7]; + gEntranceTable[ENTR_GRAVEYARD_8_1] = gEntranceTable[ENTR_GRAVEYARD_7_1]; + // Spirit Temple + gEntranceTable[ENTR_DESERT_COLOSSUS_8] = gEntranceTable[ENTR_DESERT_COLOSSUS_5]; + gEntranceTable[ENTR_DESERT_COLOSSUS_8_1] = gEntranceTable[ENTR_DESERT_COLOSSUS_5_1]; + } +} + void Entrance_CopyOriginalEntranceTable(void) { if (!hasCopiedEntranceTable) { memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE); @@ -130,9 +132,6 @@ void Entrance_ResetEntranceTable(void) { void Entrance_Init(void) { s32 index; - size_t blueWarpRemapIdx = 0; - BlueWarpReplacement bluewarps[SHUFFLEABLE_BOSS_COUNT] = {0}; - Entrance_CopyOriginalEntranceTable(); // Skip Child Stealth if given by settings @@ -149,6 +148,7 @@ void Entrance_Init(void) { Entrance_SeparateOGCFairyFountainExit(); Entrance_SeparateAdultSpawnAndPrelude(); + Entrance_ReplaceChildTempleWarps(); // Initialize the entrance override table with each index leading to itself. An // index referring to itself means that the entrance is not currently shuffled. @@ -156,9 +156,9 @@ void Entrance_Init(void) { entranceOverrideTable[i] = i; } - // Initialize all boss rooms connected to their vanilla dungeon + // Initialize all boss room save/death warps with their vanilla dungeon entryway for (s16 i = 1; i < SHUFFLEABLE_BOSS_COUNT; i++) { - dungeonBossSceneOverrides[i] = i; + bossSceneSaveDeathWarps[i] = dungeons[i].entryway; } // Initialize the grotto exit and load lists @@ -172,9 +172,30 @@ void Entrance_Init(void) { } s16 originalIndex = gSaveContext.entranceOverrides[i].index; - s16 blueWarpIndex = gSaveContext.entranceOverrides[i].blueWarp; + s16 originalDestination = gSaveContext.entranceOverrides[i].destination; s16 overrideIndex = gSaveContext.entranceOverrides[i].override; + int16_t bossScene = -1; + int16_t saveWarpEntrance = originalDestination; // Default save warp to the original return entrance + + // Search for boss room overrides and look for the matching save/death warp value to use + // If the boss room is in a dungeon, use the dungeons entryway as the save warp + // Otherwise use the "exit" value for the entrance that lead to the boss room + for (int j = 0; j <= SHUFFLEABLE_BOSS_COUNT; j++) { + if (overrideIndex == dungeons[j].bossDoor) { + bossScene = dungeons[j].bossScene; + } + + if (index == dungeons[j].bossDoor) { + saveWarpEntrance = dungeons[j].entryway; + } + } + + // Found a boss scene and a valid save/death warp value + if (bossScene != -1 && saveWarpEntrance != -1) { + bossSceneSaveDeathWarps[bossScene - SCENE_DEKU_TREE_BOSS] = saveWarpEntrance; + } + //Overwrite grotto related indices if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) { Grotto_SetExitOverride(originalIndex, overrideIndex); @@ -189,36 +210,6 @@ void Entrance_Init(void) { // Overwrite the indices which we want to shuffle, leaving the rest as they are entranceOverrideTable[originalIndex] = overrideIndex; - if (blueWarpIndex != 0) { - // When boss shuffle is enabled, we need to know what dungeon the boss room is connected to for - // death/save warping, and for the blue warp - if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) { - s16 bossScene = -1; - s16 replacedDungeonScene = -1; - s16 replacedDungeonExit = -1; - // Search for the boss scene and replaced blue warp exits - for (s16 j = 0; j <= SHUFFLEABLE_BOSS_COUNT; j++) { - if (blueWarpIndex == dungeons[j].blueWarp) { - bossScene = dungeons[j].bossScene; - } - if (overrideIndex == dungeons[j].bossDoorReverse) { - replacedDungeonScene = dungeons[j].scene; - replacedDungeonExit = dungeons[j].exit; - } - } - - // assign the boss scene override - if (bossScene != -1 && replacedDungeonScene != -1 && replacedDungeonExit != -1) { - dungeonBossSceneOverrides[bossScene - SCENE_DEKU_TREE_BOSS] = replacedDungeonScene; - bluewarps[blueWarpRemapIdx].blueWarp = blueWarpIndex; - bluewarps[blueWarpRemapIdx].destination = replacedDungeonExit; - blueWarpRemapIdx++; - } - } else { - entranceOverrideTable[blueWarpIndex] = overrideIndex; - } - } - //Override both land and water entrances for Hyrule Field -> ZR Front and vice versa if (originalIndex == ENTR_ZORAS_RIVER_0) { //Hyrule Field -> ZR Front land entrance entranceOverrideTable[ENTR_ZORAS_RIVER_3] = overrideIndex; @@ -227,14 +218,6 @@ void Entrance_Init(void) { } } - // If we have remapped blue warps from boss shuffle, handle setting those and grabbing the override for - // the replaced dungeons exit in the event that dungeon shuffle is also turned on - for (size_t i = 0; i < ARRAY_COUNT(bluewarps); i++) { - if (bluewarps[i].blueWarp != 0 && bluewarps[i].destination != 0) { - entranceOverrideTable[bluewarps[i].blueWarp] = Entrance_GetOverride(bluewarps[i].destination); - } - } - // Stop playing background music during shuffled entrance transitions // so that we don't get duplicated or overlapping music tracks if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { @@ -328,40 +311,39 @@ void Entrance_SetGameOverEntrance(void) { s16 scene = gPlayState->sceneNum; - // When in a boss room and boss shuffle is on, get the connected dungeon's original boss room entrance - // then run the normal game over overrides on it + // When in a boss room and boss shuffle is on, use the boss scene to find the death warp entrance if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF && scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) { - // Normalize boss scene range to 0 on lookup - scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS]; - gSaveContext.entranceIndex = dungeons[scene].bossDoor; + // Normalize boss scene range to 0 on lookup and handle for grotto entrances + gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]); + return; } //Set the current entrance depending on which entrance the player last came through switch (gSaveContext.entranceIndex) { case ENTR_DEKU_TREE_BOSS_0 : //Deku Tree Boss Room - gSaveContext.entranceIndex = newDekuTreeEntrance; + gSaveContext.entranceIndex = ENTR_DEKU_TREE_0; return; case ENTR_DODONGOS_CAVERN_BOSS_0 : //Dodongos Cavern Boss Room - gSaveContext.entranceIndex = newDodongosCavernEntrance; + gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0; return; case ENTR_JABU_JABU_BOSS_0 : //Jabu Jabus Belly Boss Room - gSaveContext.entranceIndex = newJabuJabusBellyEntrance; + gSaveContext.entranceIndex = ENTR_JABU_JABU_0; return; case ENTR_FOREST_TEMPLE_BOSS_0 : //Forest Temple Boss Room - gSaveContext.entranceIndex = newForestTempleEntrance; + gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0; return; case ENTR_FIRE_TEMPLE_BOSS_0 : //Fire Temple Boss Room - gSaveContext.entranceIndex = newFireTempleEntrance; + gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0; return; case ENTR_WATER_TEMPLE_BOSS_0 : //Water Temple Boss Room - gSaveContext.entranceIndex = newWaterTempleEntrance; + gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0; return; case ENTR_SPIRIT_TEMPLE_BOSS_0 : //Spirit Temple Boss Room - gSaveContext.entranceIndex = newSpiritTempleEntrance; + gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0; return; case ENTR_SHADOW_TEMPLE_BOSS_0 : //Shadow Temple Boss Room - gSaveContext.entranceIndex = newShadowTempleEntrance; + gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0; return; case ENTR_GANONDORF_BOSS_0 : //Ganondorf Boss Room gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb @@ -374,46 +356,46 @@ void Entrance_SetSavewarpEntrance(void) { s16 scene = gSaveContext.savedSceneNum; - // When in a boss room and boss shuffle is on, use the boss scene override to remap to its - // connected dungeon and use that for the final entrance + // When in a boss room and boss shuffle is on, use the boss scene to find the savewarp entrance if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF && scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) { - // Normalize boss scene range to 0 on lookup - scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS]; + // Normalize boss scene range to 0 on lookup and handle for grotto entrances + gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]); + return; } if (scene == SCENE_DEKU_TREE || scene == SCENE_DEKU_TREE_BOSS) { - gSaveContext.entranceIndex = newDekuTreeEntrance; + gSaveContext.entranceIndex = ENTR_DEKU_TREE_0; } else if (scene == SCENE_DODONGOS_CAVERN || scene == SCENE_DODONGOS_CAVERN_BOSS) { - gSaveContext.entranceIndex = newDodongosCavernEntrance; + gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0; } else if (scene == SCENE_JABU_JABU || scene == SCENE_JABU_JABU_BOSS) { - gSaveContext.entranceIndex = newJabuJabusBellyEntrance; + gSaveContext.entranceIndex = ENTR_JABU_JABU_0; } else if (scene == SCENE_FOREST_TEMPLE || scene == SCENE_FOREST_TEMPLE_BOSS) { //Forest Temple Boss Room - gSaveContext.entranceIndex = newForestTempleEntrance; + gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0; } else if (scene == SCENE_FIRE_TEMPLE || scene == SCENE_FIRE_TEMPLE_BOSS) { //Fire Temple Boss Room - gSaveContext.entranceIndex = newFireTempleEntrance; + gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0; } else if (scene == SCENE_WATER_TEMPLE || scene == SCENE_WATER_TEMPLE_BOSS) { //Water Temple Boss Room - gSaveContext.entranceIndex = newWaterTempleEntrance; + gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0; } else if (scene == SCENE_SPIRIT_TEMPLE || scene == SCENE_SPIRIT_TEMPLE_BOSS) { //Spirit Temple Boss Room - gSaveContext.entranceIndex = newSpiritTempleEntrance; + gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0; } else if (scene == SCENE_SHADOW_TEMPLE || scene == SCENE_SHADOW_TEMPLE_BOSS) { //Shadow Temple Boss Room - gSaveContext.entranceIndex = newShadowTempleEntrance; + gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0; } else if (scene == SCENE_BOTTOM_OF_THE_WELL) { // BOTW - gSaveContext.entranceIndex = newBottomOfTheWellEntrance; + gSaveContext.entranceIndex = ENTR_BOTTOM_OF_THE_WELL_0; } else if (scene == SCENE_GERUDO_TRAINING_GROUND) { // GTG - gSaveContext.entranceIndex = newGerudoTrainingGroundsEntrance; + gSaveContext.entranceIndex = ENTR_GERUDO_TRAINING_GROUND_0; } else if (scene == SCENE_ICE_CAVERN) { // Ice cavern - gSaveContext.entranceIndex = newIceCavernEntrance; + gSaveContext.entranceIndex = ENTR_ICE_CAVERN_0; } else if (scene == SCENE_INSIDE_GANONS_CASTLE) { - gSaveContext.entranceIndex = GANONS_CASTLE_ENTRANCE; + gSaveContext.entranceIndex = ENTR_INSIDE_GANONS_CASTLE_0; } else if (scene == SCENE_GANONS_TOWER || scene == SCENE_INSIDE_GANONS_CASTLE_COLLAPSE || scene == SCENE_GANONS_TOWER_COLLAPSE_INTERIOR || scene == SCENE_GANON_BOSS || scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) { gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb } else if (scene == SCENE_THIEVES_HIDEOUT) { // Theives hideout gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0 } else if (scene == SCENE_LINKS_HOUSE) { - gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); + gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); } else if (LINK_IS_CHILD) { - gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn + gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); // Child Overworld Spawn } else { gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_HYRULE_FIELD_10); // Adult Overworld Spawn (Normally 0x5F4 (ENTR_TEMPLE_OF_TIME_7), but 0x282 (ENTR_HYRULE_FIELD_10) has been repurposed to differentiate from Prelude which also uses 0x5F4) } @@ -494,7 +476,7 @@ void Entrance_OverrideBlueWarp(void) { void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) { switch (cutsceneCmd) { case 24: // Dropping a fish for Jabu Jabu - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance); + gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_JABU_JABU_0); gPlayState->transitionTrigger = TRANS_TRIGGER_START; gPlayState->transitionType = TRANS_TYPE_FADE_BLACK; // In case Jabu's mouth leads to a grotto return diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.h b/soh/soh/Enhancements/randomizer/randomizer_entrance.h index 10a485a94..8d8d3a678 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.h +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.h @@ -8,20 +8,6 @@ #define ENTRANCE_TABLE_SIZE ENTR_MAX -#define DEKU_TREE_ENTRANCE ENTR_DEKU_TREE_0 -#define DODONGOS_CAVERN_ENTRANCE ENTR_DODONGOS_CAVERN_0 -#define JABU_JABUS_BELLY_ENTRANCE ENTR_JABU_JABU_0 -#define FOREST_TEMPLE_ENTRANCE ENTR_FOREST_TEMPLE_0 -#define FIRE_TEMPLE_ENTRANCE ENTR_FIRE_TEMPLE_0 -#define WATER_TEMPLE_ENTRANCE ENTR_WATER_TEMPLE_0 -#define SPIRIT_TEMPLE_ENTRANCE ENTR_SPIRIT_TEMPLE_0 -#define SHADOW_TEMPLE_ENTRANCE ENTR_SHADOW_TEMPLE_0 -#define BOTTOM_OF_THE_WELL_ENTRANCE ENTR_BOTTOM_OF_THE_WELL_0 -#define GERUDO_TRAINING_GROUNDS_ENTRANCE ENTR_GERUDO_TRAINING_GROUND_0 -#define ICE_CAVERN_ENTRANCE ENTR_ICE_CAVERN_0 -#define GANONS_CASTLE_ENTRANCE ENTR_INSIDE_GANONS_CASTLE_0 -#define LINK_HOUSE_SAVEWARP_ENTRANCE ENTR_LINKS_HOUSE_0 - #define ENTRANCE_RANDO_GROTTO_LOAD_START 0x0700 #define ENTRANCE_RANDO_GROTTO_EXIT_START 0x0800 #define MAX_ENTRANCE_RANDO_USED_INDEX 0x0820 @@ -66,7 +52,7 @@ typedef enum { #define ENTRANCE_RANDO_GROTTO_LOAD(index) ENTRANCE_RANDO_GROTTO_LOAD_START + index #define ENTRANCE_RANDO_GROTTO_EXIT(index) ENTRANCE_RANDO_GROTTO_EXIT_START + index -#define ENTRANCE_OVERRIDES_MAX_COUNT 259 // 11 one-way entrances + 124 two-way entrances (x2) +#define ENTRANCE_OVERRIDES_MAX_COUNT 267 // 19 one-way entrances + 124 two-way entrances (x2) #define SHUFFLEABLE_BOSS_COUNT 8 #define SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT 66 // Max entrance rando index is 0x0820, (2080 / 32 == 65) + 1 @@ -79,9 +65,9 @@ typedef enum { (((startTransType) << ENTRANCE_INFO_START_TRANS_TYPE_SHIFT) & ENTRANCE_INFO_START_TRANS_TYPE_MASK)) typedef struct { + uint16_t type; int16_t index; int16_t destination; - int16_t blueWarp; int16_t override; int16_t overrideDestination; } EntranceOverride; diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index c4af7dd6d..13669271f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -104,6 +104,7 @@ const EntranceData entranceData[] = { { ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""}, { ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_DEKU_TREE_1, ENTR_DEKU_TREE_BOSS_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_KOKIRI_FOREST_11, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // Lost Woods { ENTR_KOKIRI_FOREST_2, ENTR_LOST_WOODS_9, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge", "KF", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"}, @@ -131,6 +132,7 @@ const EntranceData entranceData[] = { { ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON}, { ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_FOREST_TEMPLE_1, ENTR_FOREST_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_SACRED_FOREST_MEADOW_3, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // Kakariko Village { ENTR_HYRULE_FIELD_1, ENTR_KAKARIKO_VILLAGE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko", "Hyrule Field", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"}, @@ -179,6 +181,7 @@ const EntranceData entranceData[] = { { ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON}, { ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_SHADOW_TEMPLE_1, ENTR_SHADOW_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_GRAVEYARD_8, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // Death Mountain Trail { ENTR_GORON_CITY_0, ENTR_DEATH_MOUNTAIN_TRAIL_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"}, @@ -194,6 +197,7 @@ const EntranceData entranceData[] = { { ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"}, { ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1}, { ENTR_DODONGOS_CAVERN_1, ENTR_DODONGOS_CAVERN_BOSS_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1}, + { ENTR_DEATH_MOUNTAIN_TRAIL_5, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1}, // Death Mountain Crater { ENTR_GORON_CITY_1, ENTR_DEATH_MOUNTAIN_CRATER_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"}, @@ -208,6 +212,7 @@ const EntranceData entranceData[] = { { ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON}, { ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_FIRE_TEMPLE_1, ENTR_FIRE_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_DEATH_MOUNTAIN_CRATER_5, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // Goron City { ENTR_DEATH_MOUNTAIN_TRAIL_1, ENTR_GORON_CITY_0, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City", "DMT", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"}, @@ -247,6 +252,7 @@ const EntranceData entranceData[] = { { ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON}, { ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_JABU_JABU_1, ENTR_JABU_JABU_BOSS_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_ZORAS_FOUNTAIN_0, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, { ENTR_ZORAS_FOUNTAIN_3, ENTR_ICE_CAVERN_0, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON}, // Hyrule Field @@ -298,6 +304,7 @@ const EntranceData entranceData[] = { { ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"}, { ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1}, { ENTR_WATER_TEMPLE_1, ENTR_WATER_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1}, + { ENTR_LAKE_HYLIA_9, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1}, // Gerudo Area { ENTR_HYRULE_FIELD_5, ENTR_GERUDO_VALLEY_0, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV", "Hyrule Field", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"}, @@ -328,6 +335,7 @@ const EntranceData entranceData[] = { { ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"}, { ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Boss Door", "Twinrova", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1}, { ENTR_SPIRIT_TEMPLE_1, ENTR_SPIRIT_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Boss Door", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1}, + { ENTR_DESERT_COLOSSUS_8, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1}, // Market { ENTR_HYRULE_FIELD_7, ENTR_MARKET_ENTRANCE_DAY_1, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance", "Hyrule Field", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"}, @@ -797,6 +805,11 @@ void EntranceTrackerWindow::DrawElement() { continue; } + // RANDOTODO: Only show blue warps if bluewarp shuffle is on + if (original->metaTag.ends_with("bw") || override->metaTag.ends_with("bw")) { + continue; + } + bool isDiscovered = IsEntranceDiscovered(entrance.index); bool showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered; diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 42f94ee2c..5155bd06b 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -184,9 +184,9 @@ void SaveManager::LoadRandomizerVersion2() { SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(gSaveContext.entranceOverrides), [&](size_t i) { SaveManager::Instance->LoadStruct("", [&]() { + SaveManager::Instance->LoadData("type", gSaveContext.entranceOverrides[i].type); SaveManager::Instance->LoadData("index", gSaveContext.entranceOverrides[i].index); SaveManager::Instance->LoadData("destination", gSaveContext.entranceOverrides[i].destination); - SaveManager::Instance->LoadData("blueWarp", gSaveContext.entranceOverrides[i].blueWarp); SaveManager::Instance->LoadData("override", gSaveContext.entranceOverrides[i].override); SaveManager::Instance->LoadData("overrideDestination", gSaveContext.entranceOverrides[i].overrideDestination); }); @@ -292,9 +292,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(saveContext->entranceOverrides), [&](size_t i) { SaveManager::Instance->SaveStruct("", [&]() { + SaveManager::Instance->SaveData("type", saveContext->entranceOverrides[i].type); SaveManager::Instance->SaveData("index", saveContext->entranceOverrides[i].index); SaveManager::Instance->SaveData("destination", saveContext->entranceOverrides[i].destination); - SaveManager::Instance->SaveData("blueWarp", saveContext->entranceOverrides[i].blueWarp); SaveManager::Instance->SaveData("override", saveContext->entranceOverrides[i].override); SaveManager::Instance->SaveData("overrideDestination", saveContext->entranceOverrides[i].overrideDestination); }); diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index 772978f09..e92925c6a 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -575,6 +575,13 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) { frontRoom = gSaveContext.respawnFlag > 0 ? ((void)0, gSaveContext.respawn[gSaveContext.respawnFlag - 1].roomIndex) : play->setupEntranceList[play->curSpawn].room; + + // In ER, override roomNum to load based on scene and spawn during scene init + if (IS_RANDO && gSaveContext.respawnFlag <= 0 && + Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { + frontRoom = Entrance_OverrideSpawnSceneRoom(play->sceneNum, play->curSpawn, frontRoom); + } + func_8009728C(play, roomCtx, frontRoom); return maxRoomSize; @@ -583,12 +590,6 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) { s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) { size_t size; - // In ER, override roomNum to load based on scene and spawn - if (IS_RANDO && gSaveContext.respawnFlag <= 0 && - Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { - roomNum = Entrance_OverrideSpawnSceneRoom(play->sceneNum, play->curSpawn, roomNum); - } - return OTRfunc_8009728C(play, roomCtx, roomNum); if (roomCtx->status == 0) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 145abcdd0..852c8d3d5 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -4538,7 +4538,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol Scene_SetTransitionForNextEntrance(play); } else { - if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2) { + // In Entrance rando, if our respawnFlag is set for a grotto return, we don't want the void out to happen + if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2 && + (!IS_RANDO || (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && gSaveContext.respawnFlag != 2))) { gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex; Play_TriggerVoidOut(play); gSaveContext.respawnFlag = -2; From 460ec1bb037c28ee45ba535f7db656826bd885c9 Mon Sep 17 00:00:00 2001 From: Spodi Date: Fri, 16 Feb 2024 02:17:03 +0100 Subject: [PATCH 059/300] Use manifest for windows DPI awareness (#3270) --- soh/SHIPOFHARKINIAN.manifest | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/soh/SHIPOFHARKINIAN.manifest b/soh/SHIPOFHARKINIAN.manifest index 80d9f6036..6f47a937f 100644 --- a/soh/SHIPOFHARKINIAN.manifest +++ b/soh/SHIPOFHARKINIAN.manifest @@ -28,4 +28,10 @@ + + + true/pm + permonitorv2,permonitor + + From 46aea3aa7c1e93ee2c557cb7de63358e6eb2a494 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 16 Feb 2024 01:17:28 +0000 Subject: [PATCH 060/300] Player State Docs (#3280) * state flags 1 * state flags 2 * state flags 3 * fill array --- .../randomizer/randomizer_entrance.c | 4 +- soh/src/code/z_actor.c | 67 ++++++++++++------- soh/src/code/z_camera.c | 36 +++++----- soh/src/code/z_onepointdemo.c | 4 +- soh/src/code/z_parameter.c | 10 +-- soh/src/code/z_player_lib.c | 52 +++++++------- .../actors/ovl_Arms_Hook/z_arms_hook.c | 2 +- .../ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c | 4 +- .../overlays/actors/ovl_Bg_Haka/z_bg_haka.c | 12 ++-- .../actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c | 8 +-- .../ovl_Bg_Haka_Sgami/z_bg_haka_sgami.c | 2 +- .../ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c | 8 +-- .../ovl_Bg_Hidan_Sima/z_bg_hidan_sima.c | 2 +- .../ovl_Bg_Ice_Objects/z_bg_ice_objects.c | 6 +- .../actors/ovl_Bg_Jya_Block/z_bg_jya_block.c | 2 +- .../ovl_Bg_Jya_Goroiwa/z_bg_jya_goroiwa.c | 2 +- .../z_bg_jya_zurerukabe.c | 2 +- .../z_bg_mori_kaitenkabe.c | 4 +- .../actors/ovl_Bg_Po_Event/z_bg_po_event.c | 12 ++-- .../ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c | 12 ++-- .../z_bg_spot16_bombstone.c | 2 +- .../ovl_Bg_Spot18_Obj/z_bg_spot18_obj.c | 4 +- .../actors/ovl_Bg_Sst_Floor/z_bg_sst_floor.c | 2 +- .../actors/ovl_Boss_Ganon/z_boss_ganon.c | 4 +- .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 20 +++--- .../overlays/actors/ovl_Boss_Tw/z_boss_tw.c | 10 +-- .../overlays/actors/ovl_Boss_Va/z_boss_va.c | 12 ++-- .../overlays/actors/ovl_Door_Ana/z_door_ana.c | 6 +- .../actors/ovl_Door_Shutter/z_door_shutter.c | 4 +- .../overlays/actors/ovl_Eff_Dust/z_eff_dust.c | 2 +- soh/src/overlays/actors/ovl_En_Am/z_en_am.c | 2 +- soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c | 6 +- .../actors/ovl_En_Blkobj/z_en_blkobj.c | 2 +- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 4 +- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c | 4 +- .../overlays/actors/ovl_En_Bombf/z_en_bombf.c | 10 +-- .../overlays/actors/ovl_En_Boom/z_en_boom.c | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 4 +- soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c | 2 +- .../overlays/actors/ovl_En_Crow/z_en_crow.c | 4 +- soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c | 18 ++--- soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 2 +- .../actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c | 2 +- .../overlays/actors/ovl_En_Door/z_en_door.c | 2 +- soh/src/overlays/actors/ovl_En_Du/z_en_du.c | 10 +-- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 16 ++--- .../actors/ovl_En_Encount1/z_en_encount1.c | 2 +- .../actors/ovl_En_Fire_Rock/z_en_fire_rock.c | 2 +- .../actors/ovl_En_Floormas/z_en_floormas.c | 2 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 2 +- soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c | 12 ++-- soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 4 +- .../actors/ovl_En_Goroiwa/z_en_goroiwa.c | 2 +- soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c | 6 +- .../overlays/actors/ovl_En_Horse/z_en_horse.c | 4 +- soh/src/overlays/actors/ovl_En_In/z_en_in.c | 4 +- .../actors/ovl_En_Kakasi/z_en_kakasi.c | 8 +-- .../actors/ovl_En_Kakasi3/z_en_kakasi3.c | 16 ++--- .../actors/ovl_En_M_Thunder/z_en_m_thunder.c | 14 ++-- soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c | 12 ++-- soh/src/overlays/actors/ovl_En_Ma2/z_en_ma2.c | 10 +-- soh/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c | 2 +- soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c | 38 +++++------ soh/src/overlays/actors/ovl_En_Md/z_en_md.c | 8 +-- soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c | 4 +- .../actors/ovl_En_Nutsball/z_en_nutsball.c | 2 +- .../ovl_En_Okarina_Tag/z_en_okarina_tag.c | 16 ++--- .../overlays/actors/ovl_En_Okuta/z_en_okuta.c | 2 +- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 10 +-- .../actors/ovl_En_Po_Field/z_en_po_field.c | 6 +- soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c | 12 +++- soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c | 4 +- soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c | 5 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 26 +++---- .../actors/ovl_En_Stream/z_en_stream.c | 2 +- soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c | 2 +- soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 4 +- .../overlays/actors/ovl_En_Test/z_en_test.c | 6 +- .../actors/ovl_En_Torch2/z_en_torch2.c | 24 +++---- soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c | 2 +- .../actors/ovl_En_Wallmas/z_en_wallmas.c | 6 +- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 2 +- soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c | 4 +- .../overlays/actors/ovl_Fishing/z_fishing.c | 2 +- .../actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c | 14 ++-- .../ovl_Obj_Timeblock/z_obj_timeblock.c | 4 +- .../ovl_Obj_Warp2block/z_obj_warp2block.c | 4 +- .../overlays/actors/ovl_Shot_Sun/z_shot_sun.c | 4 +- 88 files changed, 375 insertions(+), 347 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 563873304..65606d5d9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -495,8 +495,8 @@ void Entrance_EnableFW(void) { gPlayState->sceneNum == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR || gPlayState->sceneNum == SCENE_GROTTOS || gPlayState->sceneNum == SCENE_FISHING_POND || gPlayState->sceneNum == SCENE_GANON_BOSS || gSaveContext.eventInf[0] & 0x1 || // Ingo's Minigame state - player->stateFlags1 & 0x08A02000 || // Swimming, riding horse, Down A, hanging from a ledge - player->stateFlags2 & 0x00040000 // Blank A + player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER) || // Swimming, riding horse, Down A, hanging from a ledge + player->stateFlags2 & PLAYER_STATE2_CRAWLING // Blank A // Shielding, spinning and getting skull tokens still disable buttons automatically ) { return; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 089ed475a..a8924398b 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -486,7 +486,7 @@ void func_8002C124(TargetContext* targetCtx, PlayState* play) { func_8002BE64(targetCtx, targetCtx->unk_4C, spBC.x, spBC.y, spBC.z); - if ((!(player->stateFlags1 & 0x40)) || (actor != player->unk_664)) { + if ((!(player->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN)) || (actor != player->unk_664)) { OVERLAY_DISP = Gfx_SetupDL(OVERLAY_DISP, 0x39); for (spB0 = 0, spAC = targetCtx->unk_4C; spB0 < spB8; spB0++, spAC = (spAC + 1) % 3) { @@ -1376,7 +1376,7 @@ f32 Actor_HeightDiff(Actor* actorA, Actor* actorB) { } f32 Player_GetHeight(Player* player) { - f32 offset = (player->stateFlags1 & 0x800000) ? 32.0f : 0.0f; + f32 offset = (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) ? 32.0f : 0.0f; if (LINK_IS_ADULT) { return offset + 68.0f; @@ -1386,9 +1386,9 @@ f32 Player_GetHeight(Player* player) { } f32 func_8002DCE4(Player* player) { - if (player->stateFlags1 & 0x800000) { + if (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) { return 8.0f; - } else if (player->stateFlags1 & 0x8000000) { + } else if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { return (R_RUN_SPEED_LIMIT / 100.0f) * 0.6f; } else { return R_RUN_SPEED_LIMIT / 100.0f; @@ -1396,7 +1396,7 @@ f32 func_8002DCE4(Player* player) { } s32 func_8002DD6C(Player* player) { - return player->stateFlags1 & 0x8; + return player->stateFlags1 & PLAYER_STATE1_ITEM_IN_HAND; } s32 func_8002DD78(Player* player) { @@ -1406,19 +1406,19 @@ s32 func_8002DD78(Player* player) { s32 func_8002DDA8(PlayState* play) { Player* player = GET_PLAYER(play); - return (player->stateFlags1 & 0x800) || func_8002DD78(player); + return (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) || func_8002DD78(player); } s32 func_8002DDE4(PlayState* play) { Player* player = GET_PLAYER(play); - return player->stateFlags2 & 0x8; + return player->stateFlags2 & PLAYER_STATE2_FOOTSTEP; } s32 func_8002DDF4(PlayState* play) { Player* player = GET_PLAYER(play); - return player->stateFlags2 & 0x1000; + return player->stateFlags2 & PLAYER_STATE2_STATIONARY_LADDER; } void func_8002DE04(PlayState* play, Actor* actorA, Actor* actorB) { @@ -1440,12 +1440,12 @@ void func_8002DE74(PlayState* play, Player* player) { void Actor_MountHorse(PlayState* play, Player* player, Actor* horse) { player->rideActor = horse; - player->stateFlags1 |= 0x800000; + player->stateFlags1 |= PLAYER_STATE1_ON_HORSE; horse->child = &player->actor; } s32 func_8002DEEC(Player* player) { - return (player->stateFlags1 & 0x20000080) || (player->csAction != 0); + return (player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (player->csAction != 0); } void func_8002DF18(PlayState* play, Player* player) { @@ -2005,10 +2005,13 @@ u32 Actor_HasParent(Actor* actor, PlayState* play) { s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry) { Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x3C7080) && Player_GetExplosiveHeld(player) < 0) { + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | + PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) && + Player_GetExplosiveHeld(player) < 0) { if (((player->heldActor != NULL) && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX)) || (IS_RANDO && (getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))) || - (!(player->stateFlags1 & 0x20000800))) { + (!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) { if ((getItemEntry.getItemId != GI_NONE)) { player->getItemEntry = getItemEntry; player->getItemId = getItemEntry.getItemId; @@ -2041,11 +2044,14 @@ s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry) { s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange) { Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x3C7080) && Player_GetExplosiveHeld(player) < 0) { + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | + PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) && + Player_GetExplosiveHeld(player) < 0) { if ((((player->heldActor != NULL) || (actor == player->targetActor)) && ((!IS_RANDO && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) || (IS_RANDO && ((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) || - (!(player->stateFlags1 & 0x20000800))) { + (!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) { if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) { s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y; s32 absYawDiff = ABS(yawDiff); @@ -2083,10 +2089,13 @@ void GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItem s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x3C7080) && Player_GetExplosiveHeld(player) < 0) { + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | + PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER)) && + Player_GetExplosiveHeld(player) < 0) { if ((((player->heldActor != NULL) || (actor == player->targetActor)) && ((!IS_RANDO && ((getItemId > GI_NONE) && (getItemId < GI_MAX))) || (IS_RANDO && ((getItemId > RG_NONE) && (getItemId < RG_MAX))))) || - (!(player->stateFlags1 & 0x20000800))) { + (!(player->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)))) { if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) { s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y; s32 absYawDiff = ABS(yawDiff); @@ -2156,7 +2165,9 @@ s32 Actor_IsMounted(PlayState* play, Actor* horse) { u32 Actor_SetRideActor(PlayState* play, Actor* horse, s32 mountSide) { Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x003C7880)) { + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_CHARGING_SPIN_ATTACK | PLAYER_STATE1_HANGING_OFF_LEDGE | + PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON | PLAYER_STATE1_CLIMBING_LADDER))) { player->rideActor = horse; player->mountSide = mountSide; return true; @@ -2501,8 +2512,18 @@ void func_800304DC(PlayState* play, ActorContext* actorCtx, ActorEntry* actorEnt } u32 D_80116068[ACTORCAT_MAX] = { - 0x100000C0, 0x100000C0, 0x00000000, 0x100004C0, 0x00000080, 0x300000C0, - 0x10000080, 0x00000000, 0x300000C0, 0x100004C0, 0x00000000, 0x100000C0, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, + 0, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, + PLAYER_STATE1_DEAD, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE, + PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, + 0, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, + 0, + PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS, }; void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { @@ -2543,11 +2564,11 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { sp80 = &D_80116068[0]; - if (player->stateFlags2 & 0x8000000) { + if (player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING) { unkFlag = ACTOR_FLAG_NO_FREEZE_OCARINA; } - if ((player->stateFlags1 & 0x40) && ((player->actor.textId & 0xFF00) != 0x600)) { + if ((player->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN) && ((player->actor.textId & 0xFF00) != 0x600)) { sp74 = player->targetActor; } @@ -3891,7 +3912,7 @@ s16 Actor_TestFloorInDirection(Actor* actor, PlayState* play, f32 distance, s16 s32 Actor_IsTargeted(PlayState* play, Actor* actor) { Player* player = GET_PLAYER(play); - if ((player->stateFlags1 & 0x10) && actor->isTargeted) { + if ((player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) && actor->isTargeted) { return true; } else { return false; @@ -3904,7 +3925,7 @@ s32 Actor_IsTargeted(PlayState* play, Actor* actor) { s32 Actor_OtherIsTargeted(PlayState* play, Actor* actor) { Player* player = GET_PLAYER(play); - if ((player->stateFlags1 & 0x10) && !actor->isTargeted) { + if ((player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) && !actor->isTargeted) { return true; } else { return false; diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index ec3981397..b5a0318f6 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -522,7 +522,7 @@ s32 Camera_GetWaterBoxDataIdx(Camera* camera, f32* waterY) { return -1; } - if (!(camera->player->stateFlags1 & 0x8000000)) { + if (!(camera->player->stateFlags1 & PLAYER_STATE1_IN_WATER)) { // player is not swimming *waterY = BGCHECK_Y_MIN; return -1; @@ -1031,7 +1031,7 @@ s32 Camera_CalcAtForParallel(Camera* camera, VecSph* arg1, f32 yOffset, f32* arg } if (camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || - camera->player->stateFlags1 & 0x200000) { + camera->player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) { *arg3 = Camera_LERPCeilF(playerPosRot->pos.y, *arg3, PCT(OREG(43)), 0.1f); phi_f20 = playerPosRot->pos.y - *arg3; posOffsetTarget.y -= phi_f20; @@ -1134,7 +1134,7 @@ s32 Camera_CalcAtForLockOn(Camera* camera, VecSph* eyeAtDir, Vec3f* targetPos, f tmpPos0.z = tmpPos0.z + lookFromOffset.z; if (camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || - camera->player->stateFlags1 & 0x200000) { + camera->player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) { *yPosOffset = Camera_LERPCeilF(playerPosRot->pos.y, *yPosOffset, PCT(OREG(43)), 0.1f); yPosDelta = playerPosRot->pos.y - *yPosOffset; tmpPos0.y -= yPosDelta; @@ -2203,7 +2203,7 @@ s32 Camera_Parallel1(Camera* camera) { } if (camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || - camera->player->stateFlags1 & 0x200000) { + camera->player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) { anim->yTarget = playerPosRot->pos.y; sp6A = 0; } else { @@ -2907,7 +2907,7 @@ s32 Camera_Battle1(Camera* camera) { sp78 = batt1->swingPitchFinal; fov = batt1->fov; - if (camera->player->stateFlags1 & 0x1000) { + if (camera->player->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK) { // charging sword. anim->unk_10 = Camera_LERPCeilF(PCT(OREG(12)) * 0.5f, anim->unk_10, PCT(OREG(25)), 0.1f); camera->xzOffsetUpdateRate = Camera_LERPCeilF(0.2f, camera->xzOffsetUpdateRate, PCT(OREG(25)), 0.1f); @@ -2978,7 +2978,7 @@ s32 Camera_Battle1(Camera* camera) { } if (camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || - camera->player->stateFlags1 & 0x200000) { + camera->player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) { isOffGround = false; anim->yPosOffset = playerPosRot->pos.y; } else { @@ -3303,7 +3303,7 @@ s32 Camera_KeepOn1(Camera* camera) { anim->unk_0C = NULL; cont: if (camera->playerGroundY == camera->playerPosRot.pos.y || camera->player->actor.gravity > -0.1f || - camera->player->stateFlags1 & 0x200000) { + camera->player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) { anim->unk_08 = playerPosRot->pos.y; sp80 = 0; } else { @@ -3724,7 +3724,7 @@ s32 Camera_KeepOn4(Camera* camera) { keep4->unk_04 = playerHeight * 1.6f * yNormal; keep4->unk_08 = -2.0f; keep4->unk_0C = 120.0f; - keep4->unk_10 = player->stateFlags1 & 0x8000000 ? 0.0f : 20.0f; + keep4->unk_10 = player->stateFlags1 & PLAYER_STATE1_IN_WATER ? 0.0f : 20.0f; keep4->unk_1C = 0x3212; keep4->unk_1E = 0x1E; keep4->unk_18 = 50.0f; @@ -4982,7 +4982,7 @@ s32 Camera_Unique0(Camera* camera) { camera->animState++; } - if (player->stateFlags1 & 0x20000000) { + if (player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) { anim->initalPos = playerPosRot->pos; } @@ -4990,7 +4990,7 @@ s32 Camera_Unique0(Camera* camera) { if (anim->animTimer > 0) { anim->animTimer--; anim->initalPos = playerPosRot->pos; - } else if ((!(player->stateFlags1 & 0x20000000)) && + } else if ((!(player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE)) && ((OLib_Vec3fDistXZ(&playerPosRot->pos, &anim->initalPos) >= 10.0f) || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_A) || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_B) || @@ -5018,7 +5018,7 @@ s32 Camera_Unique0(Camera* camera) { anim->initalPos = playerPosRot->pos; } - if ((!(player->stateFlags1 & 0x20000000)) && + if ((!(player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE)) && ((0.001f < camera->xzSpeed) || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_A) || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_B) || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CLEFT) || @@ -5235,7 +5235,7 @@ s32 Camera_Unique9(Camera* camera) { D_8011D3AC = anim->curKeyFrame->unk_01 & 0xF; } else if ((anim->curKeyFrame->unk_01 & 0xF0) == 0xC0) { Camera_UpdateInterface(0xF000 | ((anim->curKeyFrame->unk_01 & 0xF) << 8)); - } else if (camera->player->stateFlags1 & 0x8000000 && player->currentBoots != PLAYER_BOOTS_IRON) { + } else if (camera->player->stateFlags1 & PLAYER_STATE1_IN_WATER && player->currentBoots != PLAYER_BOOTS_IRON) { func_8002DF38(camera->play, camera->target, 8); osSyncPrintf("camera: demo: player demo set WAIT\n"); } else { @@ -5610,7 +5610,7 @@ s32 Camera_Unique9(Camera* camera) { // Set the player's position camera->player->actor.world.pos.x = anim->playerPos.x; camera->player->actor.world.pos.z = anim->playerPos.z; - if (camera->player->stateFlags1 & 0x8000000 && player->currentBoots != PLAYER_BOOTS_IRON) { + if (camera->player->stateFlags1 & PLAYER_STATE1_IN_WATER && player->currentBoots != PLAYER_BOOTS_IRON) { camera->player->actor.world.pos.y = anim->playerPos.y; } } else { @@ -6171,16 +6171,16 @@ s32 Camera_Demo5(Camera* camera) { sDemo5PrevSfxFrame = camera->play->state.frames; - if (camera->player->stateFlags1 & 0x8000000 && (player->currentBoots != PLAYER_BOOTS_IRON)) { + if (camera->player->stateFlags1 & PLAYER_STATE1_IN_WATER && (player->currentBoots != PLAYER_BOOTS_IRON)) { // swimming, and not iron boots - player->stateFlags1 |= 0x20000000; + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; // env frozen player->actor.freezeTimer = camera->timer; } else { sp4A = playerhead.rot.y - playerTargetGeo.yaw; if (camera->target->category == ACTORCAT_PLAYER) { pad = camera->play->state.frames - sDemo5PrevAction12Frame; - if (player->stateFlags1 & 0x800) { + if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { // holding object over head. func_8002DF54(camera->play, camera->target, 8); } else if (ABS(pad) > 3000) { @@ -7240,7 +7240,7 @@ s32 Camera_UpdateWater(Camera* camera) { } if (camera->unk_14C & 0x200) { - if (player->stateFlags2 & 0x800) { + if (player->stateFlags2 & PLAYER_STATE2_DIVING) { Camera_ChangeSettingFlags(camera, CAM_SET_PIVOT_WATER_SURFACE, 6); camera->unk_14C |= (s16)0x8000; } else if (camera->unk_14C & (s16)0x8000) { @@ -7730,7 +7730,7 @@ void Camera_Finish(Camera* camera) { if ((camera->parentCamIdx == MAIN_CAM) && (camera->csId != 0)) { player->actor.freezeTimer = 0; - player->stateFlags1 &= ~0x20000000; + player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; if (player->csAction != 0) { func_8002DF54(camera->play, &player->actor, 7); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 9489eefcd..411f4fb63 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -788,7 +788,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_8002DF54(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); - player->stateFlags1 |= 0x20000000; + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; player->actor.freezeTimer = 90; i = Quake_Add(csCam, 1); @@ -990,7 +990,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor if (func_800C0CB8(play)) { D_801231B4[0].eyeTargetInit.z = D_801231B4[1].eyeTargetInit.z = !LINK_IS_ADULT ? 100.0f : 120.0f; - if (player->stateFlags1 & 0x08000000) { + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { D_801231B4[2].atTargetInit.z = 0.0f; } Actor_GetWorldPosShapeRot(&spA0, &player->actor); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 6efa962b6..1881ea0e8 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3837,7 +3837,7 @@ void Interface_DrawEnemyHealthBar(TargetContext* targetCtx, PlayState* play) { Interface_CreateQuadVertexGroup(&sEnemyHealthVtx[12], -floorf(halfBarWidth) + endTexWidth, (-texHeight / 2) + 3, healthBarFill, 7, 0); - if (((!(player->stateFlags1 & 0x40)) || (actor != player->unk_664)) && targetCtx->unk_44 < 500.0f) { + if (((!(player->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN)) || (actor != player->unk_664)) && targetCtx->unk_44 < 500.0f) { f32 slideInOffsetY = 0; // Slide in the health bar from edge of the screen (mimic the Z-Target triangles fly in) @@ -4316,7 +4316,7 @@ void Interface_DrawItemButtons(PlayState* play) { if ((gSaveContext.unk_13EA == 1) || (gSaveContext.unk_13EA == 2) || (gSaveContext.unk_13EA == 5)) { temp = 0; - } else if ((player->stateFlags1 & 0x00200000) || (Player_GetEnvironmentalHazard(play) == 4) || + } else if ((player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) || (Player_GetEnvironmentalHazard(play) == 4) || (player->stateFlags2 & PLAYER_STATE2_CRAWLING)) { temp = 70; } else { @@ -5389,7 +5389,7 @@ void Interface_Draw(PlayState* play) { Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[0]], 0); } - if ((player->stateFlags1 & 0x00800000) || (play->shootingGalleryStatus > 1) || + if ((player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (play->shootingGalleryStatus > 1) || ((play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY) && Flags_GetSwitch(play, 0x38))) { if (!fullUi) { @@ -5854,7 +5854,7 @@ void Interface_Draw(PlayState* play) { if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && (msgCtx->msgMode == MSGMODE_NONE) && - !(player->stateFlags2 & 0x01000000) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && + !(player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play) && (gSaveContext.minigameState != 1) && (play->shootingGalleryStatus <= 1) && !((play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY) && Flags_GetSwitch(play, 0x38))) { @@ -6546,7 +6546,7 @@ void Interface_Update(PlayState* play) { HealthMeter_Update(play); if ((gSaveContext.timer1State >= 3) && (play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && - (msgCtx->msgMode == MSGMODE_NONE) && !(player->stateFlags2 & 0x01000000) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && + (msgCtx->msgMode == MSGMODE_NONE) && !(player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play)) {} if (gSaveContext.rupeeAccumulator != 0) { diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 3edaaca5b..532b01eba 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -526,7 +526,7 @@ void Player_SetBootData(PlayState* play, Player* this) { currentBoots = PLAYER_BOOTS_KOKIRI_CHILD; } } else if (currentBoots == PLAYER_BOOTS_IRON) { - if (this->stateFlags1 & 0x8000000) { + if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { currentBoots = PLAYER_BOOTS_IRON_UNDERWATER; } REG(27) = 500; @@ -564,8 +564,8 @@ uint8_t Player_IsCustomLinkModel() { } s32 Player_InBlockingCsMode(PlayState* play, Player* this) { - return (this->stateFlags1 & 0x20000080) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || - (this->stateFlags1 & 1) || (this->stateFlags3 & 0x80) || + return (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || + (this->stateFlags1 & PLAYER_STATE1_LOADING) || (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING) || ((gSaveContext.magicState != MAGIC_STATE_IDLE) && (Player_ActionToMagicSpell(this, this->itemAction) >= 0)); } @@ -576,7 +576,7 @@ s32 Player_InCsMode(PlayState* play) { } s32 func_8008E9C4(Player* this) { - return (this->stateFlags1 & 0x10); + return (this->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET); } s32 Player_IsChildWithHylianShield(Player* this) { @@ -595,7 +595,7 @@ s32 Player_ActionToModelGroup(Player* this, s32 actionParam) { } void Player_SetModelsForHoldingShield(Player* this) { - if ((this->stateFlags1 & 0x400000) && + if ((this->stateFlags1 & PLAYER_STATE1_SHIELDING) && ((this->itemAction < 0) || (this->itemAction == this->heldItemAction))) { if ((CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { @@ -737,15 +737,15 @@ void Player_UpdateBottleHeld(PlayState* play, Player* this, s32 item, s32 action void func_8008EDF0(Player* this) { this->unk_664 = NULL; - this->stateFlags2 &= ~0x2000; + this->stateFlags2 &= ~PLAYER_STATE2_SWITCH_TARGETING; } void func_8008EE08(Player* this) { - if ((this->actor.bgCheckFlags & 1) || (this->stateFlags1 & 0x8A00000) || - (!(this->stateFlags1 & 0xC0000) && ((this->actor.world.pos.y - this->actor.floorHeight) < 100.0f))) { - this->stateFlags1 &= ~0x400F8000; - } else if (!(this->stateFlags1 & 0x2C0000)) { - this->stateFlags1 |= 0x80000; + if ((this->actor.bgCheckFlags & 1) || (this->stateFlags1 & (PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER)) || + (!(this->stateFlags1 & (PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL)) && ((this->actor.world.pos.y - this->actor.floorHeight) < 100.0f))) { + this->stateFlags1 &= ~(PLAYER_STATE1_TARGETING | PLAYER_STATE1_TARGET_LOCKED | PLAYER_STATE1_TARGET_NOTHING | PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_30); + } else if (!(this->stateFlags1 & (PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_CLIMBING_LADDER))) { + this->stateFlags1 |= PLAYER_STATE1_FREEFALL; } func_8008EDF0(this); @@ -757,7 +757,7 @@ void func_8008EEAC(PlayState* play, Actor* actor) { func_8008EE08(this); this->unk_664 = actor; this->unk_684 = actor; - this->stateFlags1 |= 0x10000; + this->stateFlags1 |= PLAYER_STATE1_TARGET_LOCKED; Camera_SetParam(Play_GetCamera(play, 0), 8, actor); Camera_ChangeMode(Play_GetCamera(play, 0), 2); } @@ -765,7 +765,7 @@ void func_8008EEAC(PlayState* play, Actor* actor) { s32 func_8008EF30(PlayState* play) { Player* this = GET_PLAYER(play); - return (this->stateFlags1 & 0x800000); + return (this->stateFlags1 & PLAYER_STATE1_ON_HORSE); } s32 func_8008EF44(PlayState* play, s32 ammo) { @@ -942,7 +942,7 @@ s32 Player_GetEnvironmentalHazard(PlayState* play) { } else if ((this->underwaterTimer > 80) && ((this->currentBoots == PLAYER_BOOTS_IRON) || (this->underwaterTimer >= 300))) { // Deep underwater var = ((this->currentBoots == PLAYER_BOOTS_IRON) && (this->actor.bgCheckFlags & 1)) ? 1 : 3; - } else if (this->stateFlags1 & 0x8000000) { // Swimming + } else if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { // Swimming var = 2; } else { return 0; @@ -1171,7 +1171,7 @@ void func_8008F87C(PlayState* play, Player* this, SkelAnime* skelAnime, Vec3f* p s16 temp2; s32 temp3; - if ((this->actor.scale.y >= 0.0f) && !(this->stateFlags1 & 0x80) && + if ((this->actor.scale.y >= 0.0f) && !(this->stateFlags1 & PLAYER_STATE1_DEAD) && (Player_ActionToMagicSpell(this, this->itemAction) < 0)) { s32 pad; @@ -1367,10 +1367,10 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** if ((sLeftHandType == PLAYER_MODELTYPE_LH_BGS) && (gSaveContext.swordHealth <= 0.0f)) { dLists += 4; - } else if ((sLeftHandType == PLAYER_MODELTYPE_LH_BOOMERANG) && (this->stateFlags1 & 0x2000000)) { + } else if ((sLeftHandType == PLAYER_MODELTYPE_LH_BOOMERANG) && (this->stateFlags1 & PLAYER_STATE1_THREW_BOOMERANG)) { dLists = &gPlayerLeftHandOpenDLs[gSaveContext.linkAge]; - sLeftHandType = 0; - } else if ((this->leftHandType == PLAYER_MODELTYPE_LH_OPEN) && (this->actor.speedXZ > 2.0f) && !(this->stateFlags1 & 0x8000000)) { + sLeftHandType = PLAYER_MODELTYPE_LH_OPEN; + } else if ((this->leftHandType == PLAYER_MODELTYPE_LH_OPEN) && (this->actor.speedXZ > 2.0f) && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER)) { dLists = &gPlayerLeftHandClosedDLs[gSaveContext.linkAge]; sLeftHandType = PLAYER_MODELTYPE_LH_CLOSED; } @@ -1381,7 +1381,7 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** if (sRightHandType == PLAYER_MODELTYPE_RH_SHIELD) { dLists += this->currentShield * 4; - } else if ((this->rightHandType == PLAYER_MODELTYPE_RH_OPEN) && (this->actor.speedXZ > 2.0f) && !(this->stateFlags1 & 0x8000000)) { + } else if ((this->rightHandType == PLAYER_MODELTYPE_RH_OPEN) && (this->actor.speedXZ > 2.0f) && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER)) { dLists = &sPlayerRightHandClosedDLs[gSaveContext.linkAge]; sRightHandType = PLAYER_MODELTYPE_RH_CLOSED; } @@ -1510,7 +1510,7 @@ void Player_UpdateShieldCollider(PlayState* play, Player* this, ColliderQuad* co COLTYPE_METAL, }; - if (this->stateFlags1 & 0x400000) { + if (this->stateFlags1 & PLAYER_STATE1_SHIELDING) { Vec3f quadDest[4]; this->shieldQuad.base.colType = shieldColTypes[this->currentShield]; @@ -1544,12 +1544,12 @@ void func_800906D4(PlayState* play, Player* this, Vec3f* newTipPos) { Matrix_MultVec3f(&D_801260A4[2], &newBasePos[2]); if (func_80090480(play, NULL, &this->meleeWeaponInfo[0], &newTipPos[0], &newBasePos[0]) && - !(this->stateFlags1 & 0x400000)) { + !(this->stateFlags1 & PLAYER_STATE1_SHIELDING)) { EffectBlure_AddVertex(Effect_GetByIndex(this->meleeWeaponEffectIndex), &this->meleeWeaponInfo[0].tip, &this->meleeWeaponInfo[0].base); } - if ((this->meleeWeaponState > 0) && ((this->meleeWeaponAnimation < 0x18) || (this->stateFlags2 & 0x20000))) { + if ((this->meleeWeaponState > 0) && ((this->meleeWeaponAnimation < 0x18) || (this->stateFlags2 & PLAYER_STATE2_SPIN_ATTACKING))) { func_80090480(play, &this->meleeWeaponQuads[0], &this->meleeWeaponInfo[1], &newTipPos[1], &newBasePos[1]); func_80090480(play, &this->meleeWeaponQuads[1], &this->meleeWeaponInfo[2], &newTipPos[2], &newBasePos[2]); } @@ -1818,13 +1818,13 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve if (this->actor.scale.y >= 0.0f) { if (!Player_HoldsHookshot(this) && ((hookedActor = this->heldActor) != NULL)) { - if (this->stateFlags1 & 0x200) { + if (this->stateFlags1 & PLAYER_STATE1_READY_TO_FIRE) { Matrix_MultVec3f(&sLeftHandArrowVec3, &hookedActor->world.pos); Matrix_RotateZYX(0x69E8, -0x5708, 0x458E, MTXMODE_APPLY); Matrix_Get(&sp14C); Matrix_MtxFToYXZRotS(&sp14C, &hookedActor->world.rot, 0); hookedActor->shape.rot = hookedActor->world.rot; - } else if (this->stateFlags1 & 0x800) { + } else if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { Vec3s spB8; Matrix_Get(&sp14C); @@ -1858,7 +1858,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve Matrix_Push(); Matrix_Translate(stringData->pos.x, stringData->pos.y, stringData->pos.z, MTXMODE_APPLY); - if ((this->stateFlags1 & 0x200) && (this->unk_860 >= 0) && (this->unk_834 <= 10)) { + if ((this->stateFlags1 & PLAYER_STATE1_READY_TO_FIRE) && (this->unk_860 >= 0) && (this->unk_834 <= 10)) { Vec3f sp90; f32 distXYZ; @@ -1938,7 +1938,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve } if ((this->unk_862 != 0) || ((func_8002DD6C(this) == 0) && (heldActor != NULL))) { - if (!(this->stateFlags1 & 0x400) && (this->unk_862 != 0) && (this->exchangeItemId != EXCH_ITEM_NONE)) { + if (!(this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) && (this->unk_862 != 0) && (this->exchangeItemId != EXCH_ITEM_NONE)) { Math_Vec3f_Copy(&sGetItemRefPos, &this->leftHandPos); } else { sGetItemRefPos.x = (this->bodyPartsPos[15].x + this->leftHandPos.x) * 0.5f; diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index 93ff272f4..0c7435da4 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -122,7 +122,7 @@ s32 ArmsHook_CheckForCancel(ArmsHook* this) { if (Player_HoldsHookshot(player)) { if ((player->itemAction != player->heldItemAction) || (player->actor.flags & ACTOR_FLAG_PLAYER_TALKED_TO) || - ((player->stateFlags1 & 0x4000080))) { + ((player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_DAMAGED)))) { this->timer = 0; ArmsHook_DetachHookFromActor(this); Math_Vec3f_Copy(&this->actor.world.pos, &player->unk_3C8); diff --git a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c index e10eb04be..ae8f9cd05 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c +++ b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c @@ -237,7 +237,7 @@ void BgGndIceblock_Idle(BgGndIceblock* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if (this->dyna.unk_150 > 0.0f) { BgGndIceblock_SetNextPosition(this); if (Actor_WorldDistXZToPoint(&this->dyna.actor, &this->targetPos) > 1.0f) { @@ -254,7 +254,7 @@ void BgGndIceblock_Reset(BgGndIceblock* this, PlayState* play) { Actor* thisx = &this->dyna.actor; if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y, 1.0f)) { diff --git a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c index 3745db003..2379b0a58 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c @@ -61,7 +61,7 @@ void func_8087B758(BgHaka* this, Player* player) { func_8002DBD0(&this->dyna.actor, &sp1C, &player->actor.world.pos); if (fabsf(sp1C.x) < 34.6f && sp1C.z > -112.8f && sp1C.z < -36.0f) { - player->stateFlags2 |= 0x200; + player->stateFlags2 |= PLAYER_STATE2_SPAWN_DUST; } } @@ -71,7 +71,7 @@ void func_8087B7E8(BgHaka* this, PlayState* play) { if (this->dyna.unk_150 != 0.0f) { if (play->sceneNum == SCENE_GRAVEYARD && !LINK_IS_ADULT && IS_DAY && !CVarGetInteger("gDayGravePull", 0)) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if (!Play_InCsMode(play)) { Message_StartTextbox(play, 0x5073, NULL); this->dyna.actor.params = 100; @@ -80,7 +80,7 @@ void func_8087B7E8(BgHaka* this, PlayState* play) { } else if (0.0f < this->dyna.unk_150 || (play->sceneNum == SCENE_LAKE_HYLIA && !LINK_IS_ADULT && !Flags_GetSwitch(play, 0x23))) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } else { this->dyna.actor.world.rot.y = this->dyna.actor.shape.rot.y + 0x8000; this->actionFunc = func_8087B938; @@ -112,7 +112,7 @@ void func_8087B938(BgHaka* this, PlayState* play) { } actor = actor->next; } - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if (this->dyna.actor.params == 1) { func_80078884(NA_SE_SY_CORRECT_CHIME); @@ -146,7 +146,7 @@ void func_8087BAAC(BgHaka* this, PlayState* play) { if (this->dyna.unk_150 != 0.0f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } } @@ -159,7 +159,7 @@ void func_8087BAE4(BgHaka* this, PlayState* play) { } if (this->dyna.unk_150 != 0.0f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } if (this->dyna.actor.params == 0) { this->actionFunc = func_8087B7E8; diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c b/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c index de2235b2e..c61c93a46 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c @@ -153,7 +153,7 @@ void BgHakaGate_StatueInactive(BgHakaGate* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } @@ -172,7 +172,7 @@ void BgHakaGate_StatueIdle(BgHakaGate* this, PlayState* play) { this->vTurnDirection = linkDirection * forceDirection; this->actionFunc = BgHakaGate_StatueTurn; } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; if (this->vTimer != 0) { this->vTimer--; @@ -197,7 +197,7 @@ void BgHakaGate_StatueTurn(BgHakaGate* this, PlayState* play) { turnFinished = Math_StepToS(&this->vTurnAngleDeg10, 600, this->vTurnRateDeg10); turnAngle = this->vTurnAngleDeg10 * this->vTurnDirection; this->dyna.actor.shape.rot.y = (this->vRotYDeg10 + turnAngle) * 0.1f * (0x10000 / 360.0f); - if ((player->stateFlags2 & 0x10) && (sStatueDistToPlayer > 0.0f)) { + if ((player->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) && (sStatueDistToPlayer > 0.0f)) { player->actor.world.pos.x = this->dyna.actor.home.pos.x + (Math_SinS(this->dyna.actor.shape.rot.y - this->vInitTurnAngle) * sStatueDistToPlayer); @@ -209,7 +209,7 @@ void BgHakaGate_StatueTurn(BgHakaGate* this, PlayState* play) { } sStatueRotY = this->dyna.actor.shape.rot.y; if (turnFinished) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->vRotYDeg10 = (this->vRotYDeg10 + turnAngle) % 3600; this->vTurnRateDeg10 = CVarGetInteger("gFasterBlockPush", 0) * 2; this->vTurnAngleDeg10 = 0; diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Sgami/z_bg_haka_sgami.c b/soh/src/overlays/actors/ovl_Bg_Haka_Sgami/z_bg_haka_sgami.c index 846cc1f72..22b8c989a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Sgami/z_bg_haka_sgami.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Sgami/z_bg_haka_sgami.c @@ -290,7 +290,7 @@ void BgHakaSgami_Update(Actor* thisx, PlayState* play) { BgHakaSgami* this = (BgHakaSgami*)thisx; Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x300000C0) || (this->actionFunc == BgHakaSgami_SetupSpin)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE)) || (this->actionFunc == BgHakaSgami_SetupSpin)) { this->actionFunc(this, play); } } diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c index 8b1d99cb9..36cfb0a27 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c @@ -151,7 +151,7 @@ void func_8088B268(BgHidanRock* this, PlayState* play) { this->dyna.actor.world.pos.z = (Math_CosS(this->dyna.unk_158) * D_8088BFC0) + this->dyna.actor.home.pos.z; if (temp_v1) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; this->dyna.actor.home.pos.x = this->dyna.actor.world.pos.x; this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z; @@ -162,7 +162,7 @@ void func_8088B268(BgHidanRock* this, PlayState* play) { func_8002F974(&this->dyna.actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG); } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; if (this->timer != 0) { this->timer--; @@ -180,7 +180,7 @@ void func_8088B268(BgHidanRock* this, PlayState* play) { this->dyna.actor.world.pos.z = D_8088BF60.z; this->dyna.actor.speedXZ = 0.0f; D_8088BFC0 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->actionFunc = func_8088B79C; } @@ -300,7 +300,7 @@ void func_8088B990(BgHidanRock* this, PlayState* play) { this->timer++; if (this->dyna.unk_150 != 0.0f) { this->dyna.actor.speedXZ = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } if ((this->type == 0 && (Math_SmoothStepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y + 1820.0f, diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Sima/z_bg_hidan_sima.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Sima/z_bg_hidan_sima.c index ce1732e07..03615e480 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Sima/z_bg_hidan_sima.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Sima/z_bg_hidan_sima.c @@ -118,7 +118,7 @@ void func_8088E518(BgHidanSima* this, PlayState* play) { Player* player = GET_PLAYER(play); Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y, 3.4f); - if (func_8004356C(&this->dyna) && !(player->stateFlags1 & 0x6000)) { + if (func_8004356C(&this->dyna) && !(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE))) { this->timer = 20; this->dyna.actor.world.rot.y = Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x4000; if (this->dyna.actor.home.pos.y <= this->dyna.actor.world.pos.y) { diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c index 039b77807..1cd91d468 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c @@ -138,7 +138,7 @@ void BgIceObjects_Idle(BgIceObjects* this, PlayState* play) { Actor* thisx = &this->dyna.actor; if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if ((this->dyna.unk_150 > 0.0f) && !Player_InCsMode(play)) { BgIceObjects_SetNextTarget(this, play); if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) { @@ -203,7 +203,7 @@ void BgIceObjects_Reset(BgIceObjects* this, PlayState* play) { Actor* thisx = &this->dyna.actor; if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y, 1.0f)) { @@ -218,7 +218,7 @@ void BgIceObjects_Stuck(BgIceObjects* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Block/z_bg_jya_block.c b/soh/src/overlays/actors/ovl_Bg_Jya_Block/z_bg_jya_block.c index ff695140d..848931456 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Block/z_bg_jya_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Block/z_bg_jya_block.c @@ -59,7 +59,7 @@ void BgJyaBlock_Update(Actor* thisx, PlayState* play) { BgJyaBlock* this = (BgJyaBlock*)thisx; Player* player = GET_PLAYER(play); - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Goroiwa/z_bg_jya_goroiwa.c b/soh/src/overlays/actors/ovl_Bg_Jya_Goroiwa/z_bg_jya_goroiwa.c index 000895dc5..30164bf2e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Goroiwa/z_bg_jya_goroiwa.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Goroiwa/z_bg_jya_goroiwa.c @@ -201,7 +201,7 @@ void BgJyaGoroiwa_Update(Actor* thisx, PlayState* play) { s32 bgId; Vec3f pos; - if (!(player->stateFlags1 & 0x300000C0)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE))) { this->actionFunc(this, play); BgJyaGoroiwa_UpdateRotation(this); pos.x = this->actor.world.pos.x; diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Zurerukabe/z_bg_jya_zurerukabe.c b/soh/src/overlays/actors/ovl_Bg_Jya_Zurerukabe/z_bg_jya_zurerukabe.c index b8ee9c331..1b0f52ae8 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Zurerukabe/z_bg_jya_zurerukabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Zurerukabe/z_bg_jya_zurerukabe.c @@ -78,7 +78,7 @@ void BgJyaZurerukabe_InitDynaPoly(BgJyaZurerukabe* this, PlayState* play, Collis void func_8089B4C8(BgJyaZurerukabe* this, PlayState* play) { Player* player = GET_PLAYER(play); - if ((player->stateFlags1 == 0x200000) && (player->actor.wallPoly != NULL)) { + if ((player->stateFlags1 == PLAYER_STATE1_CLIMBING_LADDER) && (player->actor.wallPoly != NULL)) { s32 i; for (i = 0; i < ARRAY_COUNT(D_8089BA18); i++) { diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c index 645d5cc56..8392e7224 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c @@ -112,7 +112,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) { } if (fabsf(this->dyna.unk_150) > 0.001f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } } @@ -145,7 +145,7 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) { } if (fabsf(this->dyna.unk_150) > 0.001f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } Math_Vec3f_Copy(&player->actor.world.pos, &this->lockedPlayerPos); } diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c index ae699abb6..a2fca0db7 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c @@ -348,7 +348,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) { } } else { if ((gSaveContext.timer1Value == 0) && (sBgPoEventBlocksAtRest == 5)) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; sBgPoEventPuzzleState = 0x10; sBgPoEventBlocksAtRest = 0; } @@ -367,11 +367,11 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) { this->direction = (this->dyna.unk_150 >= 0.0f) ? 1.0f : -1.0f; this->actionFunc = BgPoEvent_BlockPush; } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; DECR(this->direction); } @@ -394,7 +394,7 @@ void BgPoEvent_BlockPush(BgPoEvent* this, PlayState* play) { this->dyna.actor.world.pos.x = (Math_SinS(this->dyna.unk_158) * displacement) + this->dyna.actor.home.pos.x; this->dyna.actor.world.pos.z = (Math_CosS(this->dyna.unk_158) * displacement) + this->dyna.actor.home.pos.z; if (blockStop) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if ((this->dyna.unk_150 > 0.0f) && (func_800435D8(play, &this->dyna, 0x1E, 0x32, -0x14) == 0)) { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); } @@ -419,7 +419,7 @@ void BgPoEvent_BlockReset(BgPoEvent* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } if (Math_StepToF(&this->dyna.actor.world.pos.y, 493.0f, 1.0f) && @@ -439,7 +439,7 @@ void BgPoEvent_BlockSolved(BgPoEvent* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } if (Math_StepToF(&this->dyna.actor.world.pos.y, 369.0f, 2.0f)) { sBgPoEventPuzzleState = 0x20; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c b/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c index 019c71cd0..4385c4341 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c @@ -239,11 +239,11 @@ void func_808B40AC(BgSpot15Rrbox* this, PlayState* play) { this->unk_17C = this->dyna.unk_150; func_808B4178(this, play); } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } @@ -275,7 +275,7 @@ void func_808B4194(BgSpot15Rrbox* this, PlayState* play) { if (!func_808B3F58(this, play)) { actor->home.pos.x = actor->world.pos.x; actor->home.pos.z = actor->world.pos.z; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; this->unk_178 = 0.0f; this->unk_174 = 0.0f; @@ -290,7 +290,7 @@ void func_808B4194(BgSpot15Rrbox* this, PlayState* play) { } actor->home.pos.x = actor->world.pos.x; actor->home.pos.z = actor->world.pos.z; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; this->unk_178 = 0.0f; this->unk_174 = 0.0f; @@ -316,7 +316,7 @@ void func_808B43D0(BgSpot15Rrbox* this, PlayState* play) { if (fabsf(this->dyna.unk_150) > 0.001f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } Actor_MoveForward(actor); @@ -347,7 +347,7 @@ void func_808B44B8(BgSpot15Rrbox* this, PlayState* play) { void func_808B44CC(BgSpot15Rrbox* this, PlayState* play) { Player* player = GET_PLAYER(play); - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } diff --git a/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c b/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c index 5509765c3..4bc551eae 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot16_Bombstone/z_bg_spot16_bombstone.c @@ -413,7 +413,7 @@ void func_808B57E0(BgSpot16Bombstone* this, PlayState* play) { OnePointCutscene_Init(play, 4180, sTimer, NULL, MAIN_CAM); } } - } else if (player->stateFlags1 & 0x800) { + } else if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { playerHeldActor = player->heldActor; if (playerHeldActor != NULL && playerHeldActor->category == ACTORCAT_EXPLOSIVE && playerHeldActor->id == ACTOR_EN_BOMBF) { diff --git a/soh/src/overlays/actors/ovl_Bg_Spot18_Obj/z_bg_spot18_obj.c b/soh/src/overlays/actors/ovl_Bg_Spot18_Obj/z_bg_spot18_obj.c index e24e39902..bcff47d6b 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot18_Obj/z_bg_spot18_obj.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot18_Obj/z_bg_spot18_obj.c @@ -213,7 +213,7 @@ void func_808B8E20(BgSpot18Obj* this, PlayState* play) { if (fabsf(this->dyna.unk_150) > 0.001f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } } @@ -256,7 +256,7 @@ void func_808B8F08(BgSpot18Obj* this, PlayState* play) { this->dyna.actor.world.pos.x = (Math_SinS(this->dyna.actor.world.rot.y) * 80.0f) + this->dyna.actor.home.pos.x; this->dyna.actor.world.pos.z = (Math_CosS(this->dyna.actor.world.rot.y) * 80.0f) + this->dyna.actor.home.pos.z; this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); func_80078884(NA_SE_SY_CORRECT_CHIME); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); diff --git a/soh/src/overlays/actors/ovl_Bg_Sst_Floor/z_bg_sst_floor.c b/soh/src/overlays/actors/ovl_Bg_Sst_Floor/z_bg_sst_floor.c index 444de05e3..f62f09128 100644 --- a/soh/src/overlays/actors/ovl_Bg_Sst_Floor/z_bg_sst_floor.c +++ b/soh/src/overlays/actors/ovl_Bg_Sst_Floor/z_bg_sst_floor.c @@ -81,7 +81,7 @@ void BgSstFloor_Update(BgSstFloor* thisx, PlayState* play) { this->dyna.actor.params = BONGOFLOOR_REST; this->drumPhase = 28; - if (func_8004356C(&this->dyna) && !(player->stateFlags1 & 0x6000)) { + if (func_8004356C(&this->dyna) && !(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE))) { distFromRim = 600.0f - this->dyna.actor.xzDistToPlayer; if (distFromRim > 0.0f) { if (distFromRim > 350.0f) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index ebc244d74..97551ca46 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -2276,10 +2276,10 @@ void BossGanon_Wait(BossGanon* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->unk_1C2 == 0) && !(player->actor.world.pos.y < 0.0f)) { - if (!(player->stateFlags1 & 0x2000) && (fabsf(player->actor.world.pos.x) < 110.0f) && + if (!(player->stateFlags1 & PLAYER_STATE1_HANGING_OFF_LEDGE) && (fabsf(player->actor.world.pos.x) < 110.0f) && (fabsf(player->actor.world.pos.z) < 110.0f)) { BossGanon_SetupPoundFloor(this, play); - } else if ((this->timers[0] == 0) && !(player->stateFlags1 & 0x2000)) { + } else if ((this->timers[0] == 0) && !(player->stateFlags1 & PLAYER_STATE1_HANGING_OFF_LEDGE)) { this->timers[0] = (s16)Rand_ZeroFloat(30.0f) + 30; if ((s8)this->actor.colChkInfo.health >= 20) { diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index f7a48f873..e811c0a35 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -387,7 +387,7 @@ void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { player->targetYaw = -0x8000; player->currentYaw = -0x8000; player->fallStartHeight = 0; - player->stateFlags1 |= 0x20; + player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED; func_80064520(play, &play->csCtx); func_8002DF54(play, &this->actor, 8); @@ -421,7 +421,7 @@ void BossSst_HeadIntro(BossSst* this, PlayState* play) { if (this->timer == 0) { sHands[RIGHT]->actor.flags |= ACTOR_FLAG_TARGETABLE; sHands[LEFT]->actor.flags |= ACTOR_FLAG_TARGETABLE; - player->stateFlags1 &= ~0x20; + player->stateFlags1 &= ~PLAYER_STATE1_INPUT_DISABLED; func_80064534(play, &play->csCtx); func_8002DF54(play, &this->actor, 7); sCameraAt.y += 30.0f; @@ -667,7 +667,7 @@ void BossSst_HeadNeutral(BossSst* this, PlayState* play) { } if (this->timer == 0) { - if ((GET_PLAYER(play)->actor.world.pos.y > -50.0f) && !(GET_PLAYER(play)->stateFlags1 & 0x6080)) { + if ((GET_PLAYER(play)->actor.world.pos.y > -50.0f) && !(GET_PLAYER(play)->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE))) { sHands[Rand_ZeroOne() <= 0.5f]->ready = true; BossSst_HeadSetupWait(this); } else { @@ -1252,7 +1252,7 @@ void BossSst_HandWait(BossSst* this, PlayState* play) { this->timer--; } - if ((this->timer == 0) && (player->actor.world.pos.y > -50.0f) && !(player->stateFlags1 & 0x6080)) { + if ((this->timer == 0) && (player->actor.world.pos.y > -50.0f) && !(player->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE))) { BossSst_HandSelectAttack(this); } } else if (sHead->actionFunc == BossSst_HeadNeutral) { @@ -1735,7 +1735,7 @@ void BossSst_HandClap(BossSst* this, PlayState* play) { if (this->ready) { this->timer = 30; this->colliderJntSph.base.atFlags &= ~(AT_ON | AT_HIT); - if (!(player->stateFlags2 & 0x80)) { + if (!(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { dropFlag = true; } } else { @@ -1824,7 +1824,7 @@ void BossSst_HandGrab(BossSst* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { this->colliderJntSph.base.atFlags &= ~(AT_ON | AT_HIT); this->actor.speedXZ = 0.0f; - if (player->stateFlags2 & 0x80) { + if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { if (Rand_ZeroOne() < 0.5f) { BossSst_HandSetupCrush(this); } else { @@ -1851,7 +1851,7 @@ void BossSst_HandGrab(BossSst* this, PlayState* play) { this->actor.world.pos.x += this->actor.speedXZ * Math_SinS(this->actor.world.rot.y); this->actor.world.pos.z += this->actor.speedXZ * Math_CosS(this->actor.world.rot.y); - if (player->stateFlags2 & 0x80) { + if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { player->unk_850 = 0; player->actor.world.pos = this->actor.world.pos; player->actor.shape.rot.y = this->actor.shape.rot.y; @@ -1872,7 +1872,7 @@ void BossSst_HandCrush(BossSst* this, PlayState* play) { this->timer--; } - if (!(player->stateFlags2 & 0x80)) { + if (!(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { BossSst_HandReleasePlayer(this, play, true); BossSst_HandSetupEndCrush(this); } else { @@ -1945,7 +1945,7 @@ void BossSst_HandSwing(BossSst* this, PlayState* play) { Math_ScaledStepToS(&this->actor.shape.rot.z, 0, 0x800); } - if (player->stateFlags2 & 0x80) { + if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { player->unk_850 = 0; Math_Vec3f_Copy(&player->actor.world.pos, &this->actor.world.pos); player->actor.shape.rot.x = this->actor.shape.rot.x; @@ -1958,7 +1958,7 @@ void BossSst_HandSwing(BossSst* this, PlayState* play) { } if ((this->timer == 4) && (this->amplitude == 0) && SkelAnime_Update(&this->skelAnime) && - (player->stateFlags2 & 0x80)) { + (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { BossSst_HandReleasePlayer(this, play, false); player->actor.world.pos.x += 70.0f * Math_SinS(this->actor.shape.rot.y); player->actor.world.pos.z += 70.0f * Math_CosS(this->actor.shape.rot.y); diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 5360eef02..4f0eadd4b 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -803,7 +803,7 @@ s32 BossTw_CheckBeamReflection(BossTw* this, PlayState* play) { Vec3f vec; Player* player = GET_PLAYER(play); - if (player->stateFlags1 & 0x400000 && + if (player->stateFlags1 & PLAYER_STATE1_SHIELDING && (s16)(player->actor.shape.rot.y - this->actor.shape.rot.y + 0x8000) < 0x2000 && (s16)(player->actor.shape.rot.y - this->actor.shape.rot.y + 0x8000) > -0x2000) { // player is shielding and facing angles are less than 45 degrees in either direction @@ -945,7 +945,7 @@ void BossTw_ShootBeam(BossTw* this, PlayState* play) { if (this->timers[1] != 0) { Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, this->rotateSpeed); - if ((player->stateFlags1 & 0x400000) && + if ((player->stateFlags1 & PLAYER_STATE1_SHIELDING) && ((s16)((player->actor.shape.rot.y - this->actor.shape.rot.y) + 0x8000) < 0x2000) && ((s16)((player->actor.shape.rot.y - this->actor.shape.rot.y) + 0x8000) > -0x2000)) { Math_ApproachF(&this->targetPos.x, player->bodyPartsPos[15].x, 1.0f, 400.0f); @@ -4799,7 +4799,7 @@ void BossTw_UpdateEffects(PlayState* play) { if (eff->workf[EFF_SCALE] == 0.0f) { eff->type = TWEFF_NONE; if (eff->target == NULL) { - player->stateFlags2 &= ~0x8000; + player->stateFlags2 &= ~PLAYER_STATE2_PAUSE_MOST_UPDATING; sFreezeState = 0; } } @@ -4815,9 +4815,9 @@ void BossTw_UpdateEffects(PlayState* play) { if (eff->workf[EFF_ROLL] >= 0.8f) { eff->workf[EFF_ROLL] -= 0.8f; - player->stateFlags2 |= 0x8000; + player->stateFlags2 |= PLAYER_STATE2_PAUSE_MOST_UPDATING; } else { - player->stateFlags2 &= ~0x8000; + player->stateFlags2 &= ~PLAYER_STATE2_PAUSE_MOST_UPDATING; } if ((sKotakePtr->workf[UNK_F11] > 10.0f) && (sKotakePtr->workf[UNK_F11] < 200.0f)) { diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index ee62b141e..4891b0330 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -1441,14 +1441,14 @@ void BossVa_BodyPhase4(BossVa* this, PlayState* play) { } else { Math_SmoothStepToS(&this->vaBodySpinRate, 0, 1, 0x96, 0); if (this->timer > 0) { - if ((player->stateFlags1 & 0x4000000) && (this->timer > 35)) { + if ((player->stateFlags1 & PLAYER_STATE1_DAMAGED) && (this->timer > 35)) { this->timer = 35; } Math_SmoothStepToF(&this->actor.shape.yOffset, -480.0f, 1.0f, 30.0f, 0.0f); this->colliderBody.info.bumper.dmgFlags = 0xFC00712; this->timer--; } else { - if ((player->stateFlags1 & 0x4000000) && (this->timer < -60)) { + if ((player->stateFlags1 & PLAYER_STATE1_DAMAGED) && (this->timer < -60)) { this->timer = -59; } if ((play->gameplayFrames % 4) == 0) { @@ -2024,7 +2024,7 @@ void BossVa_ZapperAttack(BossVa* this, PlayState* play) { sp98 = Math_Vec3f_Yaw(&sp7C, &this->armTip); tmp17 = sp98 - this->actor.shape.rot.y; - if ((sp8E >= ABS(tmp17) || this->burst) && !(sBodyState & 0x80) && !(player->stateFlags1 & 0x04000000)) { + if ((sp8E >= ABS(tmp17) || this->burst) && !(sBodyState & 0x80) && !(player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { if (!this->burst) { sp94 = sp98 - this->actor.shape.rot.y; @@ -2086,7 +2086,7 @@ void BossVa_ZapperAttack(BossVa* this, PlayState* play) { this->timer2 = 0; } - if ((this->timer2 < 0) && (player->stateFlags1 & 0x4000000)) { + if ((this->timer2 < 0) && (player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { BossVa_Spark(play, this, 1, 30, 0.0f, 0.0f, SPARK_LINK, 0.0f, true); } } @@ -2287,7 +2287,7 @@ void BossVa_ZapperEnraged(BossVa* this, PlayState* play) { sp6C = Math_Vec3f_Yaw(&sp54, &this->armTip); tmp16 = sp6C - this->actor.shape.rot.y; - if ((ABS(tmp16) <= 0x4650 || this->burst) && !(sBodyState & 0x80) && !(player->stateFlags1 & 0x04000000)) { + if ((ABS(tmp16) <= 0x4650 || this->burst) && !(sBodyState & 0x80) && !(player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { if (!this->burst) { sp68 = sp6C - this->actor.shape.rot.y; @@ -2344,7 +2344,7 @@ void BossVa_ZapperEnraged(BossVa* this, PlayState* play) { this->timer2 = 0; } - if ((this->timer2 < 0) && (player->stateFlags1 & 0x4000000)) { + if ((this->timer2 < 0) && (player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { BossVa_Spark(play, this, 1, 30, 0.0f, 0, SPARK_LINK, 0.0f, true); } } diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index f3c601fa1..bbd9b2826 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -134,7 +134,7 @@ void DoorAna_WaitOpen(DoorAna* this, PlayState* play) { player = GET_PLAYER(play); if (Math_StepToF(&this->actor.scale.x, 0.01f, 0.001f)) { - if ((this->actor.targetMode != 0) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (player->stateFlags1 & 0x80000000) && + if ((this->actor.targetMode != 0) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (player->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED) && (player->unk_84F == 0)) { destinationIdx = ((this->actor.params >> 0xC) & 7) - 1; Play_SetupRespawnPoint(play, RESPAWN_MODE_RETURN, 0x4FF); @@ -153,10 +153,10 @@ void DoorAna_WaitOpen(DoorAna* this, PlayState* play) { DoorAna_SetupAction(this, DoorAna_GrabPlayer); } else { - if (!Player_InCsMode(play) && !(player->stateFlags1 & 0x8800000) && + if (!Player_InCsMode(play) && !(player->stateFlags1 & (PLAYER_STATE1_ON_HORSE | PLAYER_STATE1_IN_WATER)) && this->actor.xzDistToPlayer <= 15.0f && -50.0f <= this->actor.yDistToPlayer && this->actor.yDistToPlayer <= 15.0f) { - player->stateFlags1 |= 0x80000000; + player->stateFlags1 |= PLAYER_STATE1_FLOOR_DISABLED; this->actor.targetMode = 1; } else { this->actor.targetMode = 0; diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index 290e809f6..c61822f67 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -553,7 +553,7 @@ void func_80997220(DoorShutter* this, PlayState* play) { } this->unk_164 = 0; this->dyna.actor.velocity.y = 0.0f; - if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & 0x800)) { + if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { DoorShutter_SetupAction(this, func_80997568); func_8002DF54(play, NULL, 2); } @@ -637,7 +637,7 @@ void DoorShutter_Update(Actor* thisx, PlayState* play) { DoorShutter* this = (DoorShutter*)thisx; Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x100004C0) || (this->actionFunc == DoorShutter_SetupType)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_IN_ITEM_CS)) || (this->actionFunc == DoorShutter_SetupType)) { this->actionFunc(this, play); } } diff --git a/soh/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c b/soh/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c index 56a761c84..a81ed473a 100644 --- a/soh/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c +++ b/soh/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c @@ -180,7 +180,7 @@ void EffDust_UpdateFunc_8099DFC0(EffDust* this, PlayState* play) { s32 i; s32 j; - if (parent == NULL || parent->update == NULL || !(player->stateFlags1 & 0x1000)) { + if (parent == NULL || parent->update == NULL || !(player->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK)) { if (this->life != 0) { this->life -= 1; } else { diff --git a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c index c5ca6686a..8347c631a 100644 --- a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c +++ b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c @@ -694,7 +694,7 @@ void EnAm_Statue(EnAm* this, PlayState* play) { ((this->hurtCollider.base.ocFlags1 & OC1_HIT) && (ABS(moveDir) <= 0x2000))) { this->unk_258 = 0; - player->stateFlags2 &= ~0x151; + player->stateFlags2 &= ~(PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_MOVING_DYNAPOLY | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY); player->actor.speedXZ = 0.0f; this->dyna.unk_150 = this->dyna.unk_154 = 0.0f; } diff --git a/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c b/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c index 9686965d5..04b09aca8 100644 --- a/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c +++ b/soh/src/overlays/actors/ovl_En_Ba/z_en_ba.c @@ -188,7 +188,7 @@ void EnBa_Idle(EnBa* this, PlayState* play) { } this->unk_2A8[13].x = this->unk_2A8[12].x; this->unk_2A8[13].y = this->unk_2A8[12].y; - if (!(player->stateFlags1 & 0x4000000) && (this->actor.xzDistToPlayer <= 175.0f) && + if (!(player->stateFlags1 & PLAYER_STATE1_DAMAGED) && (this->actor.xzDistToPlayer <= 175.0f) && (this->actor.world.pos.y == this->actor.home.pos.y + 100.0f)) { EnBa_SetupSwingAtPlayer(this); } @@ -294,7 +294,7 @@ void EnBa_SwingAtPlayer(EnBa* this, PlayState* play) { Matrix_MultVec3f(&D_809B8080, &this->unk_158[i + 1]); } this->unk_31A--; - } else if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & 0x4000000)) { + } else if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { EnBa_SetupIdle(this); } else { EnBa_SetupSwingAtPlayer(this); @@ -313,7 +313,7 @@ void EnBa_SwingAtPlayer(EnBa* this, PlayState* play) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); return; } - if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & 0x4000000)) { + if ((this->actor.xzDistToPlayer > 175.0f) || (player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { EnBa_SetupIdle(this); } else { EnBa_SetupSwingAtPlayer(this); diff --git a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c index fafb55ca5..816dcf091 100644 --- a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c +++ b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c @@ -84,7 +84,7 @@ void EnBlkobj_Wait(EnBlkobj* this, PlayState* play) { if (this->dyna.actor.xzDistToPlayer < 120.0f) { EnBlkobj_SetupAction(this, EnBlkobj_SpawnDarkLink); } - player->stateFlags2 |= 0x04000000; + player->stateFlags2 |= PLAYER_STATE2_REFLECTION; } void EnBlkobj_SpawnDarkLink(EnBlkobj* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 40adc1a6f..7fee4b178 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -238,11 +238,11 @@ void EnBom_Explode(EnBom* this, PlayState* play) { if (this->timer == 0) { player = GET_PLAYER(play); - if ((player->stateFlags1 & 0x800) && (player->heldActor == &this->actor)) { + if ((player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (player->heldActor == &this->actor)) { player->actor.child = NULL; player->heldActor = NULL; player->interactRangeActor = NULL; - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; } Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index a6d3afda5..5c18c52fa 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -200,14 +200,14 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { } } - player->stateFlags1 &= ~0x20000000; + player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; this->actor.parent = NULL; if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } - player->stateFlags1 |= 0x20000000; + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->actionFunc = EnBomBowlPit_WaitTillPrizeGiven; } diff --git a/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c b/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c index 13b02c79c..2eecc1fb3 100644 --- a/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c +++ b/soh/src/overlays/actors/ovl_En_Bombf/z_en_bombf.c @@ -164,7 +164,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { player->heldActor = NULL; player->interactRangeActor = NULL; this->actor.parent = NULL; - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; } } else if (this->bombCollider.base.acFlags & AC_HIT) { this->bombCollider.base.acFlags &= ~AC_HIT; @@ -200,7 +200,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { player->heldActor = NULL; player->interactRangeActor = NULL; this->actor.parent = NULL; - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; this->actor.world.pos = this->actor.home.pos; } } @@ -218,7 +218,7 @@ void EnBombf_GrowBomb(EnBombf* this, PlayState* play) { player->heldActor = NULL; player->interactRangeActor = NULL; this->actor.parent = NULL; - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; this->actor.world.pos = this->actor.home.pos; } } @@ -302,11 +302,11 @@ void EnBombf_Explode(EnBombf* this, PlayState* play) { if (this->timer == 0) { player = GET_PLAYER(play); - if ((player->stateFlags1 & 0x800) && (player->heldActor == &this->actor)) { + if ((player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (player->heldActor == &this->actor)) { player->actor.child = NULL; player->heldActor = NULL; player->interactRangeActor = NULL; - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; } Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Boom/z_en_boom.c b/soh/src/overlays/actors/ovl_En_Boom/z_en_boom.c index dedb53d5b..d5e082933 100644 --- a/soh/src/overlays/actors/ovl_En_Boom/z_en_boom.c +++ b/soh/src/overlays/actors/ovl_En_Boom/z_en_boom.c @@ -243,7 +243,7 @@ void EnBoom_Update(Actor* thisx, PlayState* play) { EnBoom* this = (EnBoom*)thisx; Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x20000000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE)) { this->actionFunc(this, play); Actor_SetFocus(&this->actor, 0.0f); this->activeTimer = this->activeTimer + 1; diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index a4d86ff61..6bbb48488 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -320,8 +320,8 @@ void func_809C9700(EnBox* this, PlayState* play) { this->unk_1FB = ENBOX_STATE_0; } else { if (this->unk_1FB == ENBOX_STATE_0) { - if (!(player->stateFlags2 & 0x1000000)) { - player->stateFlags2 |= 0x800000; + if (!(player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR)) { + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; return; } this->unk_1FB = ENBOX_STATE_1; diff --git a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c index a57594a0f..2a6fdb4fd 100644 --- a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c +++ b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c @@ -359,7 +359,7 @@ void func_809CEA24(EnBw* this, PlayState* play) { Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_236 + this->unk_238, 1, this->actor.speedXZ * 1000.0f, 0); } - if ((this->unk_224 == 0) || (ABS(this->actor.yDistToPlayer) > 60.0f) || (player2->stateFlags1 & 0x6000)) { + if ((this->unk_224 == 0) || (ABS(this->actor.yDistToPlayer) > 60.0f) || (player2->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE))) { this->unk_221 = 3; this->unk_224 = 150; this->unk_250 = 0.0f; diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index 24650142d..cbbba524d 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -281,7 +281,7 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { if (this->timer != 0) { this->timer--; } - if ((this->timer == 0) && (this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & 0x00800000) && + if ((this->timer == 0) && (this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->actor.yDistToWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL)) { EnCrow_SetupDiveAttack(this); } @@ -319,7 +319,7 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || (this->collider.base.atFlags & AT_HIT) || (this->actor.bgCheckFlags & 9) || - (player->stateFlags1 & 0x00800000) || (this->actor.yDistToWater > -40.0f)) { + (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->actor.yDistToWater > -40.0f)) { if (this->collider.base.atFlags & AT_HIT) { this->collider.base.atFlags &= ~AT_HIT; Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_ATTACK); diff --git a/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c b/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c index 4f58b1937..893f326d8 100644 --- a/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c +++ b/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c @@ -230,7 +230,7 @@ void EnDha_Wait(EnDha* this, PlayState* play) { this->timer += 0x1194; this->limbAngleY = Math_SinS(this->timer) * 1820.0f; - if (!(player->stateFlags2 & 0x80)) { + if (!(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { this->unk_1CC = 0; EnDha_SetupTakeDamage(this); return; @@ -245,8 +245,8 @@ void EnDha_Wait(EnDha* this, PlayState* play) { this->handAngle.y -= this->actor.shape.rot.y + this->limbAngleY; this->handAngle.x -= this->actor.shape.rot.x + this->limbAngleX[0] + this->limbAngleX[1]; } else { - if ((player->stateFlags2 & 0x80) && (&this->actor == player->actor.parent)) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; } @@ -285,8 +285,8 @@ void EnDha_Wait(EnDha* this, PlayState* play) { this->limbAngleX[1] *= -2; } } else { - if ((player->stateFlags2 & 0x80) && (&this->actor == player->actor.parent)) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; } @@ -306,8 +306,8 @@ void EnDha_SetupTakeDamage(EnDha* this) { void EnDha_TakeDamage(EnDha* this, PlayState* play) { Player* player = GET_PLAYER(play); - if ((player->stateFlags2 & 0x80) && (&this->actor == player->actor.parent)) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; } @@ -344,8 +344,8 @@ void EnDha_Die(EnDha* this, PlayState* play) { Vec3f vec; Player* player = GET_PLAYER(play); - if ((player->stateFlags2 & 0x80) && (&this->actor == player->actor.parent)) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; } diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 0dd33a8ac..cf73c6a94 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -460,7 +460,7 @@ void func_809EFF50(EnDns* this, PlayState* play) { void func_809EFF98(EnDns* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags1 & 0x400) { + if (player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { this->dnsItemEntry->setRupeesAndFlags(this); this->dropCollectible = 1; diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c index 9ce27f4c1..2864544c5 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c @@ -123,7 +123,7 @@ void EnDntJiji_Wait(EnDntJiji* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->timer == 1) && (this->actor.xzDistToPlayer < 150.0f) && !Play_InCsMode(play) && - !(player->stateFlags1 & 0x800)) { + !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { OnePointCutscene_Init(play, 2230, -99, &this->actor, MAIN_CAM); this->timer = 0; func_8002DF54(play, NULL, 8); diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c index 329462c06..2a571e34e 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c @@ -198,7 +198,7 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) { if (this->playerIsOpening != 0) { this->actionFunc = EnDoor_Open; Animation_PlayOnceSetSpeed(&this->skelAnime, D_809FCECC[this->animStyle], - (player->stateFlags1 & 0x8000000) ? 0.75f : 1.5f); + (player->stateFlags1 & PLAYER_STATE1_IN_WATER) ? 0.75f : 1.5f); if (this->lockTimer != 0) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--; Flags_SetSwitch(play, this->actor.params & 0x3F); diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index db13ecc54..19af8a4c5 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -353,9 +353,9 @@ void func_809FE3B4(EnDu* this, PlayState* play) { void func_809FE3C0(EnDu* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { func_8010BD88(play, OCARINA_ACTION_CHECK_SARIA); - player->stateFlags2 |= 0x2000000; + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; player->unk_6A8 = &this->actor; EnDu_SetupAction(this, func_809FE4A4); return; @@ -365,7 +365,7 @@ void func_809FE3C0(EnDu* this, PlayState* play) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } if (this->actor.xzDistToPlayer < 116.0f + this->collider.dim.radius) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } @@ -393,14 +393,14 @@ void func_809FE4A4(EnDu* this, PlayState* play) { EnDu_SetupAction(this, func_809FE890); play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } void func_809FE638(EnDu* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (!(player->stateFlags1 & 0x20000000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE)) { OnePointCutscene_Init(play, 3330, -99, &this->actor, MAIN_CAM); player->actor.shape.rot.y = player->actor.world.rot.y = this->actor.world.rot.y + 0x7FFF; Audio_PlayFanfare(NA_BGM_APPEAR); diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 2191daeab..f996fe6c1 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1097,13 +1097,13 @@ void func_80A0461C(EnElf* this, PlayState* play) { } else { arrowPointedActor = play->actorCtx.targetCtx.arrowPointedActor; - if ((player->stateFlags1 & 0x400) || ((YREG(15) & 0x10) && func_800BC56C(play, 2))) { + if ((player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) || ((YREG(15) & 0x10) && func_800BC56C(play, 2))) { temp = 12; this->unk_2C0 = 100; } else if (arrowPointedActor == NULL || arrowPointedActor->category == ACTORCAT_NPC) { if (arrowPointedActor != NULL) { this->unk_2C0 = 100; - player->stateFlags2 |= 0x100000; + player->stateFlags2 |= PLAYER_STATE2_NAVI_OUT; temp = 0; } else { switch (this->unk_2A8) { @@ -1124,7 +1124,7 @@ void func_80A0461C(EnElf* this, PlayState* play) { this->unk_2AE--; temp = 7; } else { - player->stateFlags2 |= 0x100000; + player->stateFlags2 |= PLAYER_STATE2_NAVI_OUT; temp = 0; } } else { @@ -1154,7 +1154,7 @@ void func_80A0461C(EnElf* this, PlayState* play) { switch (temp) { case 0: - if (!(player->stateFlags2 & 0x100000)) { + if (!(player->stateFlags2 & PLAYER_STATE2_NAVI_OUT)) { temp = 7; if (this->unk_2C7 == 0) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_NAVY_VANISH); @@ -1162,7 +1162,7 @@ void func_80A0461C(EnElf* this, PlayState* play) { } break; case 8: - if (player->stateFlags2 & 0x100000) { + if (player->stateFlags2 & PLAYER_STATE2_NAVI_OUT) { func_80A0299C(this, 0x32); this->unk_2C0 = 42; temp = 11; @@ -1172,10 +1172,10 @@ void func_80A0461C(EnElf* this, PlayState* play) { } break; case 7: - player->stateFlags2 &= ~0x100000; + player->stateFlags2 &= ~PLAYER_STATE2_NAVI_OUT; break; default: - player->stateFlags2 |= 0x100000; + player->stateFlags2 |= PLAYER_STATE2_NAVI_OUT; break; } } @@ -1514,7 +1514,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) { Player* player = GET_PLAYER(play); if ((this->unk_2A8 != 8) && !(this->fairyFlags & 8)) { - if (!(player->stateFlags1 & 0x100000) || (kREG(90) < this->actor.projectedPos.z)) { + if (!(player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) || (kREG(90) < this->actor.projectedPos.z)) { dListHead = Graph_Alloc(play->state.gfxCtx, sizeof(Gfx) * 4); OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c index 48877526a..a43dd8679 100644 --- a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c +++ b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c @@ -249,7 +249,7 @@ void EnEncount1_SpawnStalchildOrWolfos(EnEncount1* this, PlayState* play) { (CVarGetInteger("gRandomizedEnemies", 0) && enemyCount < 15)) { if (play->sceneNum == SCENE_HYRULE_FIELD) { if ((player->floorSfxOffset == 0) || (player->actor.floorBgId != BGCHECK_SCENE) || - !(player->actor.bgCheckFlags & 1) || (player->stateFlags1 & 0x08000000)) { + !(player->actor.bgCheckFlags & 1) || (player->stateFlags1 & PLAYER_STATE1_IN_WATER)) { this->fieldSpawnTimer = 60; break; diff --git a/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c b/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c index fbdfbc7f7..aa52d53ae 100644 --- a/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c +++ b/soh/src/overlays/actors/ovl_En_Fire_Rock/z_en_fire_rock.c @@ -362,7 +362,7 @@ void EnFireRock_Update(Actor* thisx, PlayState* play) { if (this->collider.base.atFlags & 2) { this->collider.base.atFlags &= ~2; if (this->collider.base.at == playerActor) { - if (!(player->stateFlags1 & 0x04000000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_DAMAGED)) { func_8002F758(play, thisx, 2.0f, -player->actor.world.rot.y, 3.0f, 4); } return; diff --git a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c index 59136cee2..1a906e5b7 100644 --- a/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c +++ b/soh/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c @@ -797,7 +797,7 @@ void EnFloormas_GrabLink(EnFloormas* this, PlayState* play) { this->actor.world.pos.z = Math_CosS(this->actor.shape.rot.y) * (xzDelta * 0.1f) + player->actor.world.pos.z; // let go - if (!(player->stateFlags2 & 0x80) || (player->invincibilityTimer < 0)) { + if (!(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) || (player->invincibilityTimer < 0)) { parent = (EnFloormas*)this->actor.parent; child = (EnFloormas*)this->actor.child; diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 11a7eb026..3cb02e441 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -606,7 +606,7 @@ s32 EnFr_SetupJumpingUp(EnFr* this, s32 frogIndex) { void EnFr_Idle(EnFr* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags2 & 0x2000000) { + if (player->stateFlags2 & PLAYER_STATE2_PLAY_FOR_ACTOR) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) { play->msgCtx.ocarinaMode = OCARINA_MODE_00; } diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 278fb18e2..67ad97c96 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -208,17 +208,17 @@ void func_80A1DBD4(EnFu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_00; Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_02) { - player->stateFlags2 &= ~0x1000000; + player->stateFlags2 &= ~PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR; this->actionFunc = EnFu_WaitAdult; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } void EnFu_WaitForPlayback(EnFu* this, PlayState* play) { Player* player = GET_PLAYER(play); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; // if dialog state is 7, player has played back the song if (Message_GetState(&play->msgCtx) == TEXT_STATE_SONG_DEMO_DONE) { func_8010BD58(play, OCARINA_ACTION_PLAYBACK_STORMS); @@ -229,7 +229,7 @@ void EnFu_WaitForPlayback(EnFu* this, PlayState* play) { void EnFu_TeachSong(EnFu* this, PlayState* play) { Player* player = GET_PLAYER(play); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; // if dialog state is 2, start song demonstration if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { this->behaviorFlags &= ~FU_WAIT; @@ -246,7 +246,7 @@ void EnFu_WaitAdult(EnFu* this, PlayState* play) { yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; if ((Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS))) { func_80A1D94C(this, play, 0x508E, func_80A1DBA0); - } else if (player->stateFlags2 & 0x1000000) { + } else if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { this->actor.textId = 0x5035; Message_StartTextbox(play, this->actor.textId, NULL); this->actionFunc = IS_RANDO ? func_80A1DBD4 : EnFu_TeachSong; @@ -257,7 +257,7 @@ void EnFu_WaitAdult(EnFu* this, PlayState* play) { if (this->actor.xzDistToPlayer < 100.0f) { this->actor.textId = 0x5034; func_8002F2CC(&this->actor, play, 100.0f); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 1ad8f4867..92a768205 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -661,7 +661,7 @@ void EnGe1_BeginGame_Archery(EnGe1* this, PlayState* play) { gSaveContext.eventInf[0] |= 0x100; Flags_SetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY); - if (!(player->stateFlags1 & 0x800000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { func_8002DF54(play, &this->actor, 1); } else { horse = Actor_FindNearby(play, &player->actor, ACTOR_EN_HORSE, ACTORCAT_BG, 1200.0f); @@ -741,7 +741,7 @@ void EnGe1_Wait_Archery(EnGe1* this, PlayState* play) { Player* player = GET_PLAYER(play); u16 textId; - if (!(player->stateFlags1 & 0x800000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { EnGe1_SetTalkAction(this, play, 0x603F, 100.0f, EnGe1_TalkNoHorse_Archery); } else { if (Flags_GetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY)) { diff --git a/soh/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c b/soh/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c index c61ac7de1..432116b2d 100644 --- a/soh/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c +++ b/soh/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c @@ -725,7 +725,7 @@ void EnGoroiwa_Update(Actor* thisx, PlayState* play) { s32 pad; s32 sp30; - if (!(player->stateFlags1 & 0x300000C0)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE))) { if (this->collisionDisabledTimer > 0) { this->collisionDisabledTimer--; } diff --git a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c index e2a4cdaa0..159774406 100644 --- a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c +++ b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c @@ -144,8 +144,8 @@ void func_80A4E470(EnGs* this, PlayState* play) { if (this->actor.xzDistToPlayer <= 100.0f) { bREG(15) = 1; if (this->unk_19D == 0) { - player->stateFlags2 |= 0x800000; - if (player->stateFlags2 & 0x1000000) { + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { func_8010BD58(play, OCARINA_ACTION_FREE_PLAY); this->unk_19D |= 1; } @@ -168,7 +168,7 @@ void func_80A4E470(EnGs* this, PlayState* play) { this->unk_19D = 0; Flags_SetSwitch(play, (this->actor.params >> 8) & 0x3F); } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index d8192be6c..f653b6ff9 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -724,7 +724,7 @@ void EnHorse_ResetRace(EnHorse* this, PlayState* play) { s32 EnHorse_PlayerCanMove(EnHorse* this, PlayState* play) { Player* player = GET_PLAYER(play); - if ((player->stateFlags1 & 1) || func_8002DD78(GET_PLAYER(play)) == 1 || (player->stateFlags1 & 0x100000) || + if ((player->stateFlags1 & PLAYER_STATE1_LOADING) || func_8002DD78(GET_PLAYER(play)) == 1 || (player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) || ((this->stateFlags & ENHORSE_FLAG_19) && !this->inRace) || this->action == ENHORSE_ACT_HBA || player->actor.flags & ACTOR_FLAG_PLAYER_TALKED_TO || play->csCtx.state != 0) { return false; @@ -3533,7 +3533,7 @@ void EnHorse_Update(Actor* thisx, PlayState* play2) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->cyl1.base); CollisionCheck_SetOC(play, &play->colChkCtx, &this->cyl1.base); CollisionCheck_SetOC(play, &play->colChkCtx, &this->cyl2.base); - if ((player->stateFlags1 & 1) && player->rideActor != NULL) { + if ((player->stateFlags1 & PLAYER_STATE1_LOADING) && player->rideActor != NULL) { if (play->sceneNum != SCENE_LON_LON_RANCH || (play->sceneNum == SCENE_LON_LON_RANCH && (thisx->world.pos.z < -2400.0f))) { EnHorse_UpdateConveyors(this, play); diff --git a/soh/src/overlays/actors/ovl_En_In/z_en_in.c b/soh/src/overlays/actors/ovl_En_In/z_en_in.c index dd8b52fcc..1d0866e6d 100644 --- a/soh/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/soh/src/overlays/actors/ovl_En_In/z_en_in.c @@ -145,7 +145,7 @@ u16 func_80A79010(PlayState* play) { } switch (gSaveContext.eventInf[0] & 0xF) { case 1: - if (!(player->stateFlags1 & 0x800000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { return 0x2036; } else if (Flags_GetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO)) { if (Flags_GetInfTable(INFTABLE_A2)) { @@ -657,7 +657,7 @@ void func_80A7A568(EnIn* this, PlayState* play) { s32 phi_a2; s32 transitionType; - if (!Flags_GetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO) && (player->stateFlags1 & 0x800000)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO) && (player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { Flags_SetInfTable(INFTABLE_AB); } if (gSaveContext.timer1State == 10) { diff --git a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c index 8c3104e9b..cf2f4499b 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c @@ -213,18 +213,18 @@ void func_80A8F75C(EnKakasi* this, PlayState* play) { if (absyawTowardsPlayer < 0x4300) { if (!this->unk_194) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { this->camId = OnePointCutscene_Init(play, 2260, -99, &this->actor, MAIN_CAM); func_8010BD58(play, OCARINA_ACTION_SCARECROW_LONG_RECORDING); this->unk_19A = 0; this->unk_1B8 = 0.0; - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; this->actionFunc = func_80A8F8D0; return; } if (this->actor.xzDistToPlayer < 80.0f) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } func_8002F2CC(&this->actor, play, 100.0f); @@ -253,7 +253,7 @@ void func_80A8F8D0(EnKakasi* this, PlayState* play) { } } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { func_80A8F320(this, play, 0); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c index bc2fb7632..37b6236a5 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c @@ -232,33 +232,33 @@ void func_80A91348(EnKakasi3* this, PlayState* play) { if (absAngleTowardsLink < 0x4300) { if (!this->unk_194) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { this->camId = OnePointCutscene_Init(play, 2260, -99, &this->actor, MAIN_CAM); play->msgCtx.msgMode = MSGMODE_PAUSED; this->dialogState = TEXT_STATE_EVENT; this->unk_1B8 = 0.0f; Message_StartTextbox(play, 0x40A4, NULL); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; this->actionFunc = func_80A915B8; return; } if (this->actor.xzDistToPlayer < 80.0f) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } else if (gSaveContext.scarecrowSpawnSongSet && !this->unk_195) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { this->camId = OnePointCutscene_Init(play, 2260, -99, &this->actor, MAIN_CAM); play->msgCtx.msgMode = MSGMODE_PAUSED; this->dialogState = TEXT_STATE_EVENT; this->unk_1B8 = 0.0f; Message_StartTextbox(play, 0x40A8, NULL); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; this->actionFunc = func_80A9187C; return; } if (this->actor.xzDistToPlayer < 80.0f) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } func_8002F2CC(&this->actor, play, 100.0f); @@ -303,7 +303,7 @@ void func_80A91620(EnKakasi3* this, PlayState* play) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { func_80A90EBC(this, play, 0); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } @@ -377,7 +377,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { func_80A90EBC(this, play, 0); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } diff --git a/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c index 6f8624518..00cfb3555 100644 --- a/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c +++ b/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c @@ -84,7 +84,7 @@ void EnMThunder_Init(Actor* thisx, PlayState* play2) { Actor_SetScale(&this->actor, 0.1f); this->unk_1CA = 0; - if (player->stateFlags2 & 0x20000) { + if (player->stateFlags2 & PLAYER_STATE2_SPIN_ATTACKING) { if (!gSaveContext.isMagicAcquired || (gSaveContext.magicState != MAGIC_STATE_IDLE) || (((this->actor.params & 0xFF00) >> 8) && !(Magic_RequestChange(play, (this->actor.params & 0xFF00) >> 8, MAGIC_CONSUME_NOW)))) { @@ -96,7 +96,7 @@ void EnMThunder_Init(Actor* thisx, PlayState* play2) { return; } - player->stateFlags2 &= ~0x20000; + player->stateFlags2 &= ~PLAYER_STATE2_SPIN_ATTACKING; this->unk_1CA = 1; this->collider.info.toucher.dmgFlags = D_80AA044C[this->unk_1C7]; this->unk_1C6 = 1; @@ -131,7 +131,7 @@ void func_80A9F314(PlayState* play, f32 arg1) { void func_80A9F350(EnMThunder* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags2 & 0x20000) { + if (player->stateFlags2 & PLAYER_STATE2_SPIN_ATTACKING) { if (player->meleeWeaponAnimation >= 0x18) { Audio_PlaySoundGeneral(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -143,7 +143,7 @@ void func_80A9F350(EnMThunder* this, PlayState* play) { return; } - if (!(player->stateFlags1 & 0x1000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK)) { Actor_Kill(&this->actor); } } @@ -176,7 +176,7 @@ void func_80A9F408(EnMThunder* this, PlayState* play) { func_800AA000(0.0f, (s32)(player->unk_858 * 150.0f) & 0xFF, 2, (s32)(player->unk_858 * 150.0f) & 0xFF); } - if (player->stateFlags2 & 0x20000) { + if (player->stateFlags2 & PLAYER_STATE2_SPIN_ATTACKING) { if ((child != NULL) && (child->update != NULL)) { child->parent = NULL; } @@ -191,7 +191,7 @@ void func_80A9F408(EnMThunder* this, PlayState* play) { Actor_Kill(&this->actor); return; } else { - player->stateFlags2 &= ~0x20000; + player->stateFlags2 &= ~PLAYER_STATE2_SPIN_ATTACKING; if ((this->actor.params & 0xFF00) >> 8) { gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP; } @@ -214,7 +214,7 @@ void func_80A9F408(EnMThunder* this, PlayState* play) { } } - if (!(player->stateFlags1 & 0x1000)) { + if (!(player->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK)) { if (this->actor.child != NULL) { this->actor.child->parent = NULL; } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 8a11eb668..606bca3b8 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -420,8 +420,8 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) { // When the player pulls out the Ocarina while close to Malon - if (player->stateFlags2 & 0x1000000) { - player->stateFlags2 |= 0x2000000; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; player->unk_6A8 = &this->actor; this->actor.textId = 0x2061; Message_StartTextbox(play, this->actor.textId, NULL); @@ -432,7 +432,7 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { } else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) { // somehow flags that the player is close to malon so that pulling out the Ocarina // triggers the code above this. - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } // If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina // in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory. @@ -444,7 +444,7 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { } void func_80AA106C(EnMa1* this, PlayState* play) { - GET_PLAYER(play)->stateFlags2 |= 0x800000; + GET_PLAYER(play)->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { Audio_OcaSetInstrument(2); func_8010BD58(play, OCARINA_ACTION_TEACH_EPONA); @@ -454,7 +454,7 @@ void func_80AA106C(EnMa1* this, PlayState* play) { } void func_80AA10EC(EnMa1* this, PlayState* play) { - GET_PLAYER(play)->stateFlags2 |= 0x800000; + GET_PLAYER(play)->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; if (Message_GetState(&play->msgCtx) == TEXT_STATE_SONG_DEMO_DONE) { func_8010BD58(play, OCARINA_ACTION_PLAYBACK_EPONA); this->actionFunc = func_80AA1150; @@ -481,7 +481,7 @@ void EnMa1_EndTeachSong(EnMa1* this, PlayState* play) { } void func_80AA1150(EnMa1* this, PlayState* play) { - GET_PLAYER(play)->stateFlags2 |= 0x800000; + GET_PLAYER(play)->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; // When rando'ed, trigger the "song learned" Ocarina mode. if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) { diff --git a/soh/src/overlays/actors/ovl_En_Ma2/z_en_ma2.c b/soh/src/overlays/actors/ovl_En_Ma2/z_en_ma2.c index dc50b0e0e..1519e57c7 100644 --- a/soh/src/overlays/actors/ovl_En_Ma2/z_en_ma2.c +++ b/soh/src/overlays/actors/ovl_En_Ma2/z_en_ma2.c @@ -265,13 +265,13 @@ void func_80AA2018(EnMa2* this, PlayState* play) { void func_80AA204C(EnMa2* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { player->unk_6A8 = &this->actor; - player->stateFlags2 |= 0x2000000; + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; func_8010BD58(play, OCARINA_ACTION_CHECK_EPONA); this->actionFunc = func_80AA20E4; } else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } @@ -288,7 +288,7 @@ void func_80AA20E4(EnMa2* this, PlayState* play) { this->actionFunc = func_80AA21C8; play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } @@ -296,7 +296,7 @@ void func_80AA21C8(EnMa2* this, PlayState* play) { Player* player = GET_PLAYER(play); if (DECR(this->unk_208)) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } else { if (this->interactInfo.talkState == NPC_TALK_STATE_IDLE) { this->actor.flags |= ACTOR_FLAG_WILL_TALK; diff --git a/soh/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c b/soh/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c index 5280f583e..63c4f4da6 100644 --- a/soh/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c +++ b/soh/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c @@ -98,7 +98,7 @@ u16 func_80AA2AA0(PlayState* play, Actor* thisx) { return 0x2004; } } - if ((!(player->stateFlags1 & 0x800000)) && + if ((!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) && (Actor_FindNearby(play, thisx, ACTOR_EN_HORSE, 1, 1200.0f) == NULL)) { return 0x2001; } diff --git a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c index 59bee3ee5..6190e2db9 100644 --- a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c +++ b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c @@ -612,8 +612,8 @@ void EnMb_SetupStunned(EnMb* this) { void EnMb_Stunned(EnMb* this, PlayState* play) { Player* player = GET_PLAYER(play); - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); @@ -737,8 +737,8 @@ void EnMb_SpearPatrolEndCharge(EnMb* this, PlayState* play) { s16 relYawFromPlayer; s16 yawPlayerToWaypoint; - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); @@ -939,7 +939,7 @@ void EnMb_SpearPatrolPrepareAndCharge(EnMb* this, PlayState* play) { if (this->attackCollider.base.atFlags & AT_HIT) { if (this->attackCollider.base.at == &player->actor) { - if (!endCharge && !(player->stateFlags2 & 0x80)) { + if (!endCharge && !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { if (player->invincibilityTimer < 0) { if (player->invincibilityTimer < -39) { player->invincibilityTimer = 0; @@ -961,7 +961,7 @@ void EnMb_SpearPatrolPrepareAndCharge(EnMb* this, PlayState* play) { } } - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->actor.world.pos.x = this->actor.world.pos.x + Math_CosS(this->actor.shape.rot.y) * 10.0f + Math_SinS(this->actor.shape.rot.y) * 89.0f; hasHitPlayer = true; @@ -973,10 +973,10 @@ void EnMb_SpearPatrolPrepareAndCharge(EnMb* this, PlayState* play) { } if (endCharge) { - if (hasHitPlayer || (player->stateFlags2 & 0x80)) { + if (hasHitPlayer || (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { this->attackCollider.base.atFlags &= ~AT_HIT; - if (player->stateFlags2 & 0x80) { - player->stateFlags2 &= ~0x80; + if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); @@ -1008,7 +1008,7 @@ void EnMb_SpearPatrolImmediateCharge(EnMb* this, PlayState* play) { if (this->attackCollider.base.atFlags & AT_HIT) { if (this->attackCollider.base.at == &player->actor) { - if (!endCharge && !(player->stateFlags2 & 0x80)) { + if (!endCharge && !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { if (player->invincibilityTimer < 0) { if (player->invincibilityTimer <= -40) { player->invincibilityTimer = 0; @@ -1030,7 +1030,7 @@ void EnMb_SpearPatrolImmediateCharge(EnMb* this, PlayState* play) { } } - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->actor.world.pos.x = this->actor.world.pos.x + Math_CosS(this->actor.shape.rot.y) * 10.0f + Math_SinS(this->actor.shape.rot.y) * 89.0f; hasHitPlayer = true; @@ -1042,10 +1042,10 @@ void EnMb_SpearPatrolImmediateCharge(EnMb* this, PlayState* play) { } if (endCharge) { - if (hasHitPlayer || (player->stateFlags2 & 0x80)) { + if (hasHitPlayer || (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { this->attackCollider.base.atFlags &= ~AT_HIT; - if (player->stateFlags2 & 0x80) { - player->stateFlags2 &= ~0x80; + if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); @@ -1274,7 +1274,7 @@ void EnMb_ClubWaitPlayerNear(EnMb* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < this->playerDetectionRange && - !(player->stateFlags1 & 0x4000000) && ABS(relYawFromPlayer) < 0x3E80) { + !(player->stateFlags1 & PLAYER_STATE1_DAMAGED) && ABS(relYawFromPlayer) < 0x3E80) { // Add a height check to the Moblin's Club attack when Enemy Randomizer is on. // Without the height check, the Moblin will attack (and play the sound effect) a lot even though // the Moblin is very far away from the player in vertical rooms (like the first room in Deku Tree). @@ -1339,8 +1339,8 @@ void EnMb_SpearDead(EnMb* this, PlayState* play) { Math_SmoothStepToF(&this->actor.speedXZ, 0.0f, 1.0f, 0.5f, 0.0f); - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); @@ -1422,8 +1422,8 @@ void EnMb_CheckColliding(EnMb* this, PlayState* play) { this->hitbox.base.acFlags &= ~AC_HIT; if (this->actor.colChkInfo.damageEffect != ENMB_DMGEFF_IGNORE && this->actor.colChkInfo.damageEffect != ENMB_DMGEFF_FREEZE) { - if ((player->stateFlags2 & 0x80) && player->actor.parent == &this->actor) { - player->stateFlags2 &= ~0x80; + if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { + player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; player->unk_850 = 200; func_8002F71C(play, &this->actor, 6.0f, this->actor.world.rot.y, 6.0f); diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index 14d9cbb7b..9181b452b 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -774,8 +774,8 @@ void func_80AAB948(EnMd* this, PlayState* play) { } if ((this->interactInfo.talkState == NPC_TALK_STATE_IDLE) && (play->sceneNum == SCENE_LOST_WOODS)) { - if (player->stateFlags2 & 0x1000000) { - player->stateFlags2 |= 0x2000000; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; player->unk_6A8 = &this->actor; func_8010BD58(play, OCARINA_ACTION_CHECK_SARIA); this->actionFunc = func_80AABC10; @@ -783,7 +783,7 @@ void func_80AAB948(EnMd* this, PlayState* play) { } if (this->actor.xzDistToPlayer < (30.0f + this->collider.dim.radius)) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } @@ -802,7 +802,7 @@ void func_80AABC10(EnMd* this, PlayState* play) { this->actionFunc = func_80AAB948; play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index e5501858c..989b90c96 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -342,13 +342,13 @@ void EnMk_Update(Actor* thisx, PlayState* play) { player = GET_PLAYER(play); if (this->flags & 8) { - if (!(player->stateFlags2 & 0x400)) { + if (!(player->stateFlags2 & PLAYER_STATE2_UNDERWATER)) { this->flags &= ~8; } } else { if (player->currentBoots == PLAYER_BOOTS_IRON) { this->flags |= 8; - } else if (player->stateFlags2 & 0x400) { + } else if (player->stateFlags2 & PLAYER_STATE2_UNDERWATER) { swimFlag = player->actor.yDistToWater; if (swimFlag > 0) { diff --git a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c index d2500afaf..2add8c4a9 100644 --- a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c +++ b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c @@ -156,7 +156,7 @@ void EnNutsball_Update(Actor* thisx, PlayState* play) { Player* player = GET_PLAYER(play); s32 pad; - if (!(player->stateFlags1 & 0x300000C0) || (this->actionFunc == func_80ABBB34)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE)) || (this->actionFunc == func_80ABBB34)) { this->actionFunc(this, play); Actor_MoveForward(&this->actor); diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 74afaacff..8cb491da4 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -115,18 +115,18 @@ void func_80ABEF2C(EnOkarinaTag* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; } else { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { // "North! ! ! ! !" osSyncPrintf(VT_FGCOL(RED) "☆☆☆☆☆ 北!!!!! ☆☆☆☆☆ %f\n" VT_RST, this->actor.xzDistToPlayer); } if ((this->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) { - if (player->stateFlags2 & 0x2000000) { + if (player->stateFlags2 & PLAYER_STATE2_PLAY_FOR_ACTOR) { ocarinaSong = this->ocarinaSong; if (ocarinaSong == 6) { ocarinaSong = 0xA; } - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; func_8010BD58(play, ocarinaSong + OCARINA_ACTION_CHECK_SARIA); this->actionFunc = func_80ABF0CC; } else if ((this->actor.xzDistToPlayer < (50.0f + this->interactRange) && @@ -180,7 +180,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; this->actionFunc = func_80ABEF2C; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } @@ -196,7 +196,7 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { ((this->type != 6) || !Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) && (this->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { switch (this->type) { case 1: func_8010BD58(play, OCARINA_ACTION_CHECK_LULLABY); @@ -217,12 +217,12 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { Actor_Kill(&this->actor); break; } - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; this->actionFunc = func_80ABF4C8; } else if ((this->actor.xzDistToPlayer < (50.0f + this->interactRange)) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 40.0f)) { this->unk_15A = 0; - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } @@ -296,7 +296,7 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) { } } if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } } diff --git a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 017d1e9ae..9533e8309 100644 --- a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -629,7 +629,7 @@ void EnOkuta_Update(Actor* thisx, PlayState* play2) { Vec3f sp38; s32 sp34; - if (!(player->stateFlags1 & 0x300000C0)) { + if (!(player->stateFlags1 & (PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE))) { if (this->actor.params == 0) { EnOkuta_ColliderCheck(this, play); if (!WaterBox_GetSurfaceImpl(play, &play->colCtx, this->actor.world.pos.x, diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index b0d03430a..34ef24e40 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -678,7 +678,7 @@ void EnOssan_EndInteraction(PlayState* play, EnOssan* this) { Actor_ProcessTalkRequest(&this->actor, play); play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.stateTimer = 4; - player->stateFlags2 &= ~0x20000000; + player->stateFlags2 &= ~PLAYER_STATE2_DISABLE_DRAW; func_800BC490(play, 1); Interface_ChangeAlpha(50); this->drawCursor = 0; @@ -762,7 +762,7 @@ void EnOssan_State_Idle(EnOssan* this, PlayState* play, Player* player) { if (Actor_ProcessTalkRequest(&this->actor, play)) { // "Start conversation!!" osSyncPrintf(VT_FGCOL(YELLOW) "★★★ 会話開始!! ★★★" VT_RST "\n"); - player->stateFlags2 |= 0x20000000; + player->stateFlags2 |= PLAYER_STATE2_DISABLE_DRAW; func_800BC590(play); EnOssan_SetStateStartShopping(play, this, false); } else if (this->actor.xzDistToPlayer < 100.0f) { @@ -1403,7 +1403,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) { } play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.stateTimer = 4; - player->stateFlags2 &= ~0x20000000; + player->stateFlags2 &= ~PLAYER_STATE2_DISABLE_DRAW; func_800BC490(play, 1); Interface_ChangeAlpha(50); this->drawCursor = 0; @@ -1811,7 +1811,7 @@ void EnOssan_State_ContinueShoppingPrompt(EnOssan* this, PlayState* play, Player case 0: osSyncPrintf(VT_FGCOL(YELLOW) "★★★ 続けるよ!! ★★★" VT_RST "\n"); player->actor.shape.rot.y += 0x8000; - player->stateFlags2 |= 0x20000000; + player->stateFlags2 |= PLAYER_STATE2_DISABLE_DRAW; func_800BC490(play, 2); Message_StartTextbox(play, this->actor.textId, &this->actor); EnOssan_SetStateStartShopping(play, this, true); @@ -1830,7 +1830,7 @@ void EnOssan_State_ContinueShoppingPrompt(EnOssan* this, PlayState* play, Player selectedItem = this->shelfSlots[this->cursorIndex]; selectedItem->updateStockedItemFunc(play, selectedItem); player->actor.shape.rot.y += 0x8000; - player->stateFlags2 |= 0x20000000; + player->stateFlags2 |= PLAYER_STATE2_DISABLE_DRAW; func_800BC490(play, 2); Message_StartTextbox(play, this->actor.textId, &this->actor); EnOssan_SetStateStartShopping(play, this, true); diff --git a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c index c11feb327..3f109863c 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c +++ b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c @@ -386,7 +386,7 @@ void EnPoField_CorrectYPos(EnPoField* this, PlayState* play) { f32 EnPoField_SetFleeSpeed(EnPoField* this, PlayState* play) { Player* player = GET_PLAYER(play); - f32 speed = ((player->stateFlags1 & 0x800000) && player->rideActor != NULL) ? player->rideActor->speedXZ : 12.0f; + f32 speed = ((player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor != NULL) ? player->rideActor->speedXZ : 12.0f; if (this->actor.xzDistToPlayer < 300.0f) { this->actor.speedXZ = speed * 1.5f + 2.0f; @@ -414,13 +414,13 @@ void EnPoField_WaitForSpawn(EnPoField* this, PlayState* play) { if (fabsf(sEnPoFieldSpawnPositions[i].x - player->actor.world.pos.x) < 150.0f && fabsf(sEnPoFieldSpawnPositions[i].z - player->actor.world.pos.z) < 150.0f) { if (Flags_GetSwitch(play, sEnPoFieldSpawnSwitchFlags[i])) { - if (player->stateFlags1 & 0x800000) { // Player riding Epona + if (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) { // Player riding Epona return; } else { this->actor.params = EN_PO_FIELD_SMALL; spawnDist = 300.0f; } - } else if (player->stateFlags1 & 0x800000 || Rand_ZeroOne() < 0.4f) { + } else if (player->stateFlags1 & PLAYER_STATE1_ON_HORSE || Rand_ZeroOne() < 0.4f) { this->actor.params = EN_PO_FIELD_BIG; this->spawnFlagIndex = i; spawnDist = 480.0f; diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 6f36bea36..4514439c1 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -333,9 +333,12 @@ void func_80AE2C1C(EnRd* this, PlayState* play) { } if ((ABS(sp32) < 0x1554) && (Actor_WorldDistXYZToActor(&this->actor, &player->actor) <= 150.0f)) { - if (!(player->stateFlags1 & 0x2C6080) && !(player->stateFlags2 & 0x80)) { + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | + PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_CLIMBING_LADDER)) && + !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { if (this->unk_306 == 0) { - if (!(this->unk_312 & 0x80) && !CVarGetInteger("gNoRedeadFreeze", 0)) { + if (!(this->unk_312 & PLAYER_STATE2_GRABBED_BY_ENEMY) && !CVarGetInteger("gNoRedeadFreeze", 0)) { player->actor.freezeTimer = 40; func_8008EEAC(play, &this->actor); GET_PLAYER(play)->unk_684 = &this->actor; @@ -405,7 +408,10 @@ void func_80AE2FD0(EnRd* this, PlayState* play) { this->actor.world.rot.y = this->actor.shape.rot.y; SkelAnime_Update(&this->skelAnime); - if (!(player->stateFlags1 & 0x2C6080) && !(player->stateFlags2 & 0x80) && + if (!(player->stateFlags1 & + (PLAYER_STATE1_DEAD | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | + PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_CLIMBING_LADDER)) && + !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (Actor_WorldDistXYZToPoint(&player->actor, &this->actor.home.pos) < 150.0f)) { this->actor.targetMode = 0; func_80AE2B90(this, play); diff --git a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c index a3265d724..f999f3486 100644 --- a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c +++ b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c @@ -499,7 +499,7 @@ void EnRr_CollisionCheck(EnRr* this, PlayState* play) { } } if ((this->ocTimer == 0) && (this->actor.colorFilterTimer == 0) && (player->invincibilityTimer == 0) && - !(player->stateFlags2 & 0x80) && + !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && ((this->collider1.base.ocFlags1 & OC1_HIT) || (this->collider2.base.ocFlags1 & OC1_HIT))) { this->collider1.base.ocFlags1 &= ~OC1_HIT; this->collider2.base.ocFlags1 &= ~OC1_HIT; @@ -627,7 +627,7 @@ void EnRr_GrabPlayer(EnRr* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_LIKE_EAT); } this->ocTimer = 8; - if ((this->grabTimer == 0) || !(player->stateFlags2 & 0x80)) { + if ((this->grabTimer == 0) || !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { EnRr_SetupReleasePlayer(this, play); } else { Math_ApproachF(&player->actor.world.pos.x, this->mouthPos.x, 1.0f, 30.0f); diff --git a/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c b/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c index 97a3c0091..1ca46ddae 100644 --- a/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c +++ b/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c @@ -866,7 +866,8 @@ void func_80AEC780(EnRu1* this, PlayState* play) { s32 pad; Player* player = GET_PLAYER(play); - if ((func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && (!(player->stateFlags1 & 0x206000)) && + if ((func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && + (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) && (player->actor.bgCheckFlags & 1)) { play->csCtx.segment = &D_80AF0880; @@ -1652,7 +1653,7 @@ void func_80AEE7C4(EnRu1* this, PlayState* play) { } player = GET_PLAYER(play); - if (player->stateFlags2 & 0x10000000) { + if (player->stateFlags2 & PLAYER_STATE2_IDLING) { this->unk_370 += 1.0f; if (this->action != 32) { if (*unk_370 > 30.0f) { diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 207d9612b..f2ff5f684 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -722,7 +722,7 @@ void EnSkj_SariasSongKidIdle(EnSkj* this, PlayState* play) { Player* player = GET_PLAYER(play); if (EnSkj_RangeCheck(player, sSmallStumpSkullKid.skullkid)) { EnSkj_SetupWaitInRange(this); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; player->unk_6A8 = &sSmallStumpSkullKid.skullkid->actor; } } @@ -906,8 +906,8 @@ void EnSkj_WaitInRange(EnSkj* this, PlayState* play) { // When link pulls out the Ocarina center him on the stump // Link was probably supposed to be pointed towards skull kid as well - if (player->stateFlags2 & 0x1000000) { - player->stateFlags2 |= 0x2000000; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; player->unk_6A8 = &sSmallStumpSkullKid.skullkid->actor; player->actor.world.pos.x = sSmallStumpSkullKid.skullkid->actor.world.pos.x; player->actor.world.pos.y = sSmallStumpSkullKid.skullkid->actor.world.pos.y; @@ -928,7 +928,7 @@ void EnSkj_WaitInRange(EnSkj* this, PlayState* play) { } else if (!EnSkj_RangeCheck(player, sSmallStumpSkullKid.skullkid)) { EnSkj_SetupResetFight(this); } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; if (Flags_GetItemGetInf(ITEMGETINF_16)) { if (Flags_GetItemGetInf(ITEMGETINF_39)) { this->textId = Text_GetFaceReaction(play, 0x15); @@ -989,10 +989,10 @@ void EnSkj_WaitForSong(EnSkj* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_05; } } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_02) { - player->stateFlags2 &= ~0x1000000; + player->stateFlags2 &= ~PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR; Actor_Kill(&this->actor); } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_01) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } else { if (play->msgCtx.ocarinaMode >= OCARINA_MODE_05) { gSaveContext.sunsSongState = 0; @@ -1214,7 +1214,7 @@ void EnSkj_SariasSongWaitForTextClear(EnSkj* this, PlayState* play) { if (state == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { EnSkj_SetupWaitInRange(this); - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; player->unk_6A8 = (Actor*)sSmallStumpSkullKid.skullkid; } } @@ -1377,8 +1377,8 @@ void EnSkj_SetupWaitForOcarina(EnSkj* this, PlayState* play) { sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->playerInRange = true; sOcarinaMinigameSkullKids[SKULL_KID_RIGHT].skullkid->playerInRange = true; - if (player->stateFlags2 & 0x1000000) { - player->stateFlags2 |= 0x2000000; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; func_800F5BF0(NATURE_ID_KOKIRI_REGION); EnSkj_TurnPlayer(this, player); player->unk_6A8 = &this->actor; @@ -1393,15 +1393,15 @@ void EnSkj_SetupWaitForOcarina(EnSkj* this, PlayState* play) { void EnSkj_WaitForOcarina(EnSkj* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (player->stateFlags2 & 0x1000000) { - player->stateFlags2 |= 0x2000000; + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { + player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; func_800F5BF0(NATURE_ID_KOKIRI_REGION); EnSkj_TurnPlayer(this, player); player->unk_6A8 = &this->actor; Message_StartTextbox(play, 0x10BE, &this->actor); this->actionFunc = EnSkj_StartOcarinaMinigame; } else if (EnSkj_RangeCheck(player, this)) { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } @@ -1535,7 +1535,7 @@ void EnSkj_WaitForOfferResponse(EnSkj* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: // yes player = GET_PLAYER(play); - player->stateFlags3 |= 0x20; // makes player take ocarina out right away after closing box + player->stateFlags3 |= PLAYER_STATE3_FORCE_PULL_OCARINA; // makes player take ocarina out right away after closing box this->actionFunc = EnSkj_SetupWaitForOcarina; break; case 1: // no diff --git a/soh/src/overlays/actors/ovl_En_Stream/z_en_stream.c b/soh/src/overlays/actors/ovl_En_Stream/z_en_stream.c index 9d061ee47..34db1a005 100644 --- a/soh/src/overlays/actors/ovl_En_Stream/z_en_stream.c +++ b/soh/src/overlays/actors/ovl_En_Stream/z_en_stream.c @@ -103,7 +103,7 @@ void EnStream_SuckPlayer(EnStream* this, PlayState* play) { if (yDistWithOffset > 0.0f) { Math_SmoothStepToF(&player->actor.velocity.y, -3.0f, 0.7f, yDistWithOffset, 0.0f); if (posDifference.y < -70.0f) { - player->stateFlags2 |= 0x80000000; + player->stateFlags2 |= PLAYER_STATE2_FORCED_VOID_OUT; } } } else { diff --git a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c index 0a6825c0e..f62f8b998 100644 --- a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -718,7 +718,7 @@ s32 func_80B0DEA8(EnSw* this, PlayState* play, s32 arg2) { s32 sp54; Vec3f sp48; - if (!(player->stateFlags1 & 0x200000) && arg2) { + if (!(player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER) && arg2) { return false; } else if (func_8002DDF4(play) && arg2) { return false; diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 0eb3e9095..267a26c90 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -579,7 +579,7 @@ s32 func_80B150AC(EnTa* this, PlayState* play, s32 idx) { Player* player = GET_PLAYER(play); Actor* interactRangeActor; - if (player->stateFlags1 & 0x800) { + if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { interactRangeActor = player->interactRangeActor; if (interactRangeActor != NULL && interactRangeActor->id == ACTOR_EN_NIW && interactRangeActor == &this->superCuccos[idx]->actor) { @@ -613,7 +613,7 @@ void func_80B15100(EnTa* this, PlayState* play) { if (player->heldActor == &this->superCuccos[unk_2CA]->actor) { player->heldActor = NULL; } - player->stateFlags1 &= ~0x800; + player->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; this->superCuccos[unk_2CA] = NULL; } this->unk_2E0 |= 1; diff --git a/soh/src/overlays/actors/ovl_En_Test/z_en_test.c b/soh/src/overlays/actors/ovl_En_Test/z_en_test.c index 46e9edc9e..1f4be6670 100644 --- a/soh/src/overlays/actors/ovl_En_Test/z_en_test.c +++ b/soh/src/overlays/actors/ovl_En_Test/z_en_test.c @@ -407,7 +407,7 @@ void EnTest_ChooseAction(EnTest* this, PlayState* play) { } else { if (this->actor.xzDistToPlayer < 110.0f) { if (Rand_ZeroOne() > 0.2f) { - if (player->stateFlags1 & 0x10) { + if (player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) { if (this->actor.isTargeted) { EnTest_SetupSlashDown(this); } else { @@ -693,7 +693,7 @@ void EnTest_WalkAndBlock(EnTest* this, PlayState* play) { if (this->actor.xzDistToPlayer < 110.0f) { if (Rand_ZeroOne() > 0.2f) { - if (player->stateFlags1 & 0x10) { + if (player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) { if (this->actor.isTargeted) { EnTest_SetupSlashDown(this); } else { @@ -978,7 +978,7 @@ void EnTest_SlashDownEnd(EnTest* this, PlayState* play) { if ((ABS(yawDiff) > 0x3E80) && (this->actor.params != STALFOS_TYPE_CEILING)) { this->actor.world.rot.y = this->actor.yawTowardsPlayer; EnTest_SetupJumpBack(this); - } else if (player->stateFlags1 & 0x10) { + } else if (player->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) { if (this->actor.isTargeted) { EnTest_SetupSlashDown(this); } else if ((play->gameplayFrames % 2) != 0) { diff --git a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index bfc99a5b8..f919bb39a 100644 --- a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -356,7 +356,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { } else if (sSwordJumpState != 0) { sStickTilt = 0.0f; - player->stateFlags3 |= 4; + player->stateFlags3 |= PLAYER_STATE3_PAUSE_ACTION_FUNC; Math_SmoothStepToF(&this->actor.world.pos.x, (Math_SinS(player->actor.shape.rot.y - 0x3E8) * 45.0f) + player->actor.world.pos.x, @@ -369,7 +369,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { if (((u32)sSwordJumpTimer == 0) || ((player->invincibilityTimer > 0) && (this->meleeWeaponState == 0))) { this->actor.world.rot.y = this->actor.shape.rot.y = this->actor.yawTowardsPlayer; input->cur.button = BTN_A; - player->stateFlags3 &= ~4; + player->stateFlags3 &= ~PLAYER_STATE3_PAUSE_ACTION_FUNC; sStickTilt = 127.0f; player->skelAnime.curFrame = 3.0f; sStickAngle = this->actor.yawTowardsPlayer + 0x8000; @@ -404,7 +404,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { sStickTilt = 0.0f; sSwordJumpState = 1; - player->stateFlags3 |= 4; + player->stateFlags3 |= PLAYER_STATE3_PAUSE_ACTION_FUNC; this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; sSwordJumpTimer = 27; player->meleeWeaponState = 0; @@ -452,7 +452,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { sStickAngle = thisx->yawTowardsPlayer; sp50 = 0.0f; if ((90.0f >= this->actor.xzDistToPlayer) && (this->actor.xzDistToPlayer > 70.0f) && - (ABS(sp5A) >= 0x7800) && (this->actor.isTargeted || !(player->stateFlags1 & 0x00400000))) { + (ABS(sp5A) >= 0x7800) && (this->actor.isTargeted || !(player->stateFlags1 & PLAYER_STATE1_SHIELDING))) { EnTorch2_SwingSword(play, input, this); } else if (((this->actor.xzDistToPlayer <= 70.0f) || ((this->actor.xzDistToPlayer <= 80.0f + sp50) && (player->meleeWeaponState != 0))) && @@ -523,7 +523,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { this->meleeWeaponState = 0; input->cur.stick_x = input->cur.stick_y = 0; if ((this->invincibilityTimer > 0) && (this->actor.world.pos.y < (this->actor.floorHeight - 160.0f))) { - this->stateFlags3 &= ~1; + this->stateFlags3 &= ~PLAYER_STATE3_IGNORE_CEILING_FLOOR_WATER; this->actor.flags |= ACTOR_FLAG_TARGETABLE; this->invincibilityTimer = 0; this->actor.velocity.y = 0.0f; @@ -608,7 +608,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { sDeathFlag = false; } if ((this->invincibilityTimer == 0) && (this->actor.colChkInfo.health != 0) && - (this->cylinder.base.acFlags & AC_HIT) && !(this->stateFlags1 & 0x04000000) && + (this->cylinder.base.acFlags & AC_HIT) && !(this->stateFlags1 & PLAYER_STATE1_SHIELDING) && !(this->meleeWeaponQuads[0].base.atFlags & AT_HIT) && !(this->meleeWeaponQuads[1].base.atFlags & AT_HIT)) { if (!Actor_ApplyDamage(&this->actor)) { @@ -623,7 +623,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { sActionState = ENTORCH2_DEATH; Enemy_StartFinishingBlow(play, &this->actor); Item_DropCollectibleRandom(play, &this->actor, &thisx->world.pos, 0xC0); - this->stateFlags3 &= ~4; + this->stateFlags3 &= ~PLAYER_STATE3_PAUSE_ACTION_FUNC; } else { func_800F5ACC(NA_BGM_MINI_BOSS); if (this->actor.colChkInfo.damageEffect == 1) { @@ -640,8 +640,8 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { this->unk_8A4 = 8.0f; this->unk_8A2 = this->actor.yawTowardsPlayer + 0x8000; Actor_SetDropFlag(&this->actor, &this->cylinder.info, 1); - this->stateFlags3 &= ~4; - this->stateFlags3 |= 1; + this->stateFlags3 &= ~PLAYER_STATE3_PAUSE_ACTION_FUNC; + this->stateFlags3 |= PLAYER_STATE3_IGNORE_CEILING_FLOOR_WATER; sActionState = ENTORCH2_DAMAGE; if (sAlpha == 255) { Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 0xC); @@ -657,10 +657,10 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { // Handles being frozen by a deku nut if ((this->actor.colorFilterTimer == 0) || (this->actor.colorFilterParams & 0x4000)) { - this->stateFlags3 &= ~4; + this->stateFlags3 &= ~PLAYER_STATE3_PAUSE_ACTION_FUNC; } else { - this->stateFlags3 |= 4; - this->stateFlags1 &= ~0x04000000; + this->stateFlags3 |= PLAYER_STATE3_PAUSE_ACTION_FUNC; + this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING; this->invincibilityTimer = 0; input->press.stick_x = input->press.stick_y = 0; /*! @bug diff --git a/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c b/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c index 82c22529d..30ff3c37f 100644 --- a/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c +++ b/soh/src/overlays/actors/ovl_En_Tp/z_en_tp.c @@ -657,7 +657,7 @@ void EnTp_Update(Actor* thisx, PlayState* play) { Player* player = GET_PLAYER(play); s16 yawToWall; - if (player->stateFlags1 & 0x4000000) { // Shielding + if (player->stateFlags1 & PLAYER_STATE1_SHIELDING) { // Shielding this->damageEffect = TAILPASARAN_DMGEFF_NONE; } diff --git a/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c b/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c index 69c33f5f5..2f90ad1a0 100644 --- a/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c +++ b/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c @@ -313,11 +313,11 @@ void EnWallmas_WaitToDrop(EnWallmas* this, PlayState* play) { } if (this->actor.params == WMT_SHADOWTAG) { - if ((player->stateFlags1 & 0x100000) || (player->stateFlags1 & 0x8000000) || !(player->actor.bgCheckFlags & 1)) { + if ((player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) || (player->stateFlags1 & PLAYER_STATE1_IN_WATER) || !(player->actor.bgCheckFlags & 1)) { Audio_StopSfxById(NA_SE_EN_FALL_AIM); this->timer = 0x82; } - } else if ((player->stateFlags1 & 0x100000) || (player->stateFlags1 & 0x8000000) || !(player->actor.bgCheckFlags & 1) || + } else if ((player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) || (player->stateFlags1 & PLAYER_STATE1_IN_WATER) || !(player->actor.bgCheckFlags & 1) || ((this->actor.params == 1) && (320.0f < Math_Vec3f_DistXZ(&this->actor.home.pos, playerPos)))) { Audio_StopSfxById(NA_SE_EN_FALL_AIM); this->timer = 0x82; @@ -339,7 +339,7 @@ void EnWallmas_WaitToDrop(EnWallmas* this, PlayState* play) { void EnWallmas_Drop(EnWallmas* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (!Player_InCsMode(play) && !(player->stateFlags2 & 0x10) && (player->invincibilityTimer >= 0) && + if (!Player_InCsMode(play) && !(player->stateFlags2 & PLAYER_STATE2_MOVING_DYNAPOLY) && (player->invincibilityTimer >= 0) && (this->actor.xzDistToPlayer < 30.0f) && (this->actor.yDistToPlayer < -5.0f) && (-(f32)(player->cylinder.dim.height + 10) < this->actor.yDistToPlayer)) { EnWallmas_SetupTakePlayer(this, play); diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 83f799877..f0cdc2249 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -392,7 +392,7 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { if (((CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !IS_RANDO) || (Flags_GetTreasure(play, 2) && IS_RANDO)) && - !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !(stateFlags & 0x20000000) && + !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && !Play_InCsMode(play)) { if (!IS_RANDO) { Cutscene_SetSegment(play, &gIceCavernSerenadeCs); diff --git a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c index 9aa8204dd..98180605e 100644 --- a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c +++ b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c @@ -532,7 +532,7 @@ s32 EnZf_CanAttack(PlayState* play, EnZf* this) { Player* player = GET_PLAYER(play); if (this->actor.params >= ENZF_TYPE_LIZALFOS_MINIBOSS_A) { // miniboss - if (player->stateFlags1 & 0x6000) { // Hanging or climbing + if (player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE)) { // Hanging or climbing return false; } else { return true; @@ -1208,7 +1208,7 @@ void EnZf_Slash(EnZf* this, PlayState* play) { if (yawDiff > 16000) { this->actor.world.rot.y = this->actor.yawTowardsPlayer; func_80B483E4(this, play); - } else if (player->stateFlags1 & 0x6010) { + } else if (player->stateFlags1 & (PLAYER_STATE1_ENEMY_TARGET | PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE)) { if (this->actor.isTargeted) { EnZf_SetupSlash(this); } else { diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 727a20730..9a31ceb50 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -2233,7 +2233,7 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) { Math_ApproachF(&D_80B7E144, 195.0f, 1.0f, 1.0f); - if (player->stateFlags1 & 0x8000000) { + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { D_80B7E0B4 = 0; player->unk_860 = 0; } diff --git a/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c b/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c index 27b4c17cd..09ce9dff6 100644 --- a/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c +++ b/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c @@ -486,11 +486,11 @@ void ObjOshihiki_OnScene(ObjOshihiki* this, PlayState* play) { this->direction = this->dyna.unk_150; ObjOshihiki_SetupPush(this, play); } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } @@ -527,11 +527,11 @@ void ObjOshihiki_OnActor(ObjOshihiki* this, PlayState* play) { this->direction = this->dyna.unk_150; ObjOshihiki_SetupPush(this, play); } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } else { - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; } } else { @@ -579,7 +579,7 @@ void ObjOshihiki_Push(ObjOshihiki* this, PlayState* play) { if (!ObjOshihiki_CheckFloor(this, play)) { thisx->home.pos.x = thisx->world.pos.x; thisx->home.pos.z = thisx->world.pos.z; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; this->pushDist = 0.0f; this->pushSpeed = 0.0f; @@ -592,7 +592,7 @@ void ObjOshihiki_Push(ObjOshihiki* this, PlayState* play) { thisx->home.pos.x = thisx->world.pos.x; thisx->home.pos.z = thisx->world.pos.z; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->dyna.unk_150 = 0.0f; this->pushDist = 0.0f; this->pushSpeed = 0.0f; @@ -620,7 +620,7 @@ void ObjOshihiki_Fall(ObjOshihiki* this, PlayState* play) { this->stateFlags |= PUSHBLOCK_FALL; if (fabsf(this->dyna.unk_150) > 0.001f) { this->dyna.unk_150 = 0.0f; - player->stateFlags2 &= ~0x10; + player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; } Actor_MoveForward(&this->dyna.actor); if (ObjOshihiki_CheckGround(this, play)) { diff --git a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c index ed210ce0b..b0c7b44fc 100644 --- a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c +++ b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c @@ -171,11 +171,11 @@ s32 ObjTimeblock_WaitForOcarina(ObjTimeblock* this, PlayState* play) { Player* player = GET_PLAYER(play); if (ObjTimeblock_PlayerIsInRange(this, play)) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { func_8010BD58(play, OCARINA_ACTION_FREE_PLAY); this->songObserverFunc = ObjTimeblock_WaitForSong; } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } return false; diff --git a/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c b/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c index 73e592e3e..b67660963 100644 --- a/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c +++ b/soh/src/overlays/actors/ovl_Obj_Warp2block/z_obj_warp2block.c @@ -159,11 +159,11 @@ s32 func_80BA2218(ObjWarp2block* this, PlayState* play) { Player* player = GET_PLAYER(play); if (func_80BA1ECC(this, play)) { - if (player->stateFlags2 & 0x1000000) { + if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { func_8010BD58(play, OCARINA_ACTION_FREE_PLAY); this->func_168 = func_80BA228C; } else { - player->stateFlags2 |= 0x800000; + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } } diff --git a/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c b/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c index 0c280171f..a0552a027 100644 --- a/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c +++ b/soh/src/overlays/actors/ovl_Shot_Sun/z_shot_sun.c @@ -128,8 +128,8 @@ void func_80BADF0C(ShotSun* this, PlayState* play) { this->unk_1A4 = 0; } else { if (this->unk_1A4 == 0) { - if (!(player->stateFlags2 & 0x1000000)) { - player->stateFlags2 |= 0x800000; + if (!(player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR)) { + player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; return; } else { this->unk_1A4 = 1; From 0932e1e504538522b62a5b0009edf0ea41354aec Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 16 Feb 2024 01:20:12 +0000 Subject: [PATCH 061/300] Make the final Magic Bean cost 99 rupees in randomiser when it is not shuffled (#3392) * Make rando final eban cost 99 and clean up Text IDs * Remove Text ID changes * Add french translation, All credit to Purple hato Co-authored-by: Purple Hato --------- Co-authored-by: Purple Hato --- .../custom-message/CustomMessageTypes.h | 16 +++++ .../Enhancements/randomizer/randomizer.cpp | 11 +++- soh/soh/OTRGlobals.cpp | 9 +-- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 59 +++++++++++++------ 4 files changed, 70 insertions(+), 25 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 47729c129..9e0d7ec0d 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -55,6 +55,22 @@ typedef enum { TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW = 0x9210, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x346, // 0x3yy for cuttable sign range TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x1B3, // 0x1yy for Navi msg range + TEXT_SARIAS_SONG_CHANNELING_POWER = 0x016D, + TEXT_BEAN_SALESMAN_BUY_FOR_10 = 0x405E, + TEXT_BEAN_SALESMAN_BUY_FOR_20 = 0x405F, + TEXT_BEAN_SALESMAN_BUY_FOR_30 = 0x4060, + TEXT_BEAN_SALESMAN_BUY_FOR_40 = 0x4061, + TEXT_BEAN_SALESMAN_BUY_FOR_50 = 0x4062, + TEXT_BEAN_SALESMAN_BUY_FOR_60 = 0x4063, + TEXT_BEAN_SALESMAN_BUY_FOR_70 = 0x4064, + TEXT_BEAN_SALESMAN_BUY_FOR_80 = 0x4065, + TEXT_BEAN_SALESMAN_BUY_FOR_90 = 0x4066, + TEXT_BEAN_SALESMAN_BUY_FOR_100 = 0x4067, + TEXT_BEAN_SALESMAN_OH_WELL = 0x4068, + TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY = 0x4069, + TEXT_BEAN_SALESMAN_SET_A_BEAN_TO_C = 0x406A, + TEXT_BEAN_SALESMAN_SOLD_OUT = 0x406B, + TEXT_BEAN_SALESMAN_WANT_TO_PLANT = 0x406C, } TextIDs; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index db287fdff..f117e4c4a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -549,13 +549,18 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) { "\x12\x38\x82" "Aufgeben! Ich verkaufe dir einen&%g{{item}}%w&für %r{{price}} Rubine%w!\x07\x10\xA3", "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter&un %g{{item}}%w?&Ça fera %r{{price}} Rubis%w!\x07\x10\xA3")); CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN, + Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10, CustomMessage("I tried to be a %rmagic bean%w salesman,&but it turns out my marketing skills&weren't worth " "beans!^Anyway, want to buy my&%gmysterious item%w for 60 Rupees?\x1B&%gYes&No%w", "Möchten Sie einen geheimnisvollen&Gegenstand für 60 Rubine?\x1B&%gJa&Nein%w", "J'ai essayé d'être un vendeur de&%rharicots magiques%w, mais j'étais&mauvais au niveau du marketing et&ça " "me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter un&" "%gobjet mystérieux%w pour 60 Rubis?\x1B&%gOui&Non%w")); + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, + CustomMessage("I never thought I'd say this, but I'm &selling the last %rMagic Bean%w. %r99%w Rupees...\x1B&%gYes&No%w", + "\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); //Setup for merchant text boxes @@ -567,7 +572,7 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) { "Wie wäre es mit %g&{{item}}%w für %y200 Rubine?%w\x1B&%gJa!&Nein!%w", "Veux-tu acheter %g&{{item}}%w pour %y200 rubis?%w\x1B&%gOui&Non&w")); - //Granny Shopy + //Granny Shop //RANDOTODO: Implement obscure/ambiguous hints CustomMessageManager::Instance->CreateMessage( Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP, @@ -5385,7 +5390,7 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { } CustomMessage Randomizer::GetSariaMessage(u16 originalTextId) { - if (originalTextId == TEXT_SARIA_SFM || (originalTextId >= TEXT_SARIAS_SONG_TEXT_START && originalTextId <= TEXT_SARIAS_SONG_TEXT_END)) { + if (originalTextId == TEXT_SARIA_SFM || (originalTextId >= TEXT_SARIAS_SONG_FACE_TO_FACE && originalTextId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE); CustomMessage messageEntry2 = messageEntry; std::string code = originalTextId == TEXT_SARIA_SFM ? "" : "\x0B"; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 62a8bdd3d..a5983c457 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2588,10 +2588,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } else if (Randomizer_GetSettingValue(RSK_FROGS_HINT) && textId == TEXT_FROGS_UNDERWATER) { messageEntry = OTRGlobals::Instance->gRandomizer->GetFrogsMessage(textId); - } else if (Randomizer_GetSettingValue(RSK_SARIA_HINT)) { - if ((gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_TEXT_START && textId <= TEXT_SARIAS_SONG_TEXT_END)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId); - } + } else if (Randomizer_GetSettingValue(RSK_SARIA_HINT) && + (gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId); + } else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index b1d453f00..f89644847 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -18,6 +18,7 @@ void EnMs_SetOfferText(EnMs* this, PlayState* play); void EnMs_Wait(EnMs* this, PlayState* play); void EnMs_Talk(EnMs* this, PlayState* play); void EnMs_Sell(EnMs* this, PlayState* play); +void EnMs_Sell_Rando(EnMs* this, PlayState* play); void EnMs_TalkAfterPurchase(EnMs* this, PlayState* play); const ActorInit En_Ms_InitVars = { @@ -49,6 +50,10 @@ static s16 sPrices[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, }; +static s16 sRandoPrices[] = { + 10, 20, 30, 40, 50, 60, 70, 80, 90, 99, +}; + static u16 sOfferTextIDs[] = { 0x405E, 0x405F, 0x4060, 0x4061, 0x4062, 0x4063, 0x4064, 0x4065, 0x4066, 0x4067, }; @@ -127,21 +132,30 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } else if (Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - if (gSaveContext.rupees < - ((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) - ? 60 - : sPrices[BEANS_BOUGHT])) { - Message_ContinueTextbox(play, 0x4069); // not enough rupees text + //Randomizer Mechanic: Magic bean salesman + if (IS_RANDO){ + if (gSaveContext.rupees < ((Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? 60 : sRandoPrices[BEANS_BOUGHT])) { + Message_ContinueTextbox(play, 0x4069); // TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY + return; + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)){ + GiveItemEntryFromActor(&this->actor, play, + Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f); + } else { + func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + } + this->actionFunc = EnMs_Sell_Rando; + return; + } else { // vanilla code + if(gSaveContext.rupees < sPrices[BEANS_BOUGHT]){ + Message_ContinueTextbox(play, 0x4069); // TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY + return; + } + func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + this->actionFunc = EnMs_Sell; return; } - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f); - } else { - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); - } - this->actionFunc = EnMs_Sell; - return; + //Randomizer Mechanic end case 1: // no Message_ContinueTextbox(play, 0x4068); default: @@ -150,14 +164,13 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } } -void EnMs_Sell(EnMs* this, PlayState* play) { +void EnMs_Sell_Rando(EnMs* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { - Rupees_ChangeBy((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sPrices[BEANS_BOUGHT]); + Rupees_ChangeBy((Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sRandoPrices[BEANS_BOUGHT]); this->actor.parent = NULL; - this->actionFunc = - (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase; + this->actionFunc = (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase; } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; @@ -172,6 +185,16 @@ void EnMs_Sell(EnMs* this, PlayState* play) { } } +void EnMs_Sell(EnMs* this, PlayState* play) { + if (Actor_HasParent(&this->actor, play)) { + Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]); + this->actor.parent = NULL; + this->actionFunc = EnMs_TalkAfterPurchase; + } else { + func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + } +} + void EnMs_TalkAfterPurchase(EnMs* this, PlayState* play) { // if dialog state is 6 and player responded to textbox if ((Message_GetState(&play->msgCtx)) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { From 3514954ad17cd50afecc0bea5b529575e868161d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 15 Feb 2024 20:23:12 -0500 Subject: [PATCH 062/300] Adds Message Viewer Window to Developer Tools (#3486) * Adds a MessageViewer window to Developer Tools. * Properly destroys message viewer window. * Adds missing ImGui::End() * Fixes an oopsie crashing non-windows builds after first run. * Adds C ABI for displaying a custom message * Fixes a crash and an issue with messages with SFX. * Remove some osSyncPrintf's that aren't very useful for this case. --- .../Enhancements/debugger/MessageViewer.cpp | 271 ++++++++++++++++++ soh/soh/Enhancements/debugger/MessageViewer.h | 62 ++++ soh/soh/SohGui.cpp | 5 + soh/soh/SohMenuBar.cpp | 10 +- soh/soh/util.cpp | 13 + soh/soh/util.h | 4 + 6 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 soh/soh/Enhancements/debugger/MessageViewer.cpp create mode 100644 soh/soh/Enhancements/debugger/MessageViewer.h diff --git a/soh/soh/Enhancements/debugger/MessageViewer.cpp b/soh/soh/Enhancements/debugger/MessageViewer.cpp new file mode 100644 index 000000000..51fe3c0b9 --- /dev/null +++ b/soh/soh/Enhancements/debugger/MessageViewer.cpp @@ -0,0 +1,271 @@ +#include "MessageViewer.h" + +#include +#include + +#include "../custom-message/CustomMessageManager.h" +#include "functions.h" +#include "macros.h" +#include "message_data_static.h" +#include "variables.h" +#include "soh/util.h" + +extern "C" u8 sMessageHasSetSfx; + +void MessageViewer::InitElement() { + CustomMessageManager::Instance->AddCustomMessageTable(TABLE_ID); + mTableIdBuf = static_cast(calloc(MAX_STRING_SIZE, sizeof(char))); + mTextIdBuf = static_cast(calloc(MAX_STRING_SIZE, sizeof(char))); + mCustomMessageBuf = static_cast(calloc(MAX_STRING_SIZE, sizeof(char))); +} + +void MessageViewer::DrawElement() { + ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin("Custom Message Debugger", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) { + ImGui::End(); + return; + } + ImGui::Text("Table ID"); + ImGui::SameLine(); + ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); + UIWidgets::InsertHelpHoverText("Leave blank for vanilla table"); + ImGui::Text("Text ID"); + ImGui::SameLine(); + switch (mTextIdBase) { + case DECIMAL: + ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsDecimal); + UIWidgets::InsertHelpHoverText("Decimal Text ID of the message to load. Decimal digits only (0-9)."); + break; + case HEXADECIMAL: + default: + ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal); + UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F)."); + break; + } + if (ImGui::RadioButton("Hexadecimal", &mTextIdBase, HEXADECIMAL)) { + memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE); + } + ImGui::SameLine(); + if (ImGui::RadioButton("Decimal", &mTextIdBase, DECIMAL)) { + memset(mTextIdBuf, 0, sizeof(char) * MAX_STRING_SIZE); + } + ImGui::Text("Language"); + ImGui::SameLine(); + if (ImGui::BeginCombo("##Language", mLanguages[mLanguage])) { + // ReSharper disable CppDFAUnreachableCode + for (size_t i = 0; i < mLanguages.size(); i++) { + if (strlen(mLanguages[i]) > 0) { + if (ImGui::Selectable(mLanguages[i], i == mLanguage)) { + mLanguage = i; + } + } + } + ImGui::EndCombo(); + } + UIWidgets::InsertHelpHoverText("Which language to load from the selected text ID"); + if (ImGui::Button("Display Message##ExistingMessage")) { + mDisplayExistingMessageClicked = true; + } + ImGui::Text("Custom Message"); + UIWidgets::InsertHelpHoverText("Enter a string using Custom Message Syntax to preview it in-game. " + "Any newline (\\n) characters inserted by the Enter key will be stripped " + "from the output."); + ImGui::InputTextMultiline("##CustomMessage", mCustomMessageBuf, MAX_STRING_SIZE); + if (ImGui::Button("Display Message##CustomMessage")) { + mDisplayCustomMessageClicked = true; + } + ImGui::End(); + // ReSharper restore CppDFAUnreachableCode +} + +void MessageViewer::UpdateElement() { + if (mDisplayExistingMessageClicked) { + mTableId = std::string(mTableIdBuf); + switch (mTextIdBase) { + case DECIMAL: + mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 10); + break; + case HEXADECIMAL: + default: + mTextId = std::stoi(std::string(mTextIdBuf), nullptr, 16); + break; + } + DisplayExistingMessage(); + mDisplayExistingMessageClicked = false; + } + if (mDisplayCustomMessageClicked) { + mCustomMessageString = std::string(mCustomMessageBuf); + std::erase(mCustomMessageString, '\n'); + DisplayCustomMessage(); + mDisplayCustomMessageClicked = false; + } +} + +void MessageViewer::DisplayExistingMessage() const { + MessageDebug_StartTextBox(mTableId.c_str(), mTextId, mLanguage); +} + +void MessageViewer::DisplayCustomMessage() const { + MessageDebug_DisplayCustomMessage(mCustomMessageString.c_str()); +} + +extern "C" MessageTableEntry* sNesMessageEntryTablePtr; +extern "C" MessageTableEntry* sGerMessageEntryTablePtr; +extern "C" MessageTableEntry* sFraMessageEntryTablePtr; +extern "C" MessageTableEntry* sStaffMessageEntryTablePtr; + +void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language) { + const char* foundSeg; + const char* nextSeg; + MessageTableEntry* messageTableEntry = sNesMessageEntryTablePtr; + Font* font; + u16 bufferId = textId; + // Use the better owl message if better owl is enabled + if (CVarGetInteger("gBetterOwl", 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B || + bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A)) + { + bufferId = 0x71B3; + } + + if (language == LANGUAGE_GER) + messageTableEntry = sGerMessageEntryTablePtr; + else if (language == LANGUAGE_FRA) + messageTableEntry = sFraMessageEntryTablePtr; + + // If PAL languages are not present in the OTR file, default to English + if (messageTableEntry == nullptr) + messageTableEntry = sNesMessageEntryTablePtr; + + const char* seg = messageTableEntry->segment; + + while (messageTableEntry->textId != 0xFFFF) { + font = &play->msgCtx.font; + + if (messageTableEntry->textId == bufferId) { + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + + nextSeg = messageTableEntry->segment; + font->msgOffset = reinterpret_cast(messageTableEntry->segment); + font->msgLength = messageTableEntry->msgSize; + return; + } + messageTableEntry++; + } + + font = &play->msgCtx.font; + messageTableEntry = sNesMessageEntryTablePtr; + + foundSeg = messageTableEntry->segment; + font->charTexBuf[0] = messageTableEntry->typePos; + messageTableEntry++; + nextSeg = messageTableEntry->segment; + font->msgOffset = foundSeg - seg; + font->msgLength = nextSeg - foundSeg; +} + +static const char* msgStaticTbl[] = +{ + gDefaultMessageBackgroundTex, + gSignMessageBackgroundTex, + gNoteStaffMessageBackgroundTex, + gFadingMessageBackgroundTex, + gMessageContinueTriangleTex, + gMessageEndSquareTex, + gMessageArrowTex +}; + +void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language) { + PlayState* play = gPlayState; + static int16_t messageStaticIndices[] = { 0, 1, 3, 2 }; + const auto player = GET_PLAYER(gPlayState); + player->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO; + MessageContext* msgCtx = &play->msgCtx; + msgCtx->ocarinaAction = 0xFFFF; + Font* font = &msgCtx->font; + sMessageHasSetSfx = 0; + for (u32 i = 0; i < FONT_CHAR_TEX_SIZE * 120; i += FONT_CHAR_TEX_SIZE) { + if (&font->charTexBuf[i] != nullptr) { + gSPInvalidateTexCache(play->state.gfxCtx->polyOpa.p++, reinterpret_cast(&font->charTexBuf[i])); + } + } + R_TEXT_CHAR_SCALE = 75; + R_TEXT_LINE_SPACING = 12; + R_TEXT_INIT_XPOS = 65; + char* buffer = font->msgBuf; + msgCtx->textId = textId; + if (strlen(tableId) == 0) { + FindMessage(play, textId, language); + msgCtx->msgLength = static_cast(font->msgLength); + const uintptr_t src = font->msgOffset; + memcpy(font->msgBuf, reinterpret_cast(src), font->msgLength); + } else { + constexpr int maxBufferSize = sizeof(font->msgBuf); + const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId); + font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); + switch (language) { + case LANGUAGE_FRA: + font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetFrench(), maxBufferSize); + break; + case LANGUAGE_GER: + font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetGerman(), maxBufferSize); + break; + case LANGUAGE_ENG: + default: + font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetEnglish(), maxBufferSize); + break; + } + msgCtx->msgLength = static_cast(font->msgLength); + } + msgCtx->textBoxProperties = font->charTexBuf[0]; + msgCtx->textBoxType = msgCtx->textBoxProperties >> 4; + msgCtx->textBoxPos = msgCtx->textBoxProperties & 0xF; + const int16_t textBoxType = msgCtx->textBoxType; + // "Text Box Type" + osSyncPrintf("吹き出し種類=%d\n", msgCtx->textBoxType); + if (textBoxType < TEXTBOX_TYPE_NONE_BOTTOM) { + const char* textureName = msgStaticTbl[messageStaticIndices[textBoxType]]; + memcpy(msgCtx->textboxSegment, textureName, strlen(textureName) + 1); + if (textBoxType == TEXTBOX_TYPE_BLACK) { + msgCtx->textboxColorRed = 0; + msgCtx->textboxColorGreen = 0; + msgCtx->textboxColorBlue = 0; + } else if (textBoxType == TEXTBOX_TYPE_WOODEN) { + msgCtx->textboxColorRed = 70; + msgCtx->textboxColorGreen = 50; + msgCtx->textboxColorBlue = 30; + } else if (textBoxType == TEXTBOX_TYPE_BLUE) { + msgCtx->textboxColorRed = 0; + msgCtx->textboxColorGreen = 10; + msgCtx->textboxColorBlue = 50; + } else { + msgCtx->textboxColorRed = 255; + msgCtx->textboxColorGreen = 0; + msgCtx->textboxColorBlue = 0; + } + if (textBoxType == TEXTBOX_TYPE_WOODEN) { + msgCtx->textboxColorAlphaTarget = 230; + } else if (textBoxType == TEXTBOX_TYPE_OCARINA) { + msgCtx->textboxColorAlphaTarget = 180; + } else { + msgCtx->textboxColorAlphaTarget = 170; + } + msgCtx->textboxColorAlphaCurrent = 0; + } + msgCtx->choiceNum = msgCtx->textUnskippable = msgCtx->textboxEndType = 0; + msgCtx->msgBufPos = msgCtx->unk_E3D0 = msgCtx->textDrawPos = 0; + msgCtx->talkActor = &player->actor; + msgCtx->msgMode = MSGMODE_TEXT_START; + msgCtx->stateTimer = 0; + msgCtx->textDelayTimer = 0; + msgCtx->ocarinaMode = OCARINA_MODE_00; +} + +void MessageDebug_DisplayCustomMessage(const char* customMessage) { + CustomMessageManager::Instance->ClearMessageTable(MessageViewer::TABLE_ID); + CustomMessageManager::Instance->CreateMessage(MessageViewer::TABLE_ID, 0, + CustomMessage(customMessage, customMessage, customMessage)); + MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0); +} + + diff --git a/soh/soh/Enhancements/debugger/MessageViewer.h b/soh/soh/Enhancements/debugger/MessageViewer.h new file mode 100644 index 000000000..702693793 --- /dev/null +++ b/soh/soh/Enhancements/debugger/MessageViewer.h @@ -0,0 +1,62 @@ +#ifndef CUSTOMMESSAGEDEBUGGER_H +#define CUSTOMMESSAGEDEBUGGER_H +#include "z64.h" + +#ifdef __cplusplus +#include "GuiWindow.h" +#include +extern "C" { +#endif +/** + * \brief Pulls a message from the specified message table and kicks off the process of displaying that message + * in a text box on screen. + * \param tableId the tableId string for the table we want to pull from. Empty string for authentic/vanilla messages + * \param textId The textId corresponding to the message to display. Putting in a textId that doesn't exist will + * probably result in a crash. + * \param language The Language to display on the screen. + */ +void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t language); + +/** + * \brief + * \param customMessage A string using Custom Message Syntax. + */ +void MessageDebug_DisplayCustomMessage(const char* customMessage); +#ifdef __cplusplus +} + + +class MessageViewer : public LUS::GuiWindow { +public: + static inline const char* TABLE_ID = "MessageViewer"; + using GuiWindow::GuiWindow; + + void InitElement() override; + void DrawElement() override; + void UpdateElement() override; + + virtual ~MessageViewer() = default; + +private: + void DisplayExistingMessage() const; + void DisplayCustomMessage() const; + + static constexpr uint16_t MAX_STRING_SIZE = 1024; + static constexpr std::array mLanguages = {"English", "German", "French"}; + static constexpr int HEXADECIMAL = 0; + static constexpr int DECIMAL = 1; + char* mTableIdBuf; + std::string mTableId; + char* mTextIdBuf; + uint16_t mTextId; + int mTextIdBase = HEXADECIMAL; + size_t mLanguage = LANGUAGE_ENG; + char* mCustomMessageBuf; + std::string mCustomMessageString; + bool mDisplayExistingMessageClicked = false; + bool mDisplayCustomMessageClicked = false; +}; + + +#endif //__cplusplus +#endif //CUSTOMMESSAGEDEBUGGER_H diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 49f84068a..a295fed66 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -41,6 +41,7 @@ #include "Enhancements/game-interactor/GameInteractor.h" #include "Enhancements/cosmetics/authenticGfxPatches.h" #include "Enhancements/resolution-editor/ResolutionEditor.h" +#include "Enhancements/debugger/MessageViewer.h" bool ToggleAltAssetsAtEndOfFrame = false; bool isBetaQuestEnabled = false; @@ -122,6 +123,7 @@ namespace SohGui { std::shared_ptr mSaveEditorWindow; std::shared_ptr mDLViewerWindow; std::shared_ptr mValueViewerWindow; + std::shared_ptr mMessageViewerWindow; std::shared_ptr mGameplayStatsWindow; std::shared_ptr mCheckTrackerSettingsWindow; std::shared_ptr mCheckTrackerWindow; @@ -175,6 +177,8 @@ namespace SohGui { gui->AddGuiWindow(mDLViewerWindow); mValueViewerWindow = std::make_shared("gValueViewer.WindowOpen", "Value Viewer"); gui->AddGuiWindow(mValueViewerWindow); + mMessageViewerWindow = std::make_shared("gMessageViewerEnabled", "Message Viewer"); + gui->AddGuiWindow(mMessageViewerWindow); mGameplayStatsWindow = std::make_shared("gGameplayStatsEnabled", "Gameplay Stats"); gui->AddGuiWindow(mGameplayStatsWindow); mCheckTrackerWindow = std::make_shared("gCheckTrackerEnabled", "Check Tracker"); @@ -204,6 +208,7 @@ namespace SohGui { mGameplayStatsWindow = nullptr; mDLViewerWindow = nullptr; mValueViewerWindow = nullptr; + mMessageViewerWindow = nullptr; mSaveEditorWindow = nullptr; mColViewerWindow = nullptr; mActorViewerWindow = nullptr; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c2a300877..7fb93544d 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -28,6 +28,7 @@ #include "Enhancements/debugger/dlViewer.h" #include "Enhancements/debugger/valueViewer.h" #include "Enhancements/gameplaystatswindow.h" +#include "Enhancements/debugger/MessageViewer.h" #include "Enhancements/randomizer/randomizer_check_tracker.h" #include "Enhancements/randomizer/randomizer_entrance_tracker.h" #include "Enhancements/randomizer/randomizer_item_tracker.h" @@ -1579,6 +1580,7 @@ extern std::shared_ptr mColViewerWindow; extern std::shared_ptr mActorViewerWindow; extern std::shared_ptr mDLViewerWindow; extern std::shared_ptr mValueViewerWindow; +extern std::shared_ptr mMessageViewerWindow; void DrawDeveloperToolsMenu() { if (ImGui::BeginMenu("Developer Tools")) { @@ -1678,6 +1680,12 @@ void DrawDeveloperToolsMenu() { mValueViewerWindow->ToggleVisibility(); } } + UIWidgets::Spacer(0); + if (mMessageViewerWindow) { + if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger("gMessageViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + mMessageViewerWindow->ToggleVisibility(); + } + } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); @@ -1967,4 +1975,4 @@ void SohMenuBar::DrawElement() { ImGui::EndMenuBar(); } } -} // namespace SohGui +} // namespace SohGui diff --git a/soh/soh/util.cpp b/soh/soh/util.cpp index 856432cbb..ceadb8b0e 100644 --- a/soh/soh/util.cpp +++ b/soh/soh/util.cpp @@ -336,3 +336,16 @@ std::string SohUtils::Sanitize(std::string stringValue) { return stringValue; } + +size_t SohUtils::CopyStringToCharBuffer(char* buffer, const std::string& source, const size_t maxBufferSize) { + if (!source.empty()) { + // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. + memset(buffer, 0, std::max(0, maxBufferSize)); + // Gaurentee that this value will be greater than 0, regardless of passed variables. + const size_t copiedCharLen = std::min(std::max(0, maxBufferSize - 1), source.length()); + memcpy(buffer, source.c_str(), copiedCharLen); + return copiedCharLen; + } + + return 0; +} diff --git a/soh/soh/util.h b/soh/soh/util.h index db5af8636..827355862 100644 --- a/soh/soh/util.h +++ b/soh/soh/util.h @@ -14,4 +14,8 @@ namespace SohUtils { void CopyStringToCharArray(char* destination, std::string source, size_t size); std::string Sanitize(std::string stringValue); + + // Copies a string into a char buffer up to maxBufferSize characters. This does NOT insert a null terminator + // on the end, as this is used for in-game messages which are not null-terminated. + size_t CopyStringToCharBuffer(char* buffer, const std::string& source, size_t maxBufferSize); } // namespace SohUtils From 458970816fb7214c1893236c53144883a95d9cb1 Mon Sep 17 00:00:00 2001 From: Giantblargg Date: Thu, 15 Feb 2024 18:26:27 -0700 Subject: [PATCH 063/300] Fix Check Tracker Vanilla/MQ Dungeon Spoilers (#3723) * Fix Dungeon Spoilers * Update soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp * Update soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index a50a28762..81415f407 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -762,7 +762,6 @@ void InitTrackerData(bool isDebug) { } } UpdateAllOrdering(); - UpdateInventoryChecks(); } void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) { From c1365b3263d7934439700f7e27c71da67edb8431 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:27:26 -0500 Subject: [PATCH 064/300] [Time Savers] Shops and Games always open (#3789) * Shops and Games always open * Added comment for scene reload requirement * Prefix * Spacing Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> * I'm bad at merging * Refined by Archez --------- Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> --- soh/soh/Enhancements/mods.cpp | 30 +++++++++++++++++++ soh/soh/SohMenuBar.cpp | 2 ++ .../overlays/actors/ovl_En_Door/z_en_door.h | 2 ++ 3 files changed, 34 insertions(+) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 8b65cdcbe..9ae89719f 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -33,6 +33,7 @@ extern "C" { #include "functions.h" #include "variables.h" #include "functions.h" +#include "src/overlays/actors/ovl_En_Door/z_en_door.h" void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); @@ -1222,6 +1223,34 @@ void RegisterRandomizedEnemySizes() { }); } +void RegisterOpenAllHours() { + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + + if (CVarGetInteger("gEnhancements.OpenAllHours", 0) && (actor->id == ACTOR_EN_DOOR)) { + switch (actor->params) { + case 4753: // Night Market Bazaar + case 1678: // Night Potion Shop + case 2689: // Day Bombchu Shop + case 2703: // Night Slingshot Game + case 653: // Day Chest Game + case 6801: // Night Kak Bazaar + case 7822: // Night Kak Potion Shop + case 4751: // Night Kak Archery Game + case 3728: // Night Mask Shop + { + actor->params = (actor->params & 0xFC00) | (DOOR_SCENEEXIT << 7) | 0x3F; + EnDoor* enDoor = static_cast(refActor); + EnDoor_SetupType(enDoor, gPlayState); + break; + } + default: + break; + } + } + }); +} + void PatchToTMedallions() { // TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect // effects to take effect in there @@ -1353,6 +1382,7 @@ void InitMods() { RegisterAltTrapTypes(); RegisterRandomizerSheikSpawn(); RegisterRandomizedEnemySizes(); + RegisterOpenAllHours(); RegisterToTMedallions(); NameTag_RegisterHooks(); RegisterPatchHandHandler(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 7fb93544d..20b53fc89 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -631,6 +631,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", "gMarketSneak", true, false); UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate."); + UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", "gEnhancements.OpenAllHours", true, false); + UIWidgets::Tooltip("Shops and minigames are open both day and night. Requires scene reload to take effect."); UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", "gQuitFishingAtDoor", true, false); diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h index 5cb5a7f1c..7389ac99a 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h @@ -57,4 +57,6 @@ typedef struct EnDoor { /* 0x01D4 */ EnDoorActionFunc actionFunc; } EnDoor; // size = 0x01D8 +void EnDoor_SetupType(EnDoor* enDoor, PlayState* play); + #endif From 7cdd33a01d7b82d256164ca57933c4fe31d1c45f Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 16 Feb 2024 02:32:17 +0100 Subject: [PATCH 065/300] Better ammo rendering (#3844) * Better ammo rendering * Update soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c Co-authored-by: Archez * Update z_kaleido_scope_PAL.c * Rename gBetterAmmoRendering to gEnhancements.BetterAmmoRendering --------- Co-authored-by: Archez --- soh/soh/SohMenuBar.cpp | 2 ++ .../misc/ovl_kaleido_scope/z_kaleido_item.c | 25 ++++++++++++++++--- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 10 +++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 20b53fc89..8b33a72ef 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1149,6 +1149,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Space between text characters (useful for HD font textures)"); UIWidgets::PaddedEnhancementCheckbox("More info in file select", "gFileSelectMoreInfo", true, false); UIWidgets::Tooltip("Shows what items you have collected in the file select screen, like in N64 randomizer"); + UIWidgets::PaddedEnhancementCheckbox("Better ammo rendering in pause menu", "gEnhancements.BetterAmmoRendering", true, false); + UIWidgets::Tooltip("Ammo counts in the pause menu will work correctly regardless of the position of items in the inventory"); ImGui::EndMenu(); } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index b04f07b38..18cfdc065 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -19,8 +19,23 @@ static s16 sAmmoVtxOffset[] = { 0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12, }; +static s16 sAllAmmoVtxOffset[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46 +}; + extern const char* _gAmmoDigit0Tex[]; +s8 ItemInSlotUsesAmmo(s16 slot) { + s16 item = gSaveContext.inventory.items[slot]; + return item == ITEM_STICK || + item == ITEM_NUT || + item == ITEM_BOMB || + item == ITEM_BOW || + item == ITEM_SLINGSHOT || + item == ITEM_BOMBCHU || + item == ITEM_BEAN; +} + void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item, int slot) { s16 ammo; s16 i; @@ -55,7 +70,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gDPPipeSync(POLY_KAL_DISP++); if (i != 0) { - gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[slot] + 31) * 4], 4, 0); + gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 31) * 4], 4, 0); gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[i]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, @@ -64,7 +79,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); } - gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[(sAmmoVtxOffset[slot] + 32) * 4], 4, 0); + gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 32) * 4], 4, 0); gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[ammo]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, @@ -764,8 +779,10 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { gDPSetCombineLERP(POLY_KAL_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - for (i = 0; i < 15; i++) { - if ((gAmmoItems[i] != ITEM_NONE) && (gSaveContext.inventory.items[i] != ITEM_NONE)) { + u8 gBetterAmmoRendering = CVarGetInteger("gEnhancements.BetterAmmoRendering", 0); + + for (i = 0; i < (gBetterAmmoRendering ? 24 : 15); i++) { + if ((gBetterAmmoRendering ? ItemInSlotUsesAmmo(i) : gAmmoItems[i] != ITEM_NONE) && (gSaveContext.inventory.items[i] != ITEM_NONE)) { KaleidoScope_DrawAmmoCount(pauseCtx, play->state.gfxCtx, gSaveContext.inventory.items[i], i); } } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 5f8da1b70..059a845c3 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -2703,6 +2703,8 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 pageIndex, s16 arg3) { static s16 D_8082B11C[] = { 0, 4, 8, 12, 24, 32, 56 }; +static s16 D_8082B11C_all[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 96 }; + static s16 D_8082B12C[] = { -114, 12, 44, 76 }; static u8 D_8082B134[] = { 1, 5, 9, 13 }; @@ -2825,7 +2827,7 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorVtx[19].v.tc[1] = 0x400; // 24 items, 7 "item selected" backgrounds, 14 ammo digits (2 each for 7 items) -- then 4 vertices for each - pauseCtx->itemVtx = Graph_Alloc(gfxCtx, (24 + 7 + 14) * 4 * sizeof(Vtx)); + pauseCtx->itemVtx = Graph_Alloc(gfxCtx, (24 + 7 + 2 * (CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? ARRAY_COUNT(D_8082B11C_all) : ARRAY_COUNT(D_8082B11C))) * 4 * sizeof(Vtx)); for (phi_t4 = 0, phi_t2 = 0, phi_t5 = 58; phi_t4 < 4; phi_t4++, phi_t5 -= 32) { for (phi_t1 = -96, phi_t3 = 0; phi_t3 < 6; phi_t3++, phi_t2 += 4, phi_t1 += 32) { @@ -2915,8 +2917,10 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { } } - for (phi_t3 = 0; phi_t3 < 7; phi_t3++) { - phi_t4 = D_8082B11C[phi_t3]; + u8 gBetterAmmoRendering = CVarGetInteger("gEnhancements.BetterAmmoRendering", 0); + + for (phi_t3 = 0; phi_t3 < (gBetterAmmoRendering ? ARRAY_COUNT(D_8082B11C_all) : ARRAY_COUNT(D_8082B11C)); phi_t3++) { + phi_t4 = gBetterAmmoRendering ? D_8082B11C_all[phi_t3] : D_8082B11C[phi_t3]; pauseCtx->itemVtx[phi_t2 + 0].v.ob[0] = pauseCtx->itemVtx[phi_t2 + 2].v.ob[0] = pauseCtx->itemVtx[phi_t4].v.ob[0]; From db958ab3f45e6ab34d13ee82f6dd53589f5c3928 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 15 Feb 2024 17:37:19 -0800 Subject: [PATCH 066/300] New input viewer (#3890) * Move input viewer into SoH * Remove unnecessary comments * Update button outline mode to match default viewer * Fix ambiguous call * CVar name changes and minor fixes * Two more cvars * Separate C-buttons into individual toggles * Account for text height regardless of scale * A few extra comments * Use new LoadTextureFromRawImage to load layer textures --- soh/assets/custom/textures/buttons/ABtn.png | Bin 10967 -> 1485 bytes .../custom/textures/buttons/ABtnOutline.png | Bin 0 -> 1818 bytes .../custom/textures/buttons/AnalogStick.png | Bin 0 -> 2206 bytes .../textures/buttons/AnalogStickOutline.png | Bin 0 -> 3677 bytes soh/assets/custom/textures/buttons/BBtn.png | Bin 1300 -> 1534 bytes .../custom/textures/buttons/BBtnOutline.png | Bin 0 -> 1878 bytes soh/assets/custom/textures/buttons/CDown.png | Bin 11241 -> 1285 bytes .../custom/textures/buttons/CDownOutline.png | Bin 0 -> 1544 bytes soh/assets/custom/textures/buttons/CLeft.png | Bin 11232 -> 1291 bytes .../custom/textures/buttons/CLeftOutline.png | Bin 0 -> 1544 bytes soh/assets/custom/textures/buttons/CRight.png | Bin 11284 -> 1336 bytes .../custom/textures/buttons/CRightOutline.png | Bin 0 -> 1541 bytes soh/assets/custom/textures/buttons/CUp.png | Bin 11219 -> 1305 bytes .../custom/textures/buttons/CUpOutline.png | Bin 0 -> 1546 bytes .../custom/textures/buttons/DPadDown.png | Bin 0 -> 946 bytes .../textures/buttons/DPadDownOutline.png | Bin 0 -> 984 bytes .../custom/textures/buttons/DPadLeft.png | Bin 0 -> 929 bytes .../textures/buttons/DPadLeftOutline.png | Bin 0 -> 953 bytes .../custom/textures/buttons/DPadRight.png | Bin 0 -> 922 bytes .../textures/buttons/DPadRightOutline.png | Bin 0 -> 954 bytes soh/assets/custom/textures/buttons/DPadUp.png | Bin 0 -> 968 bytes .../custom/textures/buttons/DPadUpOutline.png | Bin 0 -> 993 bytes .../buttons/InputViewerBackground.png | Bin 0 -> 941 bytes soh/assets/custom/textures/buttons/LBtn.png | Bin 355 -> 1031 bytes .../custom/textures/buttons/LBtnOutline.png | Bin 0 -> 1089 bytes soh/assets/custom/textures/buttons/RBtn.png | Bin 379 -> 992 bytes .../custom/textures/buttons/RBtnOutline.png | Bin 0 -> 1074 bytes .../custom/textures/buttons/RightStick.png | Bin 0 -> 2150 bytes .../textures/buttons/RightStickOutline.png | Bin 0 -> 2407 bytes .../custom/textures/buttons/StartBtn.png | Bin 11868 -> 973 bytes .../textures/buttons/StartBtnOutline.png | Bin 0 -> 1031 bytes soh/assets/custom/textures/buttons/ZBtn.png | Bin 1241 -> 1005 bytes .../custom/textures/buttons/ZBtnOutline.png | Bin 0 -> 1069 bytes soh/soh/Enhancements/controls/InputViewer.cpp | 519 ++++++++++++++++++ soh/soh/Enhancements/controls/InputViewer.h | 47 ++ soh/soh/SohGui.cpp | 6 + soh/soh/SohGui.hpp | 1 + soh/soh/SohMenuBar.cpp | 25 +- 38 files changed, 594 insertions(+), 4 deletions(-) create mode 100644 soh/assets/custom/textures/buttons/ABtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/AnalogStick.png create mode 100644 soh/assets/custom/textures/buttons/AnalogStickOutline.png create mode 100644 soh/assets/custom/textures/buttons/BBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/CDownOutline.png create mode 100644 soh/assets/custom/textures/buttons/CLeftOutline.png create mode 100644 soh/assets/custom/textures/buttons/CRightOutline.png create mode 100644 soh/assets/custom/textures/buttons/CUpOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadDown.png create mode 100644 soh/assets/custom/textures/buttons/DPadDownOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadLeft.png create mode 100644 soh/assets/custom/textures/buttons/DPadLeftOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadRight.png create mode 100644 soh/assets/custom/textures/buttons/DPadRightOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadUp.png create mode 100644 soh/assets/custom/textures/buttons/DPadUpOutline.png create mode 100644 soh/assets/custom/textures/buttons/InputViewerBackground.png create mode 100644 soh/assets/custom/textures/buttons/LBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/RBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/RightStick.png create mode 100644 soh/assets/custom/textures/buttons/RightStickOutline.png create mode 100644 soh/assets/custom/textures/buttons/StartBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/ZBtnOutline.png create mode 100644 soh/soh/Enhancements/controls/InputViewer.cpp create mode 100644 soh/soh/Enhancements/controls/InputViewer.h diff --git a/soh/assets/custom/textures/buttons/ABtn.png b/soh/assets/custom/textures/buttons/ABtn.png index c1b06571c3a9c4427420bcbccec364f28c7c4778..031924cb963fdd399db122ccc7e584ab77d0b782 100644 GIT binary patch delta 1343 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 Fe*n=C2|@q> literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/AnalogStick.png b/soh/assets/custom/textures/buttons/AnalogStick.png new file mode 100644 index 0000000000000000000000000000000000000000..d3fec7d015eb293346187db09fea10407ad7cf2a GIT binary patch literal 2206 zcmb_ci#rqQAK!?%#3r|4ZFAHwmnE05>bT6TF}b9edu5HEilNOdj!sr9mmwm#)ei?- zE};o2cd?Mel9tO_B4Soav2@n&Z#eJsyzl#cKF{a*yzl4vzMuDor#oInNmmH~0I0Y) zJ9z;BK)kfBSCE&kkw!2xDR4C$i}iHDVv$iXl+f@CWB|Z0CppK~xyMuEs>cajPMY(P z>xO5m-L;(3(FD!()AyP+{b^*8)GP(}b{`JH{VfZUDC+})=aT?%#%=17|9 zj=*^Pa>@{}E8s3=xFld1Rt0vr7Wyzr76y|M;)a4Z;^Qa_Z?;#$hee=vrI_Bw2H6SH zzQ~8T;++7MfLy?B2RY7BDWVwV>~|3WP*(pnfq*;3P$>way13y$i$J)x5qiYAdRz+W zP;tIgEF~g>97zRWW5{Qy`QaO!`Nco#QM;-9M8Qgxb(6Xs<6>y_!Q2>vrTXs)nQ z$r&VwZ3t6z&QqOXBV)n4?gkVW0azgJ-V1X1z|@6gP1H0-DceHSFi~ft7Cy)f$=S5) zbU>=T$c9QjAx5I0GSb8Uh2hX1@4oLy(eS6?P)m2C4i$YmlmvH-mk@ajAAU+z9t$eO z5^DTWS|&mAbP`1-x+6Fx!#sEb_-&UrAza7tk$N5y)(*Q)#7hc|=?z1TA3rDA)l>IE zm<#ZXxTThM_;j9%u5xITeA9ADhRJe z9KrIb=j_UeO;aeaK7Bp0WYTg3`2NpRezuX;dOhbMOb@n6P5QO^f}o_Kir{b46RYC07COsmNLau_Z!f=mT5Lg4 zVthwaVum>jjzQbi)TH^xejjUZTjBn7c|sF|w!Y(DrR|0pn`cF5U3{iei$QY|W(Qc} zqNQlsT&ryNgJ|dJD*Q@hZ1T5WgPWa&4AOXZBCkMsCdTyIOC;iIR+rbS?@*8}=_$5ab1qPMO`G zT>d{>Q7W;(Cfk-r?f3=zLRE@sXzSXrj~@(ZB5O!{9{4T(uT3#_9MX67BvKJKMv zXwsWCL{H|bLU(jkU&z==+xZAl)9Q=t%}t#J)oNG(qd;it@qFTz2-h>|8l*-iu~A&p zBGv$u6viGH4!t-XGg3ywL725mI(%{&YoKk|Z6)|lrPK^%{gtmvAGE$bHivH<>}{Yh zfMpN#3)ZQJJ649|>iBI<=Z+Z#)#zf-aDUr6$Iqr#LQdhVx>EmgzJThB()xADQ5Kxv zEex?JEdIE|?Z=+yxbY36N^l#Zxb9<~9x;C&(IaROD;7dYb}-f1JaU4Uh*Os;Zrcm3 z*Gj*Nn?=G-X=KMqqX5>IaD>Y?=KbO*^veF5e^bEg zPob0ShAyCyu#`|wX3uuh^V&b5j*l*SNSXClVw$EhP7o-hjD#Q2+l!O{pbrhQ9i*mf fE&DJ0>m6TG*pl|y5|BpPFEtmOyHlOx=_~&Lon_D` literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/AnalogStickOutline.png b/soh/assets/custom/textures/buttons/AnalogStickOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d8d71907601d74393ae9514df947db71252e19 GIT binary patch literal 3677 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 W?mz4GDbwrMD=pAAsA>~j!hZk&QN3UQ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/BBtn.png b/soh/assets/custom/textures/buttons/BBtn.png index 99b1197c9982d8d2027987f6ae578a9656db2d26..8e2fbb54b5345f3d11afb2d62e2361d982fdfbab 100644 GIT binary patch literal 1534 zcmb`G`#aMM9LK*S=F-JNZgV--g;jFDm$3ESrp81r!)TF-ZD!@V2$f4@Em3pL4o=9a z(2;tu7ILcy$EA}+E-i`L=-A=tf9U-@@6YpoUO#-E&+~kqccup(+@_?h1OUJ`EC%HX z01$99*DJ_xPO357bQ4^rxVm~^U0n_63|bf^G86!e*ev#8%ySR5%kC%9>@18!hS8a7 z{4P|sElxc`~_v?f(EXA7ym0v&+`_f~&=sjUEa!zBst81h;!Q@`1yMcUCk_h*}h>#@C7 z?r_6h*}4Z}P4{adqi@>QR%?G$_A5~DCl(FiavHz9Bx!b?+fTVasO=1Q!x$*S%p;5{ zWRziJR-VUsbB;4Y{R>ho9dCPap2%5A>Cp|I!xn6P$(A;xyFlWcDrnu1 zc48T=ub3!;SM4}@C9E+?77mx0LU#wP#KqEPC)O7zeT&c*C5GTBA}@aPFY>3|Kosyh zzyS)6$~7I^B#Ly5Ukm^!tNt_uxKpIL3875v2{d#LqNlN6#-5=%wTZNtXkVr)Eh;LM z$^={)p&`uBGX}8~X1D=}J>lVVX}bmh$PQsq&R%h23-1Vc9Z(bcl{QRBN9I`{ZkOyX ztU}Tj6kSXJv0{qqUqYEeqNRHwH`2WgCy~wiP<$jEW1McZC+?YO{i6HR;A0jQPVa3V zE&sgmSF6q1tujU58{hMZj8aE`t_tuXOd}ayFajFIdOY|ke6XrCTapm{wzn6~XV*2X z-FL(q=O8*)6LR}U!bdO4|w3Rpy$}kqC`6;{@lQVIe z*OJ$hV6awkI40js`^ii%JGnVApsFC>pZcwxG0k500zuXp93+#@Lqt7rx>;U%vt!p* zAqLFk?6^9(zT++*ZToP~L2;f}%b=$?gN}0hFTc2jCRE9#Z>Y63Blv9bVrszcEh@Pa zHUj1C1?CE%y+Qa@4_sOK z_tIT)_m*^oNPIe_KqtE*EbOC7ZmqWk@Dc*yPaP?9t9;4@I4XUyqdqIK50YQQ(RK5 z0uoFpzilb5?t?xU?Mys!9paVyy*^dyE8wclH;7IpL^BbZqnaA#NrMY(<1o9(i&8BhS5 z40rofXo5T&Hd!ioXYzWF8jrf~5}f)!;y`<# literal 1300 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 e;TaV literal 11241 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 U5$hkg$@^Cfx?)}Godd7^16AUFtN;K2 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CLeft.png b/soh/assets/custom/textures/buttons/CLeft.png index 5e26a2067e159b8bc2c9116664f9e72b5d7896fa..43b04412fbc0752e6589dd93235700e259ec9f64 100644 GIT binary patch delta 1127 zcmV-t1ep8aSBnZEiBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9Fq3f#6@Ms^ zeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9A2ex5Qd}Gb*MfsTi&X~~ zXI&j!1wrr!#M!|~(M3wUFDbN$@xtSMoOjRRz54*6QDLgtH3_JiWu)RUF`HWzdtTwg zCOGqFI5i)8hqXG*N+BH&4r06{6;U9MVNpi{LDua<@0e@AfkQ_hw zAN-!JS(u)3lL9fI`^C0D#(2000SaNLh0L01FcU01FcV z0GgZ_00007bV*G`2j~GF7b`nucbn?~000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}0008wNkl7zN;S;|`K80Ad1Ql9B;HVkm-;36Nj_(n%U7 zK(GMbqqT1zNL8sVPy_@g`96sU#DlG$_~_g?@lBIaA4`+K8xVhZOT`G_d3P5%>XZFZ zGOo!u4?juLmZVLRu4I-UY4=Vaen&XMM!LDoK~poW$-xURszp~a+dIy}6on&fPAHyd z+%&m*X(;|PB)d#BN#O_^(H2KF-`@Blo9vuqZo2DbWCZZw_A=AA4#p&@$<^&;rY5X8 z!deDnYR=yIYCC`1Jo zcF?T;y}*w+CYmD*x;1K#nj>h9PiUH4`44E0pfzfbnj@^m3;$ETeDpaq&Fj8_gK&h6 z)F=CgEp3Wm2VR$e6>qq|d-E>$sd)Q957rD;|-Z9=ias6qIz@J(p5RNcN zeaU1SkBxAIC+!_)QM3A80ZX#5Rf2GYL91P6t6t)Eoz^HEVd(AgG;K=es|v`z*+Jg>Gk2G1hBN+yZR{a@$nveRtra1XLlDls>$>%1JYjAmesKK zc1|+yOC}|+53`!g1*7H&8|UUS2Tjd%`B2*bZjv>b*OIS7Q8>cZ1m!aPeg)+?Nn4V( tPufv(-E~>G8x50DA4`+K8w?j4>?hWcnVy|(M}+_Y002ovPDHLkV1kll_JRNa literal 11232 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 P{-XmPLv+0FK)(1tYki4q literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CRight.png b/soh/assets/custom/textures/buttons/CRight.png index 9e6180639b9b332424a585c3ba7e57d287742779..c2d1afabfa0994a1c73817d8172f7bfba44b0433 100644 GIT binary patch delta 1163 zcmV;61a$k9Shxy*iBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ zsT&@D=m8!VEEaF+QCR>002y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00R$6L_t(|+U?!VO&d`dhS7KING!8R15N`VDgY`86aW$x7*~J<1>jT?Qvreom}NF; zAj$Y<0m&l5{3K@Zc+Qc$KrHSsLXW=dv3wJgaU)ZcKpY5vmZ@?JfWO_GWq+RR43bev zM!9<>NnIs%k~CE&`I&nA`0i(M1lH2kd3J{-;PDhHcKnRfl&4E%dQKV6?^yzDS0Nl7lQ&oeeT0-X$F zN={z6E+<=mhna{Y(A%x_BJ(PHU42j^j?kwto@O){=C;i>=S@C#@ga@(9HB?5Vf*g| zzQvj*M_{F=#x75fCPy$ezPjNs7bZu*)VK!Iqsb9^VDK)VT3YJcBh%xqZ8gwW9~MrI z$&NSzE2S!}PHkmDY)0Y;td!Djn7*&THHahdENzB=X=4ShK^%c+sass@>k3?hI07r@ z{W|;+;s`xZwL7(KtiUyhBk;6&yJ32;E2ZkzxATZ2^uQpwT=1(O?#{w#8|Z`Uv)twl zpBQf)b*ncfN1zRL*DhEbp(o~54*IyZI0BE_KFqA7{Zj#}WY)!_62uXDq%@hdy~S;s z?oEw<;s|}49*?{)F~7;%Ii+B(eSK9EoBhW~p%ebUvF2bXgLfKIwU zyLvyb@$sIHpII%A&~rCu*)Pd>nSt!`S=F}HK$2whDAReBgDU?Yvyx2LC5$FV;E${G z><&xD_g_l;>`AgD(^BR0x}M002ovPDHLkV1joC1z!LF literal 11284 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 a-T&@2YJoFO%U-?#^v9T38ecYa-}N5>&$}J~ diff --git a/soh/assets/custom/textures/buttons/CRightOutline.png b/soh/assets/custom/textures/buttons/CRightOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..d450084ead24fc1b64c507881cb1f094b7b7a572 GIT binary patch literal 1541 zcmcJO`#;kQ7{|YJTW)EIg}I!TyO!LVLsn*OGe&fqxnHJ{+gxU(T+&S@n+|4{UX`4P z&Y4T)62fUYi<09OCUVJP$mL|xS${;&>-9XZ=k@;O^Ln1o^IZ2NVpWy2l>h)x#p7JO z004xQ_BA^cq&3AEXP_dANfV5h-Bfy?Y{b zf;5(P>GTWMVJ(sR^_imRvmH7e)+N8aVcbD>xU!rt5FLYh<*(~MLo{x6J)3>fYK=Z_ zWa|Ojrrq|lJijth z!-6+IDOva&u%cBHj4k<8vm@74{R#TTjw^0#U)JA;x@_hMdy z+Q?-w!cy`)?4jDxE0nqmvM`v;B<8jMMlwBS=EL>^RVW5GD$zQc;I|l3Ulf7~SQp>{ zzy^wr%GV#462({?DINfn)qf-i;Bfa!Avgi=jseet^q>}y<=l=FO0r*hhqT+(WUd7*ZNuws{wC( z8E~rtr~m|efZyf3GsNdac4^!r45aZ5;=jR}_@*&2J30NTA2s{pH*3BFTPpao;t8P> z4qRMy?3w%3UeA!taa;LjjOVay@PC>;6ExWLb&FppV?_oB#8x^3zWt%=UAstCuF>T) zq#amMtn;!Rdl|VAquL2Y({A(8R8~7gVN4Tio9D3eHs1rvn3eFgzHX!kZPE%W{lFot z_fy;5e$_VEvck3^&b%72a6aHoJRFvhrR_Q}b+^Fg!E|1K1b>iLATY5<*z)yH{}E7& zu%DZE&W*kNi~MAi(Y?5qmfcD@9#H$CX`e7|C5xM+FlC0?h|BNd!c}lu^d9+Y0zO0m&{ zZ)>H}X*lrS%730Nz$WdSdg90Jz(Wn|7544GP38)DBsS$tThac++aXbZ)<*{v^0m`JmLWi)$z?tc8ZU{oz0EAZ|fH*SXvHe5kcsqr3-Ed!4XV=H6j z)_Zf>Rv`g33BKM)nbet1yN0IGw7^7P{#>7|I@2-~tKU1#-0a_#4Ocl!O>Hh;bb59C zK;=73yxh9*xnYsh$2HFI?x%IDk#xO@9kRXaDeibmBbV+wMp+p~9FYp@l!PezN93`Y zHQ{4b^E#hfqAr-jf@UMC>2XzUD+oRl{ajlJ86?cJ_|@qbdX`ccCHR5GkEI)$%+~MJ z6duN1QXec`wo}izQ^3=v?y5-oGRtB!`DCWlh}<%VB;i+ogZS?Zo+OGq^~Eu-rWDKf zS*x*)cGlg?5(=^&&TVsRO!3|X&G{+Q@po! zSYAs$EZ{i4XN{{F?#YHPMR-QHi)+fbq5K=oM9ztoTA#4D4PPoiKj&>ke%o@-)8w}5 S)QhkFP{3n|F4fL~ng0X($aydT literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CUp.png b/soh/assets/custom/textures/buttons/CUp.png index 6c0e29d2de653af5f5518cfd1c6a5d3b956b1e33..aca46472857d3db116e5042f097e2ab27bb7c723 100644 GIT binary patch delta 1138 zcmV-&1daRCSD6ZbiBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ zXd51X=m8!VEDC$*4Hf_Z02y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00QtyL_t(|+U?!VO&dV~1>iR}g)9vaxdNO@0tFa}3V;fb;sS6giBkb04P?8>1@Giw zU&2r10JhigebSyV7|m**-poof2><{90001!#~v?#Pb-E1`swyM&EOzklBCp(Ytm$S zwX27>?UHto{5U$x%!mm`c=w@LhPf!o$$$J>n1dLW^culfU;RZjCqKWwZXHu|1hx~5*J%dB{MzDIw%%lGj?jC(H*xrITHy$PJk*CZKkJUd5&B3l2}eLc3rAo*t^Ywd z0uPiP1XB@?!V!3^6OO_W`esp{-B+=0@uC0WP6$Wnm-}a1+txOLSuAWkAsnG+M(1fu zb{9@HnK^h%IKsY7tv4TzCEwfu;RyX~kCV)I(H?6uvzMcAgnqZjMNYLw;RrlzkIS`x z$JYd8U0wI-e{6}x5!~lW^d4V=G`KPf>CpX_the=(+r2XdBH(kZC7$C6on&vgpeF}$?+g* zRy%k%S#2CqlD3v*5L#CR000000001!xFK{I0DxZm1EaN`Nc^1!IRF3v07*qoM6N<$ Ef(ZEcVgLXD literal 11219 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 bZO&Y|BP(K(_C3BvKV^}Y))p1#T%!L4P5g(G literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadDown.png b/soh/assets/custom/textures/buttons/DPadDown.png new file mode 100644 index 0000000000000000000000000000000000000000..cec0af1e5575f8e0e6eebacd062afc96b8440f5d GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}gPR?K3xGnBC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uUs^mK6yskrs_#zw&=1BteW_OBGqIUd#GJ1DDb zdeial0l_shnq7C?2tKh;wsM};)$%*lih@A1hXg24ILUJSdTH#<;yM}k`>a>3XEHd* zFdh+n5H2o!CH?QR9p8P0?tlas3R!*}nw{Lb$FOO(a)Sj^2QEUPkKs|o)|)H}eSgG{ zx9@b2SsmadSvIFOibv_3n#I1%Sl lT5l@YiW%k=<>Tg(=UKIn$db;|#taD0e0szR&GfMyf literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadDownOutline.png b/soh/assets/custom/textures/buttons/DPadDownOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..e8dca39b69449bf33a532f091d6f9649b21d72fa GIT binary patch literal 984 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}&ApFzCIE#bOI#yLobz*YQ}ap~ zoQqNuOHxx5$}>wc6x=<11Hv2m#DVd>-qXb~q~g}w+Xpib8;GzySiY?}g>Sx**RE#P zea~{$)1;G<5{-`USAU+&Ti^6FoAVg1r6<(-Z$LXOsLi56>KTe%+j p`0Ui)D^cf{PT|*N#0=U4&hyXc8F6TrX&HhfJzf1=);T3K0RXK7P$&QZ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadLeft.png b/soh/assets/custom/textures/buttons/DPadLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..2a4a09b7983c12c9ad6888ecdc215309386175c3 GIT binary patch literal 929 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!iLYuM(m)}}64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSE`c)B=-RNQ)d6OYQU* z2g5Xu`aP1>lRIGeA&&9nnfYhtp9MK!NPq)w X)7&PfTBJQk1f;>!)z4*}Q$iB}bC4wB literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadLeftOutline.png b/soh/assets/custom/textures/buttons/DPadLeftOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..ba3dbf4e8a15d38b6f7407087d2bd118069aa753 GIT binary patch literal 953 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!F1GnUgMmVlC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uTx;OXKRQgQ3;t&O>d4Fp&(BtLPSU}n zGTnC*0v82tI=NHy#j#!nMnXMYuq?W41AH(&pFXa4W{ zuD`_xo>)x!{`cX;&m=m=T#)oydV5>@~Bz};iE)qM#?GHz*cOBqg0 y^vljYeWqK*!LlfR!u8Bqc1lT;K{<>FV6#}ds6*>{pk|&gNVTV{pUXO@geCytfi*V( literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadRight.png b/soh/assets/custom/textures/buttons/DPadRight.png new file mode 100644 index 0000000000000000000000000000000000000000..e7854a2192b6af2b3deae8700e4baa3f0f300fb5 GIT binary patch literal 922 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!CJvXvM4*sliEBiObAE1aYF-J0 zb5UwyNotBhd1gt5g1e`0KzJjcI555oJzX3_DsH{Ky;1OxfdI<^ac4!nqiZiT%P?<@ zWeH(gx?{4s!a+3_^-p<>TzWey|9S`lO&${9!UUzJZ@h;mNXy!~ADJ`rdgiQola{Hn z3w~(UQ~DKjYVoxyG4@k}*TN?R>219hC#2#2L(k)~@>z?ng!*HJF>hx5-!b{klJ1j& zQc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}bN4qb%s?T@64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSE;^mK6yskrs__Qu@91_G=Xk|#LYbcLVf6IpPs zOx;21&`gzkN1|L7aGRS=KG6E0t!n)g2GRXL9t5Va0Bsl&z(l2UL2c~ysphp+eH}Ze z6wO-pQYka)lOj{t4c8-fOTSDmw(DSi%JG$B(j~*^d#1CT608$na#i{450Qi4dLIAS zay{m~=e76$FMt1=7db84G_856@@+Go!!fo&eH!izPdVy8Ft<&+S$t<{9 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadUp.png b/soh/assets/custom/textures/buttons/DPadUp.png new file mode 100644 index 0000000000000000000000000000000000000000..8d70d96dad432d4f23185bb474e9f62bbb4faae9 GIT binary patch literal 968 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!)wO;{KyfTt;u=xnoS&PUnpeW$ zT$GwvlA5AWo>`Ki;O^-g5Z=fq4vg>lo-U3d6}R5r*;shULBQc+tTUsYW2wd@?M9^% zLuZ|@PMi*ltX@3fm?NQNoSbIxJx(Kb%fajCSi6803_j5CU#)k6>|+bQnLE2X9v*+} z?Glr<_IKqx|79%q!`v>k1)VZ8<`=wpcki#B4n5=TwfB#2(n-I}G&|W_`te8e^z60q zW*!|s44T;XHO!pNe(s$Q&ykIyhndr@A2Su^xPD)|u!QI$F6j2m(bnQsWMtcW`7KC;r>mdK II;Vst0Pem!Q2+n{ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadUpOutline.png b/soh/assets/custom/textures/buttons/DPadUpOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad2d7959750842c432eb01ab039b72047d1f8aa GIT binary patch literal 993 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!`D`cI9Y7(;64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSG!@N{tuskrs_&PLxO4gwArC4CsDB-|=U(R$dm z;j!?{rKS2)7*y6Bo~y%na<1|Oheuo9w?6Mx`yrQKAPBT#@PUHtOB}ZheJ{_L`Mg6y zzwVxL()z9Y*1Z0e=k;N!ag*7Z&o!scT<>_n-!G@M==_<>20R;cZ?|VQp53^#_v2gZ z^z60%W*!|ojGNf*HOxG3Z&7V#C~!Qi=lI(VQzk8)@@Ch&j|JPz^?*V#tnWWF{**b6Mw<&;$TX{Z1MH literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/InputViewerBackground.png b/soh/assets/custom/textures/buttons/InputViewerBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..091d686c0006e444615a666f5e297103ff343b5e GIT binary patch literal 941 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}DJJ6^Wk4ax64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSG6c)B=-RNQ)d#gLIff#-n10X4RYfWyYjKU^62 zwz)X`-vH$=8 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/LBtn.png b/soh/assets/custom/textures/buttons/LBtn.png index 2e0a8f00c3b02c2b5d254311bfda6a703f13efa7..351ea383a7d97df9eb27444e5bf5d6a4dd18b64b 100644 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUHTkS#KzRnq64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSGk^K@|xskrs__C?>r1`@3o@4r(hY3_57SfVtS zrBujAErIzIo2(*F&}?=A{tph)OG3Dw>j=DDU6tzX$pW+k6Z{F>b*=gLzWD1=@1wJ0 zy;gn>u8~w$3i4{7a%tZbBQK`^DKgt{=gtqRn(}|mLY>0~Z#xsG z=e+mQWLHf%_W$l3{xw^z471pdef+)BQ0dyH_?*8t`63=!%=1$}Z1ML?#cC#<5}9Bx z^GW`fqpE`$#jN@)pNF4Z9=SG*T{L0gV+r~7%X&7&-#h!eZ^MH^ouxgN&*#1opTEPj zd1rohvHgb%o4(m+)sz-Z{$IX!>s0h!~u;e$N`HuDdzk8suV6S3j3^P6 literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijK0(?STo12?guU_r!>}+jqU0+|neEIV7^78rf=jZ3=o12?YpFUk*Uq3rL zJ2^QyIyxGt>C%_@*FZ|3B*-uLKPq5&pd2d+l;bS$h%9Dc;5!V$jK}j=qyPmMc)B=- zSom+fd|RklfyXtFOXQ-{&;R>#g`8&j9e(g-Q@qRhOXjiBU#uT2(@kS4**imU#(CKl zH>=Mt7u>fdj^FHoaY~cK`kK%F3Xhlt9!se(G~ZCj6!_(+w4syZAe)lUgwNMl1sHCe z({_0vu5QZ$*1w7wbzHiqGTQH}%=ug0MN4vl2 ezQ4t`d}Ac-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUB?)$>ETE8NiEBiObAE1aYF-J0 zb5UwyNotBhd1gt5g1e`0KzJjcI0FNdgr|#RNX4zUx8HW&F%V%5@C^2t!?mo%qP61D z%9NX4i%#$^Y4)+2AvDKH=k5H|#62y4nb_wPO9{j*JYLJz4zvXekQe!X_26TRvaQ$h z*KV~tc4K#!dNGIM5ea?6W54Ho))D&Q-}cymC%Nb2?jP}{8pWDV<3u)merVB`9H0GH z_1AT8&Dyh;@hXhc`*yG8U$Zr<$B6mt$EDY9L|OY^o)UXB*zN8noxi^}H-F=>&g(n9 zslB^S?J+^%Az-37WioX zjpIF?C((A%^v=4g%P+rNx3z5Y>4yayf(}nh&3oPc|Hs+DL&UjN*C0 zUg;b6?<_pcV^((K*MZkxt>pWU3pl+v`hU~4TR>&OLK_}$t=gNk{o1>%wR7*Y&tHF0 pv1LxsuZQ0qu>{S~5PDE6$FOoz^>L1~oSq;Td%F6$taD0e0svfcg;oFn literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RBtn.png b/soh/assets/custom/textures/buttons/RBtn.png index c255643c35893d1e10a5c7056459a364ff8d9a16..ecb96bd6c10fe4736841b2ced7f1f0f404adc657 100644 GIT binary patch literal 992 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUA-j7<$AChTC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uUc?&;zfQgQ3;?T5b24h*ah?rr1{-q7?`K_Tw} z+cD2BgN_}IiA*vrarLvqfuw7i+N=^5Ecta}*$Y|qnDFagcgI(Tt$kZ4(boKwW2Sc3Bh95IUXT8D sT`X#muCV*Dc+Gr%CQJ_u4Us?f>1VD46sEmde;?#vPgg&ebxsLQ0Izjb6951J literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijK0(?STo12?guU_r!>}+jqy?pud`ucivbMx}@a(#XM`Sa)J=jTtKK0P}- zJ2^QyIyxGtsej3mM?gxTB*-uLKPq5&pd2d+l;bS$h%9Dc;5!V$jK}j=qyPnXc)B=- zSop7B*A@50-GH zDcompl@4(gy|8%e83*+lrxFaG%}#jA`GU1rP=}*uqU1!qz5^>dH<%ID@VQJw{43z!zQ13&09ha znEf=GaFs_#aPg*lza3l(Ok7<5=~>MCuOr$1M{3Sc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdU-p$wSje$avC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;tUK-oSrU@Ar-gY-ac4(+kuC{p~*{eje~BBUdxxI z%_R#0RnwL@Eh?E1$m*jg^68{=+LIoWx~F@7KmOYw-Nf*GT_(^POz>c?6W4?L#|rPH zrpXKL&Dmp={!B)2`Qe8f!et&dYb-4}y=jj|*LTrV+j8eG%bb6Z|-X>xq4yH%$w_XDYX`+&RS-v^zHS#jkEZd=(g=H2`UJW6LDX$ zr+7~I`SVMs#HGdcUp>9)P1xMWA>K9rEDz=0pSA4e`mW@YXN>w5pZQa`GiFvt#QMK0 zRPCP2JmfuWP*XnT`NF*4B{p*Nd#(oTJe&4e)!5(Y<43N==LFw9`1N4+s(p4Gm|-zA cL_Ylg&8sL=9ea7Qa}mhJp00i_>zopr0ED!F1^@s6 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RightStick.png b/soh/assets/custom/textures/buttons/RightStick.png new file mode 100644 index 0000000000000000000000000000000000000000..6b8490aafd7e750ab8e46ff435a3f2196d94e6a6 GIT binary patch literal 2150 zcmd5+{X5g^A0K6kZ^v21iVyl8=QxBAWkOR7n};0oIP3*Zs^&e5IY)5cun!8ZM18;n1TrJ+?A+0IcE@7LBtk@V7zCo1dnMP#smJ|r z<^@kw?sX?ChTf$rH#K`E0;9?d{_~-#e}W0^jkbA&lScrcF#c->lIf)g565W+D4ct* z*gM&c9!6n0jP)NfK0KMf!lnwOom-GUe+l7Cp4wk^C+z;5scA7*l^!VV(SyS5FNRi@ zIvEpY{em{eTod3@zv(Nf-n>67j?Ny+TDnd2?bYZtD=y^I$`HMnKhCGPS%vfnLLK9()SWOG*rf{r|kGKi=j zRX+zfJ005(I~l2WPhJ@|b;`r#{%h-3QtiZTG&Z{a1KyGSpm)7~+E+yy5 zo8H}e+Jfv$E5+UQYn83yMZ{9bPWUV)YOCfz@Ta`>WUR8b+#XTa(*$hZM%tie@N4v~ ze+}erKfHEcE(v*$^jxkRdzUm+f_)1-P_g}uz)jf$0P^#w=YbnZRML`oM;0-(s@SeX z?(NXYp@F1cgP{`*!6NT&w+Y=Tn;f;mI*7Ov6&vw*oB= zA(T3vKfhB0b#CBSFE6vew*Ply*2{TEq08CQ+WJPm$NhDKWHLWDo;5h=EZw)g0cdKX z__W0+GT&4^`9`AKjlo!*y&pa-MR$? zzUB3DhM)|o>^PgS{4trkCx%M3fM#?*A3p%ic+}Zhr_3FIg1yj=vD&!{vXy$}=l+*>TaAq3pvynU&huuo!Xt&x4oEA7?Rse}NT} zFFf!p(0QK>06?#(l{5~WGZeddVzdb%zWs=$6dU#IvtB7LJ=}LTKj5R7=1*Xk?=N3l zA#aISH>^hAtT!+w=yN9X<$9k40zp4hrEtm86B8E~*Hpl3UaW!M@ogQg5Xn|tAB?UF z_VqCse9D=xQ*S?>txf)=gmyu?FB;b>!W}J?5UIu$>mPGlgO=EemP=oyvA3_6C*6vl zzR9==i^Hkrz~ZK4i5ptVukt+>O(Sa3;apB#33p_s#(#mm*8e$l5Kma$RUcf-<8ddv z9(*4&|4^$y$9-^MV1S&!ZL~dEj5qWt$dJZv5^*LD_Uy8EqM6!AjN+T%1J+o6mjPd>Zr>-7`gIQHLQnor=i-q3DIAy!)1{isSp zOwD4DxwJ3OCa_?X%i)`fB@$e%x>d#O_9puS!6@;w*_pMcMV}{_vaiF#xv_f#y@e+V zGCN0BoiE_Vi}1CFa#V%$TO$)qb>F07psA%*uUt+RBBsYCESHKsoL1|UdN_DhRu}VP zwklS^s$zVXl+lxF(E4&M$l>1bNK?%65A7f;083SF9g9#y#WhzqiDaLWT*LH%^xe|G zrqLUE`UeRoU%XLY?C+uumbY;AAHwk?u|gH0GB zk!Wg-A@XOySX~aspS_{@TfN};OTFsigDiVD1f!&+#2=pe%o2Gm1QQ{n zlljAu-2b{z;5!mXy2GjJy=5K|N{+MIvW0~ob@R~TnHh`7Vx6n9`RTqwThQI+IRp6~ z0RaIWckpVUNc3)JBrA~q$JT>KcT{Hk3r`<=cQW)_5RG!PuRkCB>p%IZ B&b|Nu literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RightStickOutline.png b/soh/assets/custom/textures/buttons/RightStickOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..8fbd54fcc36d766bfb97b99365685f88426c4dbf GIT binary patch literal 2407 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 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/StartBtn.png b/soh/assets/custom/textures/buttons/StartBtn.png index c3e08dc3600853304c65a79b2ba937d297c03c78..ec85f261957998dde16f4ebda829b14c68527681 100644 GIT binary patch delta 786 zcmV+t1MU3WT+Ii6iBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ z@f{w2=m8!VDm3iVw>tm;02y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00E>)L_t(|+U?xIZNe}ZhT)G+;!T=OI!Z=?O#+jIP0S&w6sbss)(0zj9_hdO@E=~; z2uJ_`0000000000000000001h#mNe2ttKUZ$ybtLo%?2Pr{rQwz@eg8ld&fCmlCbP`}dk*9DhcJH6*#-g6>F48lO?N)5fPebz6dP;pT`qvO6upR;&?m1aU+hIe>eEGcMMMII=g_P67+!NLOy1oB`06nw)(J9N=dm z9E+b10<;OFKb`;%70A(38sK>(hxK#FX>&`Q)^HXZ0+T@^WRp-LQ5W9u0E?Lpn2Z4b Q$N&HU07*qoM6N<$f@-Zr?*IS* literal 11868 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 diff --git a/soh/assets/custom/textures/buttons/StartBtnOutline.png b/soh/assets/custom/textures/buttons/StartBtnOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..a7902edbdafeb8bdc1a440f700e08cdc06664c32 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdU{j_a$*MUNkC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uU6=jq}YQgQ3;orAf}1|n<^+|@s79BBhvF<;eRAVlf z9?G!{4dryYM1N>;I65$bu{77){C=pUQQ l={zhm$FmjHw?l;2AiJ(G!GtHH+Tk3?#h$KyF6*2UngC=DT%rH~ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/ZBtn.png b/soh/assets/custom/textures/buttons/ZBtn.png index def8d9a6da2fcab6486b6106064d9fcd11dd47ba..4fee52d5762f0763b5fb1a5059937b35c1796370 100644 GIT binary patch literal 1005 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUnVV_y2Z2J8C9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uSm;_2cTQgQ3;?Tfz60TOKw|Fyf$SfG7_kLeLx zUc#Iu9L*8t26GwM8!u;X_3aW@lbip%@AmX(k0(qy3raL3fFGNknm%pG{XM1lp6e06 zUjJotK8pw*Pn4MV^nk@b;n?d}KikOnJj!*R8FcG=t-a?#RnMj(iDRL!D(CSV75J(; zO3qsLQt44(r|5cL!LMbz|60uTd!O~-NyMvOpO=2EvvuOvy;nVGA*S>EP3bT8{XaWa z0C|VXj|o1G_;Io@C~-@5g!SqRH9S`#-I*%9TG}ct^W& za`MAftEx^|%1<@uv9K&^JkP%V(@zBw{5TLw53ILlJ`@#Lc&OqQJIH=dS3j3^P64z!-JE+(X)vKtE{9js;Vf8EX$%O3WC7%d^Ve9S=K|x zSrm&?(;VtXPt{sVp(e={K?-@n<#>zDYBVELR4$!iNs=OZji^&AwW>iQ@@gd~4(y6= zm0csWb>C7wv*74*QIpJqpvyT;;%lK5d0J=}JX0!aIYZ%8k(G0_A6Sm77j4zB6ipWu zH76;YAY~EV`9vRg<-M41`AlqNN;2VcfRhP!yBNpl`)HadNysn=umHFNFa{U^^Z?ob z4S*P+3=jag07U=;U^c^kADc~#B6MBUG!%ryJc&S(i9o_ms0l9wumLojPjKADevEA& z>jp+52K2s5&7JhLm>!$tKqvN8=qS*V0db7jMvM?`Laox7yY_tk=gIf%qo)9#`0M?v`Zx4T z><_y)E_`?O1>!Oi7k7B}p>t2ay!`d*t>=6=f9%hd^)>U;o%pVAmmWTUJM}lvza;hA z(cv38M|?_9rj`P~oKp8a)c Yb??E?_CD!fN=}5$jjjCd`nlKt0Xc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUalb9cJb^-zC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;tUK-ES@foAr-gY-aeRn+d+W!f~;2S3Z|_By96%H z=DXCm!0U`htIJD;09GHx)hAUQQk>Yle|N`m{twA*5!0A}_K*PnYl#1+{tJ+g%{!P*f>fr_&ELa%f*FVY8vQ8)N*Y~GN>Qf${Qa@h# z@lQa5*0#WDT)OQ-x>CX=0Ztx!hw^YO1$x`G>Rek)48D?DH5 z+Lrj^oz{8h%in&MSlN0qWq&=DYc^YdX63Y&q$5vG$kxf%Ouo;~NJ97wgwlUI?=RX~ U9s92IvpL9mPgg&ebxsLQ0BZnzNB{r; literal 0 HcmV?d00001 diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp new file mode 100644 index 000000000..6b25589c6 --- /dev/null +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -0,0 +1,519 @@ +#include "InputViewer.h" + +#include "public/bridge/consolevariablebridge.h" +#include "libultraship/libultra/controller.h" +#include "Context.h" +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include +#include +#include + +#include "../../UIWidgets.hpp" + +// Text colors +static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); +static ImVec4 range1Color = ImVec4(1.0f, 0.7f, 0, 1.0f); +static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f); + +static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed", + "Shown Only While Pressed", "Always Hidden" }; + +static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" }; + +static Color_RGBA8 vec2Color(ImVec4 vec) { + Color_RGBA8 color; + color.r = vec.x * 255.0; + color.g = vec.y * 255.0; + color.b = vec.z * 255.0; + color.a = vec.w * 255.0; + return color; +} + +static ImVec4 color2Vec(Color_RGBA8 color) { + return ImVec4(color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0); +} + +InputViewer::~InputViewer() { + SPDLOG_TRACE("destruct input viewer"); +} + +void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTexture, int state, ImVec2 size, + int outlineMode) { + const ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SetNextItemAllowOverlap(); + // Render Outline based on settings + if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) || + (outlineMode == BUTTON_OUTLINE_PRESSED && state)) { + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size, + ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + // Render button if pressed + if (state) { + ImGui::SetCursorPos(pos); + ImGui::SetNextItemAllowOverlap(); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size, + ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } +} + +void InputViewer::DrawElement() { + if (CVarGetInteger("gOpenWindows.InputViewer", 0)) { + static bool sButtonTexturesLoaded = false; + if (!sButtonTexturesLoaded) { + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( + "Input-Viewer-Background", "textures/buttons/InputViewerBackground.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", + "textures/buttons/StartBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", + "textures/buttons/AnalogStick.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", + "textures/buttons/DPadLeft.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", + "textures/buttons/DPadRight.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", + "textures/buttons/DPadDown.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", + "textures/buttons/RightStick.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", + "textures/buttons/ABtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", + "textures/buttons/BBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", + "textures/buttons/LBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", + "textures/buttons/RBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", + "textures/buttons/ZBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", + "textures/buttons/StartBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", + "textures/buttons/CLeftOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", + "textures/buttons/CRightOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", + "textures/buttons/CUpOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", + "textures/buttons/CDownOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", + "textures/buttons/AnalogStickOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", + "textures/buttons/DPadLeftOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", + "textures/buttons/DPadRightOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", + "textures/buttons/DPadUpOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", + "textures/buttons/DPadDownOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", + "textures/buttons/RightStickOutline.png"); + sButtonTexturesLoaded = true; + } + + ImVec2 mainPos = ImGui::GetWindowPos(); + ImVec2 size = ImGui::GetContentRegionAvail(); + +#ifdef __WIIU__ + const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f) * 2.0f; +#else + const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f); +#endif + const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0); + const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED); + + ImVec2 bgSize = LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); + ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); + + ImGui::SetNextWindowSize(ImVec2( + scaledBGSize.x + 20, + scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f) + 20)); + ImGui::SetNextWindowContentSize( + ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * + CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f))); + ImGui::SetNextWindowPos( + ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), + ImGuiCond_FirstUseEver); + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + + OSContPad* pads = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); + + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoFocusOnAppearing; + + if (!CVarGetInteger("gInputViewer.EnableDragging", 1)) { + windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; + } + + if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { + ImGui::SetCursorPos(ImVec2(10, 10)); + const ImVec2 aPos = ImGui::GetCursorPos(); + + if (CVarGetInteger("gInputViewer.ShowBackground", 1)) { + ImGui::SetNextItemAllowOverlap(); + // Background + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // A/B + if (CVarGetInteger("gInputViewer.BBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.ABtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode); + } + + // C buttons + if (CVarGetInteger("gInputViewer.CUp", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CLeft", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CRight", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, + buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CDown", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode); + } + + // L/R/Z + if (CVarGetInteger("gInputViewer.LBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.RBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.ZBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode); + } + + // Start + if (CVarGetInteger("gInputViewer.StartBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, + buttonOutlineMode); + } + + // Dpad + if (CVarGetInteger("gInputViewer.Dpad", 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, + buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, + buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, + buttonOutlineMode); + } + + const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; + const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; + + // Analog Stick + const int analogOutlineMode = + CVarGetInteger("gInputViewer.AnalogStick.OutlineMode", STICK_MODE_ALWAYS_SHOWN); + const float maxStickDistance = CVarGetInteger("gInputViewer.AnalogStick.Movement", 12); + if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + const int analogStickMode = + CVarGetInteger("gInputViewer.AnalogStick.VisibilityMode", STICK_MODE_ALWAYS_SHOWN); + if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || + (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // Right Stick + const float maxRightStickDistance = CVarGetInteger("gInputViewer.RightStick.Movement", 7); + const int rightOutlineMode = + CVarGetInteger("gInputViewer.RightStick.OutlineMode", STICK_MODE_ALWAYS_HIDDEN); + if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + const int rightStickMode = + CVarGetInteger("gInputViewer.RightStick.VisibilityMode", STICK_MODE_ALWAYS_HIDDEN); + if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || + (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // Analog stick angle text + if (showAnalogAngles) { + ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger("gInputViewer.AnalogAngles.Offset", 0) * scale, + scaledBGSize.y + aPos.y + 10)); + // Scale font with input viewer scale + float oldFontScale = ImGui::GetFont()->Scale; + ImGui::GetFont()->Scale *= scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f); + ImGui::PushFont(ImGui::GetFont()); + + // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt + const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; + + // ESS range + const int range1Min = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Min", 8); + const int range1Max = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Max", 27); + // Walking speed range + const int range2Min = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Min", 27); + const int range2Max = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Max", 62); + + // Push color based on angle ranges + if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0) && + (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, + color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)))); + } else if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0) && + (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, + color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)))); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor("gInputViewer.AnalogAngles.TextColor", + vec2Color(textColor)))); + } + + // Render text + ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); + // Restore original color + ImGui::PopStyleColor(); + // Restore original font scale + ImGui::GetFont()->Scale = oldFontScale; + ImGui::PopFont(); + } + + ImGui::End(); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + } +} + +InputViewerSettingsWindow::~InputViewerSettingsWindow() { + SPDLOG_TRACE("destruct input viewer settings window"); +} + +void InputViewerSettingsWindow::DrawElement() { + ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver); + + if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) { + + // gInputViewer.Scale + UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", "gInputViewer.Scale", 0.1f, 5.0f, "", + 1.0f, false, true); + UIWidgets::Tooltip("Sets the on screen size of the input viewer"); + + // gInputViewer.EnableDragging + UIWidgets::EnhancementCheckbox("Enable Dragging", "gInputViewer.EnableDragging", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(true, true); + + // gInputViewer.ShowBackground + UIWidgets::EnhancementCheckbox("Show Background Layer", "gInputViewer.ShowBackground", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(true, true); + + if (ImGui::CollapsingHeader("Buttons")) { + // gInputViewer.ABtn + UIWidgets::EnhancementCheckbox("Show A-Button Layers", "gInputViewer.ABtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.BBtn + UIWidgets::EnhancementCheckbox("Show B-Button Layers", "gInputViewer.BBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CUp + UIWidgets::EnhancementCheckbox("Show C-Up Layers", "gInputViewer.CUp", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CRight + UIWidgets::EnhancementCheckbox("Show C-Right Layers", "gInputViewer.CRight", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CDown + UIWidgets::EnhancementCheckbox("Show C-Down Layers", "gInputViewer.CDown", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CLeft + UIWidgets::EnhancementCheckbox("Show C-Left Layers", "gInputViewer.CLeft", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.LBtn + UIWidgets::EnhancementCheckbox("Show L-Button Layers", "gInputViewer.LBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.RBtn + UIWidgets::EnhancementCheckbox("Show R-Button Layers", "gInputViewer.RBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.ZBtn + UIWidgets::EnhancementCheckbox("Show Z-Button Layers", "gInputViewer.ZBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.StartBtn + UIWidgets::EnhancementCheckbox("Show Start Button Layers", "gInputViewer.StartBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.Dpad + UIWidgets::EnhancementCheckbox("Show D-Pad Layers", "gInputViewer.Dpad", false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + + // gInputViewer.ButtonOutlineMode + UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.ButtonOutlineMode", buttonOutlineOptions, + BUTTON_OUTLINE_NOT_PRESSED); + UIWidgets::Tooltip( + "Sets the desired visibility behavior for the button outline/background layers. Useful for " + "custom input viewers."); + + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Analog Stick")) { + // gInputViewer.AnalogStick.VisibilityMode + UIWidgets::PaddedText("Analog Stick Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.VisibilityMode", stickModeOptions, + STICK_MODE_ALWAYS_SHOWN); + UIWidgets::Tooltip( + "Determines the conditions under which the moving layer of the analog stick texture is visible."); + + // gInputViewer.AnalogStick.OutlineMode + UIWidgets::PaddedText("Analog Stick Outline/Background Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.OutlineMode", stickModeOptions, + STICK_MODE_ALWAYS_SHOWN); + UIWidgets::Tooltip( + "Determines the conditions under which the analog stick outline/background texture is visible."); + + // gInputViewer.AnalogStick.Movement + UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement", + "gInputViewer.AnalogStick.Movement", 0, 200, "", 12, true); + UIWidgets::Tooltip( + "Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers."); + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { + // gInputViewer.RightStick.VisibilityMode + UIWidgets::PaddedText("Right Stick Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.RightStick.VisibilityMode", stickModeOptions, + STICK_MODE_HIDDEN_IN_DEADZONE); + UIWidgets::Tooltip( + "Determines the conditions under which the moving layer of the right stick texture is visible."); + + // gInputViewer.RightStick.OutlineMode + UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.RightStick.OutlineMode", stickModeOptions, + STICK_MODE_HIDDEN_IN_DEADZONE); + UIWidgets::Tooltip( + "Determines the conditions under which the right stick outline/background texture is visible."); + + // gInputViewer.RightStick.Movement + UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement", + "gInputViewer.RightStick.Movement", 0, 200, "", 7, true); + UIWidgets::Tooltip( + "Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."); + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Analog Angle Values")) { + // gAnalogAngles + UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", "gInputViewer.AnalogAngles.Enabled"); + UIWidgets::Tooltip("Displays analog stick angle values in the input viewer"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0)) { + // gInputViewer.AnalogAngles.TextColor + if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) { + CVarSetColor("gInputViewer.AnalogAngles.TextColor", vec2Color(textColor)); + } + // gAnalogAngleScale + UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale", + "gInputViewer.AnalogAngles.Scale", 0.1f, 5.0f, "", 1.0f, true, true); + // gInputViewer.AnalogAngles.Offset + UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset", + "gInputViewer.AnalogAngles.Offset", 0, 400, "", 0, true); + UIWidgets::PaddedSeparator(true, true); + // gInputViewer.AnalogAngles.Range1.Enabled + UIWidgets::EnhancementCheckbox("Highlight ESS Position", "gInputViewer.AnalogAngles.Range1.Enabled"); + UIWidgets::Tooltip( + "Highlights the angle value text when the analog stick is in ESS position (on flat ground)"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0)) { + // gInputViewer.AnalogAngles.Range1.Color + if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) { + CVarSetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)); + } + } + + UIWidgets::PaddedSeparator(true, true); + // gInputViewer.AnalogAngles.Range2.Enabled + UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles", + "gInputViewer.AnalogAngles.Range2.Enabled"); + UIWidgets::Tooltip("Highlights the angle value text when the analog stick is at an angle that would " + "produce a walking speed (on flat ground)\n\n" + "Useful for 1.0 Empty Jumpslash Quick Put Away"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0)) { + // gInputViewer.AnalogAngles.Range2.Color + if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) { + CVarSetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)); + } + } + } + } + + ImGui::End(); + } +} \ No newline at end of file diff --git a/soh/soh/Enhancements/controls/InputViewer.h b/soh/soh/Enhancements/controls/InputViewer.h new file mode 100644 index 000000000..646c15d9d --- /dev/null +++ b/soh/soh/Enhancements/controls/InputViewer.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +typedef enum { + BUTTON_OUTLINE_ALWAYS_SHOWN, + BUTTON_OUTLINE_NOT_PRESSED, + BUTTON_OUTLINE_PRESSED, + BUTTON_OUTLINE_ALWAYS_HIDDEN +} ButtonOutlineMode; + +typedef enum { + STICK_MODE_ALWAYS_SHOWN, + STICK_MODE_HIDDEN_IN_DEADZONE, + STICK_MODE_ALWAYS_HIDDEN, +} StickMode; + +class InputViewer : public LUS::GuiWindow { +public: + using LUS::GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; + + InputViewer(); + ~InputViewer(); + + void Draw(); + + private: + void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode); +}; + +class InputViewerSettingsWindow : public LUS::GuiWindow { +public: + using LUS::GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; + + InputViewerSettingsWindow(); + ~InputViewerSettingsWindow(); + + void Draw(); +}; \ No newline at end of file diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index a295fed66..4cb43d3a8 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -117,6 +117,8 @@ namespace SohGui { std::shared_ptr mInputEditorWindow; std::shared_ptr mAudioEditorWindow; + std::shared_ptr mInputViewer; + std::shared_ptr mInputViewerSettings; std::shared_ptr mCosmeticsEditorWindow; std::shared_ptr mActorViewerWindow; std::shared_ptr mColViewerWindow; @@ -165,6 +167,10 @@ namespace SohGui { mAudioEditorWindow = std::make_shared("gAudioEditor.WindowOpen", "Audio Editor"); gui->AddGuiWindow(mAudioEditorWindow); + mInputViewer = std::make_shared("gOpenWindows.InputViewer", "Input Viewer"); + gui->AddGuiWindow(mInputViewer); + mInputViewerSettings = std::make_shared("gOpenWindows.InputViewerSettings", "Input Viewer Settings"); + gui->AddGuiWindow(mInputViewerSettings); mCosmeticsEditorWindow = std::make_shared("gCosmeticsEditorEnabled", "Cosmetics Editor"); gui->AddGuiWindow(mCosmeticsEditorWindow); mActorViewerWindow = std::make_shared("gActorViewerEnabled", "Actor Viewer"); diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp index 73a3addd4..0e1d970a8 100644 --- a/soh/soh/SohGui.hpp +++ b/soh/soh/SohGui.hpp @@ -11,6 +11,7 @@ #include #include "SohMenuBar.h" #include "Enhancements/audio/AudioEditor.h" +#include "Enhancements/controls/InputViewer.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 8b33a72ef..d74649290 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -21,6 +21,7 @@ #include "Enhancements/audio/AudioEditor.h" +#include "Enhancements/controls/InputViewer.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" @@ -180,6 +181,8 @@ void DrawShipMenu() { } extern std::shared_ptr mInputEditorWindow; +extern std::shared_ptr mInputViewer; +extern std::shared_ptr mInputViewerSettings; extern std::shared_ptr mAdvancedResolutionSettingsWindow; void DrawSettingsMenu() { @@ -245,11 +248,25 @@ void DrawSettingsMenu() { #ifndef __SWITCH__ UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", "gControlNav"); UIWidgets::Tooltip("Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: This will disable game inputs while the menubar is visible.\n\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); + UIWidgets::PaddedSeparator(); #endif - UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); - UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.2f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false, true, true, false); - UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + if (mInputViewer) { + if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger("gOpenWindows.InputViewer", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + mInputViewer->ToggleVisibility(); + } + } + if (mInputViewerSettings) { + if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger("gOpenWindows.InputViewerSettings", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + mInputViewerSettings->ToggleVisibility(); + } + } + ImGui::PopStyleColor(1); + ImGui::PopStyleVar(3); + UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, true, true, false); UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later"); From f7e746e295f4c294796318aa3e32493ff182a842 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 15 Feb 2024 19:37:55 -0600 Subject: [PATCH 067/300] Tweaks to coloridoscope (#3901) --- .../cosmetics/CosmeticsEditor.cpp | 189 ++++++++++++++---- 1 file changed, 146 insertions(+), 43 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 240bf5894..2166f43bc 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -269,35 +269,35 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), - COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), - COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false), - COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, false), - COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color A", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), - COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusA", "Quest StatusColor A", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_QuestStatusB", "Quest StatusColor B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false), - COSMETIC_OPTION("Kal_QuestStatusC", "Quest StatusColor C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, false), - COSMETIC_OPTION("Kal_QuestStatusD", "Quest StatusColor D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusA", "Quest Status Color", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusB", "Quest Status Color B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kal_QuestStatusC", "Quest Status Color C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kal_QuestStatusD", "Quest Status Color D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectA", "Map Color A", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectA", "Map Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveA", "Save A", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_SaveB", "Save B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false), - COSMETIC_OPTION("Kal_SaveC", "Save C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, false), - COSMETIC_OPTION("Kal_SaveD", "Save D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveA", "Save Color", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveB", "Save Color B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kal_SaveC", "Save Color C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kal_SaveD", "Save Color D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), COSMETIC_OPTION("Kal_NamePanel", "Name Panel", GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), @@ -1631,25 +1631,20 @@ void CopyMultipliedColor(CosmeticOption& cosmeticOptionSrc, CosmeticOption& cosm CVarSetInteger((cosmeticOptionTarget.changedCvar), 1); } -void RandomizeColor(CosmeticOption& cosmeticOption) { - Color_RGBA8 newColor; - newColor.r = Random(0, 255); - newColor.g = Random(0, 255); - newColor.b = Random(0, 255); - newColor.a = 255; - // For alpha supported options, retain the last set alpha instead of overwriting - if (cosmeticOption.supportsAlpha) { - newColor.a = cosmeticOption.currentColor.w * 255; +void ToggleRainbow(CosmeticOption& cosmeticOption, bool state) { + if (state) { + CVarSetInteger(cosmeticOption.rainbowCvar, 1); + CVarSetInteger(cosmeticOption.changedCvar, 1); + } else { + CVarClear(cosmeticOption.rainbowCvar); + CVarClear(cosmeticOption.changedCvar); } +} - cosmeticOption.currentColor.x = newColor.r / 255.0; - cosmeticOption.currentColor.y = newColor.g / 255.0; - cosmeticOption.currentColor.z = newColor.b / 255.0; - cosmeticOption.currentColor.w = newColor.a / 255.0; - - CVarSetColor(cosmeticOption.cvar, newColor); - CVarSetInteger((cosmeticOption.rainbowCvar), 0); - CVarSetInteger((cosmeticOption.changedCvar), 1); +void ApplySideEffects(CosmeticOption& cosmeticOption) { + if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + return; + } // This bit is kind of experimental, not sure how I feel about it yet, but it allows for // advanced cosmetic options to be changed based on a non-advanced option. @@ -1671,9 +1666,91 @@ void RandomizeColor(CosmeticOption& cosmeticOption) { CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f); } else if (cosmeticOption.label == "Level 2 Secondary") { CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level2Primary"), 2.0f); + } else if (cosmeticOption.label == "Item Select Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_ItemSelB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_ItemSelC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_ItemSelD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelD"), 1.0f); + } + } else if (cosmeticOption.label == "Equip Select Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_EquipSelB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_EquipSelC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_EquipSelD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelD"), 1.0f); + } + } else if (cosmeticOption.label == "Map Dungeon Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunD"), 1.0f); + } + } else if (cosmeticOption.label == "Quest Status Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusD"), 1.0f); + } + } else if (cosmeticOption.label == "Map Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_MapSelectB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_MapSelectC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_MapSelectD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectD"), 1.0f); + } + } else if (cosmeticOption.label == "Save Color") { + if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { + ToggleRainbow(cosmeticOptions.at("Kal_SaveB"), true); + ToggleRainbow(cosmeticOptions.at("Kal_SaveC"), true); + ToggleRainbow(cosmeticOptions.at("Kal_SaveD"), true); + } else { + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveD"), 1.0f); + } } } +void RandomizeColor(CosmeticOption& cosmeticOption) { + Color_RGBA8 newColor; + newColor.r = Random(0, 255); + newColor.g = Random(0, 255); + newColor.b = Random(0, 255); + newColor.a = 255; + // For alpha supported options, retain the last set alpha instead of overwriting + if (cosmeticOption.supportsAlpha) { + newColor.a = cosmeticOption.currentColor.w * 255; + } + + cosmeticOption.currentColor.x = newColor.r / 255.0; + cosmeticOption.currentColor.y = newColor.g / 255.0; + cosmeticOption.currentColor.z = newColor.b / 255.0; + cosmeticOption.currentColor.w = newColor.a / 255.0; + + CVarSetColor(cosmeticOption.cvar, newColor); + CVarSetInteger((cosmeticOption.rainbowCvar), 0); + CVarSetInteger((cosmeticOption.changedCvar), 1); + ApplySideEffects(cosmeticOption); +} + void ResetColor(CosmeticOption& cosmeticOption) { Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.x, cosmeticOption.defaultColor.y, cosmeticOption.defaultColor.z, cosmeticOption.defaultColor.w}; cosmeticOption.currentColor.x = defaultColor.r / 255.0; @@ -1691,7 +1768,7 @@ void ResetColor(CosmeticOption& cosmeticOption) { CVarClear((std::string(cosmeticOption.cvar) + ".A").c_str()); CVarClear((std::string(cosmeticOption.cvar) + ".Type").c_str()); - // This portion should match 1:1 the multiplied colors in `RandomizeColor()` + // This portion should match 1:1 the multiplied colors in `ApplySideEffect()` if (cosmeticOption.label == "Bow Body") { ResetColor(cosmeticOptions.at("Equipment_BowTips")); ResetColor(cosmeticOptions.at("Equipment_BowHandle")); @@ -1707,6 +1784,30 @@ void ResetColor(CosmeticOption& cosmeticOption) { ResetColor(cosmeticOptions.at("SpinAttack_Level1Primary")); } else if (cosmeticOption.label == "Level 2 Secondary") { ResetColor(cosmeticOptions.at("SpinAttack_Level2Primary")); + } else if (cosmeticOption.label == "Item Select Color") { + ResetColor(cosmeticOptions.at("Kal_ItemSelB")); + ResetColor(cosmeticOptions.at("Kal_ItemSelC")); + ResetColor(cosmeticOptions.at("Kal_ItemSelD")); + } else if (cosmeticOption.label == "Equip Select Color") { + ResetColor(cosmeticOptions.at("Kal_EquipSelB")); + ResetColor(cosmeticOptions.at("Kal_EquipSelC")); + ResetColor(cosmeticOptions.at("Kal_EquipSelD")); + } else if (cosmeticOption.label == "Map Dungeon Color") { + ResetColor(cosmeticOptions.at("Kal_MapSelDunB")); + ResetColor(cosmeticOptions.at("Kal_MapSelDunC")); + ResetColor(cosmeticOptions.at("Kal_MapSelDunD")); + } else if (cosmeticOption.label == "Quest Status Color") { + ResetColor(cosmeticOptions.at("Kal_QuestStatusB")); + ResetColor(cosmeticOptions.at("Kal_QuestStatusC")); + ResetColor(cosmeticOptions.at("Kal_QuestStatusD")); + } else if (cosmeticOption.label == "Map Color") { + ResetColor(cosmeticOptions.at("Kal_MapSelectB")); + ResetColor(cosmeticOptions.at("Kal_MapSelectC")); + ResetColor(cosmeticOptions.at("Kal_MapSelectD")); + } else if (cosmeticOption.label == "Save Color") { + ResetColor(cosmeticOptions.at("Kal_SaveB")); + ResetColor(cosmeticOptions.at("Kal_SaveC")); + ResetColor(cosmeticOptions.at("Kal_SaveD")); } } @@ -1727,6 +1828,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { CVarSetColor(cosmeticOption.cvar, color); CVarSetInteger((cosmeticOption.rainbowCvar), 0); CVarSetInteger((cosmeticOption.changedCvar), 1); + ApplySideEffects(cosmeticOption); ApplyOrResetCustomGfxPatches(); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -1744,6 +1846,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { if (ImGui::Checkbox(("Rainbow##" + cosmeticOption.label).c_str(), &isRainbow)) { CVarSetInteger((cosmeticOption.rainbowCvar), isRainbow); CVarSetInteger((cosmeticOption.changedCvar), 1); + ApplySideEffects(cosmeticOption); ApplyOrResetCustomGfxPatches(); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -1800,7 +1903,7 @@ static const char* colorSchemes[2] = { }; void CosmeticsEditorWindow::DrawElement() { - ImGui::SetNextWindowSize(ImVec2(480, 520), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(550, 520), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Cosmetics Editor", &mIsVisible)) { ImGui::End(); return; From a7b8c1dbcac917440bfe7e59c736ea5e855c9959 Mon Sep 17 00:00:00 2001 From: Josh Bodner <30329717+jbodner09@users.noreply.github.com> Date: Thu, 15 Feb 2024 17:38:28 -0800 Subject: [PATCH 068/300] Fix neck slider (#3902) --- soh/soh/UIWidgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 8de4e9e9d..4817e85fc 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -449,7 +449,7 @@ namespace UIWidgets { if (changed && !(abs(oldVal - val) < 0.000001f)) { std::stringstream ss; - ss << std::setprecision(ticks + 1) << val; + ss << std::setprecision(ticks + 1) << std::setiosflags(std::ios_base::fixed) << val; val = std::stof(ss.str()); CVarSetFloat(cvarName, val); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); From 107a365b71f8330559e667495174ba0ebc253e22 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 16 Feb 2024 01:38:54 +0000 Subject: [PATCH 069/300] Add safety measure to Scene_CommandObjectList to prevent crash (#3904) * dont let k overflow * Update soh/soh/z_scene_otr.cpp Co-authored-by: Archez --------- Co-authored-by: Archez --- soh/soh/z_scene_otr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 54065e27e..33104326e 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -178,7 +178,7 @@ bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { // Loop until a mismatch in the object lists // Then clear all object ids past that in the context object list and kill actors for those objects for (i = play->objectCtx.unk_09, k = 0; i < play->objectCtx.num; i++, k++) { - if (play->objectCtx.status[i].id != cmdObj->objects[k]) { + if (i >= cmdObj->objects.size() || play->objectCtx.status[i].id != cmdObj->objects[k]) { for (j = i; j < play->objectCtx.num; j++) { play->objectCtx.status[j].id = OBJECT_INVALID; } From e68b281b18f5cff7d3bac92d4de797043e207ff5 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 15 Feb 2024 17:39:24 -0800 Subject: [PATCH 070/300] [Enhancement] Preserve minimap toggle state between areas (#3906) * Add enhancement to preserve minimap toggle state between areas * add map toggle enhancement to presets --- soh/soh/Enhancements/presets.h | 1 + soh/soh/SohMenuBar.cpp | 2 ++ soh/src/code/z_construct.c | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 8a9b963e8..572439e22 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -331,6 +331,7 @@ const std::vector cheatCvars = { "gCosmetics.Link_HeadScale.Value", "gCosmetics.Link_SwordScale.Changed", "gCosmetics.Link_SwordScale.Value", + "gEnhancements.RememberMapToggleState", }; const std::vector randomizerCvars = { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index d74649290..5f41f1e25 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -988,6 +988,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Disables the voice audio when Navi calls you"); UIWidgets::PaddedEnhancementCheckbox("Disable Hot/Underwater Warning Text", "gDisableTunicWarningText", true, false); UIWidgets::Tooltip("Disables warning text when you don't have on the Goron/Zora Tunic in Hot/Underwater conditions."); + UIWidgets::PaddedEnhancementCheckbox("Remember Minimap State Between Areas", "gEnhancements.RememberMapToggleState"); + UIWidgets::Tooltip("Preserves the minimap visibility state when going between areas rather than defaulting it to \"on\" when going through loading zones."); ImGui::EndMenu(); } diff --git a/soh/src/code/z_construct.c b/soh/src/code/z_construct.c index b95902cc5..c8a340492 100644 --- a/soh/src/code/z_construct.c +++ b/soh/src/code/z_construct.c @@ -430,7 +430,9 @@ void Regs_InitDataImpl(void) { WREG(28) = 0; R_OW_MINIMAP_X = 238; R_OW_MINIMAP_Y = 164; - R_MINIMAP_DISABLED = CVarGetInteger("gMinimalUI", 0); + if (!CVarGetInteger("gEnhancements.RememberMapToggleState", 0)) { + R_MINIMAP_DISABLED = CVarGetInteger("gMinimalUI", 0); + } WREG(32) = 122; WREG(33) = 60; WREG(35) = 0; From eeb6c7faaa16d50ce0d094e191c5778cc2ce904e Mon Sep 17 00:00:00 2001 From: "Tina H. (sheepytina)" <99330992+sheepytina@users.noreply.github.com> Date: Fri, 16 Feb 2024 12:47:13 +1100 Subject: [PATCH 071/300] Fix Cosmetics Editor getting stuck on weapon trails (#3913) * Partially fix cosmetics editor getting stuck on sword trails. * No reason for "reset" to be static. * bombchu --- soh/src/code/z_eff_blure.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_eff_blure.c b/soh/src/code/z_eff_blure.c index 91ac43766..e770a9096 100644 --- a/soh/src/code/z_eff_blure.c +++ b/soh/src/code/z_eff_blure.c @@ -203,13 +203,17 @@ s32 EffectBlure_Update(void* thisx) { EffectBlure* this = (EffectBlure*)thisx; s32 i; Color_RGBA8 color; - u8 changed = 0; + static u8 changed = 0; + u8 reset = 0; switch (this->trailType) { //there HAS to be a better way to do this. case 2: if (CVarGetInteger("gCosmetics.Trails_Boomerang.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_Boomerang.Value", (Color_RGBA8){ 255, 255, 100, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 100, 255 }; + reset = 1; } break; case 3: @@ -227,36 +231,65 @@ s32 EffectBlure_Update(void* thisx) { this->p2StartColor.b = color.b * 0.8f; this->p1EndColor.b = color.b * 0.6f; this->p2EndColor.b = color.b * 0.4f; + } else if (changed) { + color = (Color_RGBA8){ 250, 0, 0, 255 }; + this->p1StartColor.r = color.r; + this->p2StartColor.r = color.r * 0.8f; + this->p1EndColor.r = color.r * 0.6f; + this->p2EndColor.r = color.r * 0.4f; + this->p1StartColor.g = color.g; + this->p2StartColor.g = color.g * 0.8f; + this->p1EndColor.g = color.g * 0.6f; + this->p2EndColor.g = color.g * 0.4f; + this->p1StartColor.b = color.b; + this->p2StartColor.b = color.b * 0.8f; + this->p1EndColor.b = color.b * 0.6f; + this->p2EndColor.b = color.b * 0.4f; } break; case 4: if (CVarGetInteger("gCosmetics.Trails_KokiriSword.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_KokiriSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 255, 255 }; + reset = 1; } break; case 5: if (CVarGetInteger("gCosmetics.Trails_MasterSword.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_MasterSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 255, 255 }; + reset = 1; } break; case 6: if (CVarGetInteger("gCosmetics.Trails_BiggoronSword.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_BiggoronSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 255, 255 }; + reset = 1; } break; case 7: if (CVarGetInteger("gCosmetics.Trails_Stick.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_Stick.Value", (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 255, 255 }; + reset = 1; } break; case 8: if (CVarGetInteger("gCosmetics.Trails_Hammer.Changed", 0)) { color = CVarGetColor("gCosmetics.Trails_Hammer.Value", (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; + } else if (changed) { + color = (Color_RGBA8){ 255, 255, 255, 255 }; + reset = 1; } break; default: // don't do anything @@ -278,6 +311,9 @@ s32 EffectBlure_Update(void* thisx) { this->p1EndColor.b = color.b; this->p2EndColor.b = color.b; } + if (reset) { + changed = 0; + } // Don't override boomerang and bombchu trail durations if (this->trailType != 2 && this->trailType != 3) { From 7ccc816772c4cc036c1653d66e2895eb82100e11 Mon Sep 17 00:00:00 2001 From: "Tina H. (sheepytina)" <99330992+sheepytina@users.noreply.github.com> Date: Fri, 16 Feb 2024 12:49:13 +1100 Subject: [PATCH 072/300] Cosmetics Editor fixes for icons in z_message_PAL.c (#3914) * Fix resetting button icon colours in message boxes. * Fix type/math error for custom color in textbox icon pulsing. * Fix type error for custom color in ocarina icon pulsing. * Make custom env colour math more closely match vanilla equivalents. * Make comments presentable. --- soh/src/code/z_message_PAL.c | 73 +++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 4c661aad7..234972ff6 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -453,19 +453,20 @@ void Message_SetTextColor(MessageContext* msgCtx, u16 colorParameter) { } void Message_DrawTextboxIcon(PlayState* play, Gfx** p, s16 x, s16 y) { - static Color_RGB8 sIconPrimColors[2] = { + // SoH [Cosmetics] The following Color_RGB8 were originally static + Color_RGB8 sIconPrimColors[2] = { { 0, 80, 200 }, { 50, 130, 255 }, }; - static Color_RGB8 sIconEnvColors[2] = { + Color_RGB8 sIconEnvColors[2] = { { 0, 0, 0 }, { 0, 130, 255 }, }; if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_AButton.Value", (Color_RGB8){ 50, 130, 255 }); - sIconPrimColors[0].r = (color.r / 255) * 95; - sIconPrimColors[0].g = (color.g / 255) * 95; - sIconPrimColors[0].b = (color.b / 255) * 95; + sIconPrimColors[0].r = color.r - 50; + sIconPrimColors[0].g = color.g - 50; + sIconPrimColors[0].b = color.b - 50; sIconPrimColors[1] = color; sIconEnvColors[1] = color; } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { @@ -2006,19 +2007,21 @@ void Message_DrawMain(PlayState* play, Gfx** p) { static void* sOcarinaNoteTextures[] = { gOcarinaBtnIconATex, gOcarinaBtnIconCDownTex, gOcarinaBtnIconCRightTex, gOcarinaBtnIconCLeftTex, gOcarinaBtnIconCUpTex, }; - static Color_RGB8 sOcarinaNoteAPrimColors[2] = { + + // SoH [Cosmetics] The following Color_RGB8 were originally static + Color_RGB8 sOcarinaNoteAPrimColors[2] = { { 80, 150, 255 }, { 100, 200, 255 }, }; - static Color_RGB8 sOcarinaNoteAEnvColors[2] = { + Color_RGB8 sOcarinaNoteAEnvColors[2] = { { 10, 10, 10 }, { 50, 50, 255 }, }; if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_AButton.Value", (Color_RGB8){ 100, 200, 255 }); - sOcarinaNoteAPrimColors[0].r = (color.r / 255) * 95; - sOcarinaNoteAPrimColors[0].g = (color.g / 255) * 95; - sOcarinaNoteAPrimColors[0].b = (color.b / 255) * 95; + sOcarinaNoteAPrimColors[0].r = (color.r / 255.0f) * 95; + sOcarinaNoteAPrimColors[0].g = (color.g / 255.0f) * 95; + sOcarinaNoteAPrimColors[0].b = (color.b / 255.0f) * 95; sOcarinaNoteAPrimColors[1] = color; sOcarinaNoteAEnvColors[1] = color; } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { @@ -2027,11 +2030,11 @@ void Message_DrawMain(PlayState* play, Gfx** p) { sOcarinaNoteAEnvColors[1] = (Color_RGB8){ 50, 255, 50 }; } - static Color_RGB8 sOcarinaNoteCPrimColors[2] = { + Color_RGB8 sOcarinaNoteCPrimColors[2] = { { 255, 255, 50 }, { 255, 255, 180 }, }; - static Color_RGB8 sOcarinaNoteCEnvColors[2] = { + Color_RGB8 sOcarinaNoteCEnvColors[2] = { { 10, 10, 10 }, { 110, 110, 50 }, }; @@ -2039,16 +2042,16 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CButtons.Value", (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCPrimColors[0] = color; sOcarinaNoteCPrimColors[1] = color; - sOcarinaNoteCEnvColors[1].r = (color.r / 255) * 95; - sOcarinaNoteCEnvColors[1].g = (color.g / 255) * 95; - sOcarinaNoteCEnvColors[1].b = (color.b / 255) * 95; + sOcarinaNoteCEnvColors[1].r = (color.r / 255.0f) * 95; + sOcarinaNoteCEnvColors[1].g = (color.g / 255.0f) * 95; + sOcarinaNoteCEnvColors[1].b = (color.b / 255.0f) * 95; } - static Color_RGB8 sOcarinaNoteCUpPrimColors[2] = { + Color_RGB8 sOcarinaNoteCUpPrimColors[2] = { { 255, 255, 50 }, { 255, 255, 180 }, }; - static Color_RGB8 sOcarinaNoteCUpEnvColors[2] = { + Color_RGB8 sOcarinaNoteCUpEnvColors[2] = { { 10, 10, 10 }, { 110, 110, 50 }, }; @@ -2056,16 +2059,16 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCUpPrimColors[0] = color; sOcarinaNoteCUpPrimColors[1] = color; - sOcarinaNoteCUpEnvColors[1].r = (color.r / 255) * 95; - sOcarinaNoteCUpEnvColors[1].g = (color.g / 255) * 95; - sOcarinaNoteCUpEnvColors[1].b = (color.b / 255) * 95; + sOcarinaNoteCUpEnvColors[1].r = (color.r / 255.0f) * 95; + sOcarinaNoteCUpEnvColors[1].g = (color.g / 255.0f) * 95; + sOcarinaNoteCUpEnvColors[1].b = (color.b / 255.0f) * 95; } - static Color_RGB8 sOcarinaNoteCDownPrimColors[2] = { + Color_RGB8 sOcarinaNoteCDownPrimColors[2] = { { 255, 255, 50 }, { 255, 255, 180 }, }; - static Color_RGB8 sOcarinaNoteCDownEnvColors[2] = { + Color_RGB8 sOcarinaNoteCDownEnvColors[2] = { { 10, 10, 10 }, { 110, 110, 50 }, }; @@ -2073,16 +2076,16 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCDownPrimColors[0] = color; sOcarinaNoteCDownPrimColors[1] = color; - sOcarinaNoteCDownEnvColors[1].r = (color.r / 255) * 95; - sOcarinaNoteCDownEnvColors[1].g = (color.g / 255) * 95; - sOcarinaNoteCDownEnvColors[1].b = (color.b / 255) * 95; + sOcarinaNoteCDownEnvColors[1].r = (color.r / 255.0f) * 95; + sOcarinaNoteCDownEnvColors[1].g = (color.g / 255.0f) * 95; + sOcarinaNoteCDownEnvColors[1].b = (color.b / 255.0f) * 95; } - static Color_RGB8 sOcarinaNoteCLeftPrimColors[2] = { + Color_RGB8 sOcarinaNoteCLeftPrimColors[2] = { { 255, 255, 50 }, { 255, 255, 180 }, }; - static Color_RGB8 sOcarinaNoteCLeftEnvColors[2] = { + Color_RGB8 sOcarinaNoteCLeftEnvColors[2] = { { 10, 10, 10 }, { 110, 110, 50 }, }; @@ -2090,16 +2093,16 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCLeftPrimColors[0] = color; sOcarinaNoteCLeftPrimColors[1] = color; - sOcarinaNoteCLeftEnvColors[1].r = (color.r / 255) * 95; - sOcarinaNoteCLeftEnvColors[1].g = (color.g / 255) * 95; - sOcarinaNoteCLeftEnvColors[1].b = (color.b / 255) * 95; + sOcarinaNoteCLeftEnvColors[1].r = (color.r / 255.0f) * 95; + sOcarinaNoteCLeftEnvColors[1].g = (color.g / 255.0f) * 95; + sOcarinaNoteCLeftEnvColors[1].b = (color.b / 255.0f) * 95; } - static Color_RGB8 sOcarinaNoteCRightPrimColors[2] = { + Color_RGB8 sOcarinaNoteCRightPrimColors[2] = { { 255, 255, 50 }, { 255, 255, 180 }, }; - static Color_RGB8 sOcarinaNoteCRightEnvColors[2] = { + Color_RGB8 sOcarinaNoteCRightEnvColors[2] = { { 10, 10, 10 }, { 110, 110, 50 }, }; @@ -2107,9 +2110,9 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCRightPrimColors[0] = color; sOcarinaNoteCRightPrimColors[1] = color; - sOcarinaNoteCRightEnvColors[1].r = (color.r / 255) * 95; - sOcarinaNoteCRightEnvColors[1].g = (color.g / 255) * 95; - sOcarinaNoteCRightEnvColors[1].b = (color.b / 255) * 95; + sOcarinaNoteCRightEnvColors[1].r = (color.r / 255.0f) * 95; + sOcarinaNoteCRightEnvColors[1].g = (color.g / 255.0f) * 95; + sOcarinaNoteCRightEnvColors[1].b = (color.b / 255.0f) * 95; } static s16 sOcarinaNoteFlashTimer = 12; From 2c5cb58ef6fec2d690b4bd3f307d9927496069d6 Mon Sep 17 00:00:00 2001 From: mckinlee Date: Thu, 15 Feb 2024 20:49:56 -0500 Subject: [PATCH 073/300] Rename func_80853148 to Player_StartTalking (#3915) -In PR #3498 I renamed this function for clarity and decided to make a quick seperate PR for this change. --- .../actors/ovl_player_actor/z_player.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 852c8d3d5..0651f900b 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -347,7 +347,7 @@ s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction); void func_80853080(Player* this, PlayState* play); s32 Player_InflictDamage(PlayState* play, s32 damage); s32 Player_InflictDamageModified(PlayState* play, s32 damage, u8 modified); -void func_80853148(PlayState* play, Actor* actor); +void Player_StartTalking(PlayState* play, Actor* actor); // .bss part 1 static s32 D_80858AA0; @@ -4708,7 +4708,7 @@ s32 func_80839800(Player* this, PlayState* play) { if (this->doorType <= PLAYER_DOORTYPE_AJAR) { doorActor->textId = 0xD0; - func_80853148(play, doorActor); + Player_StartTalking(play, doorActor); return 0; } @@ -5533,7 +5533,7 @@ s32 func_8083B644(Player* this, PlayState* play) { } this->currentMask = D_80858AA4; - func_80853148(play, sp34); + Player_StartTalking(play, sp34); return 1; } } @@ -10040,7 +10040,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { play->startPlayerCutscene = Player_TryCsAction; play->func_11D54 = func_80853080; play->damagePlayer = Player_InflictDamage; - play->talkWithPlayer = func_80853148; + play->talkWithPlayer = Player_StartTalking; thisx->room = -1; this->ageProperties = &sAgeProperties[gSaveContext.linkAge]; @@ -13496,11 +13496,11 @@ void func_8084E3C4(Player* this, PlayState* play) { func_8005B1A4(Play_GetCamera(play, 0)); if ((this->targetActor != NULL) && (this->targetActor == this->unk_6A8)) { - func_80853148(play, this->targetActor); + Player_StartTalking(play, this->targetActor); } else if (this->naviTextId < 0) { this->targetActor = this->naviActor; this->naviActor->textId = -this->naviTextId; - func_80853148(play, this->targetActor); + Player_StartTalking(play, this->targetActor); } else if (!func_8083B040(this, play)) { func_8083A098(this, &gPlayerAnim_link_normal_okarina_end, play); } @@ -13570,7 +13570,7 @@ void func_8084E6D4(Player* this, PlayState* play) { this->exchangeItemId = EXCH_ITEM_NONE; if (func_8084B4D4(play, this) == 0) { - func_80853148(play, this->targetActor); + Player_StartTalking(play, this->targetActor); } } else { func_8084DFAC(play, this); @@ -13952,7 +13952,7 @@ void func_8084F104(Player* this, PlayState* play) { this->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO; } - func_80853148(play, targetActor); + Player_StartTalking(play, targetActor); } else { GetItemEntry giEntry = ItemTable_Retrieve(D_80854528[this->exchangeItemId - 1]); @@ -15832,7 +15832,7 @@ s32 Player_InflictDamageModified(PlayState* play, s32 damage, u8 modified) { } // Start talking with the given actor -void func_80853148(PlayState* play, Actor* actor) { +void Player_StartTalking(PlayState* play, Actor* actor) { Player* this = GET_PLAYER(play); s32 pad; From 11a0a0063352018660467edaf0e66e38fb6b192b Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 15 Feb 2024 18:50:31 -0700 Subject: [PATCH 074/300] Add `CVarClear` to appropriate sections of randomizer Locations and Tricks tabs to get around issue with saving blank CVar strings. (#3916) --- soh/soh/Enhancements/randomizer/randomizer.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ab3554174..835621fd3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4689,7 +4689,11 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += std::to_string(excludedLocationIt); excludedLocationString += ","; } - CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); + if (excludedLocationString == "") { + CVarClear("gRandomizeExcludedLocations"); + } else { + CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); + } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -4866,7 +4870,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarClear("gRandomizeEnabledTricks"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -5070,7 +5074,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarClear("gRandomizeEnabledTricks"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5108,7 +5112,11 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + if (enabledTrickString == "") { + CVarClear("gRandomizeEnabledTricks"); + } else { + CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } DrawTagChips(*rtObject.rtTags); From 43fed2d77e7efe1c187c2fe5ae5794e95d5c8893 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:51:31 -0500 Subject: [PATCH 075/300] ci: pin switch docker image to known working version (#3917) --- .github/workflows/generate-builds.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index cd8a6fd9b..38cc4c9ad 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -191,7 +191,7 @@ jobs: needs: generate-soh-otr runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} container: - image: devkitpro/devkita64:latest + image: devkitpro/devkita64:20240120 steps: - name: Install dependencies run: | From bbac8f8da40adfb86d82066f5ce6aa041abb3a58 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 15 Feb 2024 17:52:46 -0800 Subject: [PATCH 076/300] [Fixes] Fix for Zora hint dialogue condition with an inverted flag check (#3920) * [Fixes] Fix for Zora hint dialogue condition with an inverted flag check * Base dialogue off of ruto's letter flag * simplify condition --- soh/soh/SohMenuBar.cpp | 2 ++ soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 5f41f1e25..4450d3aa1 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1236,6 +1236,8 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Fixes Darunia's dancing speed so he dances to the beat of Saria's Song, like in vanilla."); + UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", "gFixZoraHintDialogue", true, false); + UIWidgets::Tooltip("Fixes one Zora's dialogue giving a hint about bringing Ruto's Letter to King Zora to properly occur before moving King Zora rather than after"); ImGui::EndMenu(); } diff --git a/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c b/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c index 561ebf81b..f5275618b 100644 --- a/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c +++ b/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c @@ -361,7 +361,7 @@ void EnZo_SpawnSplashes(EnZo* this) { } } -u16 func_80B61024(PlayState* play, Actor* thisx) { +u16 EnZo_GetTextId(PlayState* play, Actor* thisx) { u16 textId; textId = Text_GetFaceReaction(play, 29); @@ -427,7 +427,9 @@ u16 func_80B61024(PlayState* play, Actor* thisx) { return 0x402D; } - if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) || + (CVarGetInteger("gFixZoraHintDialogue", 0) && + Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER))) { return 0x4010; } if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_A_ZORA)) { @@ -520,7 +522,7 @@ void EnZo_Dialog(EnZo* this, PlayState* play) { } Npc_TrackPoint(&this->actor, &this->interactInfo, 11, this->trackingMode); if (this->canSpeak == true) { - Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->dialogRadius, func_80B61024, + Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->dialogRadius, EnZo_GetTextId, func_80B61298); } } From 0cb4cd158aa1243cbec697fff6e663551764b39b Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 15 Feb 2024 18:53:18 -0700 Subject: [PATCH 077/300] Adds reset function to z_en_si (GS Token) to set getItemId to vanilla after resetting SoH. (#3925) --- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 49e88f903..f6c87074d 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -16,6 +16,7 @@ void EnSi_Init(Actor* thisx, PlayState* play); void EnSi_Destroy(Actor* thisx, PlayState* play); void EnSi_Update(Actor* thisx, PlayState* play); void EnSi_Draw(Actor* thisx, PlayState* play); +void EnSi_Reset(); s32 func_80AFB748(EnSi* this, PlayState* play); void func_80AFB768(EnSi* this, PlayState* play); @@ -61,7 +62,7 @@ const ActorInit En_Si_InitVars = { (ActorFunc)EnSi_Destroy, (ActorFunc)EnSi_Update, (ActorFunc)EnSi_Draw, - NULL, + (ActorResetFunc)EnSi_Reset, }; void EnSi_Init(Actor* thisx, PlayState* play) { @@ -224,6 +225,11 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { } } +void EnSi_Reset() { + textId = 0xB4; + giveItemId = ITEM_SKULL_TOKEN; +} + void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); From 3d3b8bfc5b22fdc056cea448738fe904a8523f02 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 15 Feb 2024 20:54:35 -0500 Subject: [PATCH 078/300] Allow IsSaveLoaded to consider debug saves (#3929) --- .../game-interactor/GameInteractor.cpp | 11 ++++++-- .../game-interactor/GameInteractor.h | 2 +- soh/soh/Enhancements/mods.cpp | 27 ++++++++++--------- soh/soh/Enhancements/tts/tts.cpp | 2 +- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor.cpp index eb330947b..5a0d0efd3 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.cpp @@ -37,12 +37,19 @@ GameInteractionEffectQueryResult GameInteractor::RemoveEffect(GameInteractionEff // MARK: - Helpers -bool GameInteractor::IsSaveLoaded() { +bool GameInteractor::IsSaveLoaded(bool allowDbgSave) { Player* player; if (gPlayState != NULL) { player = GET_PLAYER(gPlayState); } - return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true; + + // Checking for normal game mode prevents debug saves from reporting true on title screen + if (gPlayState == NULL || player == NULL || gSaveContext.gameMode != GAMEMODE_NORMAL) { + return false; + } + + // Valid save file or debug save + return (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) || (allowDbgSave && gSaveContext.fileNum == 0xFF); } bool GameInteractor::IsGameplayPaused() { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 4f8ef259b..b56a001d2 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -198,7 +198,7 @@ public: DEFINE_HOOK(OnAssetAltChange, void()); // Helpers - static bool IsSaveLoaded(); + static bool IsSaveLoaded(bool allowDbgSave = false); static bool IsGameplayPaused(); static bool CanSpawnActor(); static bool CanAddOrTakeAmmo(int16_t amount, int16_t item); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 6692dd5c9..258fbba42 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -47,7 +47,7 @@ void ReloadSceneTogglingLinkAge() { void RegisterInfiniteMoney() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gInfiniteMoney", 0) != 0) { if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) { gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); @@ -58,7 +58,7 @@ void RegisterInfiniteMoney() { void RegisterInfiniteHealth() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gInfiniteHealth", 0) != 0) { if (gSaveContext.health < gSaveContext.healthCapacity) { gSaveContext.health = gSaveContext.healthCapacity; @@ -69,7 +69,7 @@ void RegisterInfiniteHealth() { void RegisterInfiniteAmmo() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gInfiniteAmmo", 0) != 0) { // Deku Sticks if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) { @@ -106,7 +106,7 @@ void RegisterInfiniteAmmo() { void RegisterInfiniteMagic() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gInfiniteMagic", 0) != 0) { if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) { gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30; @@ -117,7 +117,7 @@ void RegisterInfiniteMagic() { void RegisterInfiniteNayrusLove() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gInfiniteNayru", 0) != 0) { gSaveContext.nayrusLoveTimer = 0x44B; } @@ -126,7 +126,7 @@ void RegisterInfiniteNayrusLove() { void RegisterMoonJumpOnL() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gMoonJumpOnL", 0) != 0) { Player* player = GET_PLAYER(gPlayState); @@ -141,7 +141,7 @@ void RegisterMoonJumpOnL() { void RegisterInfiniteISG() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gEzISG", 0) != 0) { Player* player = GET_PLAYER(gPlayState); @@ -153,7 +153,7 @@ void RegisterInfiniteISG() { //Permanent quick put away (QPA) glitched damage value void RegisterEzQPA() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gEzQPA", 0) != 0) { Player* player = GET_PLAYER(gPlayState); @@ -165,7 +165,7 @@ void RegisterEzQPA() { void RegisterUnrestrictedItems() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; if (CVarGetInteger("gNoRestrictItems", 0) != 0) { u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong; @@ -193,11 +193,14 @@ void RegisterFreezeTime() { /// Switches Link's age and respawns him at the last entrance he entered. void RegisterSwitchAge() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) { + static bool warped = false; + + if (!GameInteractor::IsSaveLoaded(true)) { CVarClear("gSwitchAge"); + warped = false; return; } - static bool warped = false; + static Vec3f playerPos; static int16_t playerYaw; static RoomContext* roomCtx; @@ -231,7 +234,7 @@ void RegisterSwitchAge() { void RegisterOcarinaTimeTravel() { GameInteractor::Instance->RegisterGameHook([]() { - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded(true)) { CVarClear("gTimeTravel"); return; } diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 0b46cd18f..9e5ff4a42 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -168,7 +168,7 @@ void RegisterOnInterfaceUpdateHook() { prevTimer = timer; - if (!GameInteractor::IsSaveLoaded()) return; + if (!GameInteractor::IsSaveLoaded(true)) return; static int16_t lostHealth = 0; static int16_t prevHealth = 0; From bdfcf39e5685b967699e7ac55ab7140f4bce5d2f Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 15 Feb 2024 17:55:01 -0800 Subject: [PATCH 079/300] Add a link to ship.equipment to the CRC error message box during extraction (#3939) * Add a link to ship.equipment to the CRC error message box during extraction * Improve message and add to ShowCrcErrorBox * Change 'known good roms' to 'known compatible roms' --- soh/soh/Extractor/Extract.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/soh/soh/Extractor/Extract.cpp b/soh/soh/Extractor/Extract.cpp index d4b524474..b08783763 100644 --- a/soh/soh/Extractor/Extract.cpp +++ b/soh/soh/Extractor/Extract.cpp @@ -107,7 +107,8 @@ void Extractor::ShowSizeErrorBox() const { } void Extractor::ShowCrcErrorBox() const { - ShowErrorBox("Rom CRC invalid", "Rom CRC did not match the list of known good roms. Please find another."); + ShowErrorBox("Rom CRC invalid", "Rom CRC did not match the list of known compatible roms. Please find another.\n\n" + "Visit https://ship.equipment/ to validate your ROM and see a list of compatible versions"); } void Extractor::ShowCompressedErrorBox() const { @@ -479,7 +480,8 @@ bool Extractor::Run(std::string searchPath, RomSearchMode searchMode) { ShowCrcErrorBox(); } else { ShowErrorBox("Rom CRC invalid", - "Rom CRC did not match the list of known good roms. Trying the next one..."); + "Rom CRC did not match the list of known compatible roms. Trying the next one...\n\n" + "Visit https://ship.equipment/ to validate your ROM and see a list of compatible versions"); } continue; } From cf6101f4daeb8591c65b8a3d0262b4888e000d06 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 16 Feb 2024 02:03:58 +0000 Subject: [PATCH 080/300] Logic bug: child cannot climb forest temple to the straight hallway either (#3934) --- .../randomizer/3drando/location_access/locacc_forest_temple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index fea9fda6f..5e64aee6c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -172,7 +172,7 @@ void AreaTable_Init_ForestTemple() { Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}), Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}), Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}), - Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return (CanUse(BOW) || CanUse(SLINGSHOT)) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}), + Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return IsAdult && (CanUse(BOW) || CanUse(SLINGSHOT)) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}), }); areaTable[FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { From a84227cbbb755681ea8534460a665e5e8c524f4b Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 15 Feb 2024 20:08:31 -0600 Subject: [PATCH 081/300] Support hook unregistration (#3538) --- .../game-interactor/GameInteractor.h | 27 +++- soh/soh/Enhancements/mods.cpp | 127 +++++++++++------- soh/soh/Enhancements/mods.h | 2 + soh/soh/SohMenuBar.cpp | 8 +- 4 files changed, 106 insertions(+), 58 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 3e70da37a..c68aa61df 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -163,11 +163,30 @@ public: static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect); // Game Hooks - template struct RegisteredGameHooks { inline static std::vector functions; }; - template void RegisterGameHook(typename H::fn h) { RegisteredGameHooks::functions.push_back(h); } + uint32_t nextHookId = 1; + template struct RegisteredGameHooks { inline static std::unordered_map functions; }; + template struct HooksToUnregister { inline static std::vector hooks; }; + template uint32_t RegisterGameHook(typename H::fn h) { + // Ensure hook id is unique and not 0, which is reserved for invalid hooks + if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1; + while (RegisteredGameHooks::functions.find(this->nextHookId) != RegisteredGameHooks::functions.end()) { + this->nextHookId++; + } + + RegisteredGameHooks::functions[this->nextHookId] = h; + return this->nextHookId++; + } + template void UnregisterGameHook(uint32_t id) { + HooksToUnregister::hooks.push_back(id); + } + template void ExecuteHooks(Args&&... args) { - for (auto& fn : RegisteredGameHooks::functions) { - fn(std::forward(args)...); + for (auto& hookId : HooksToUnregister::hooks) { + RegisteredGameHooks::functions.erase(hookId); + } + HooksToUnregister::hooks.clear(); + for (auto& hook : RegisteredGameHooks::functions) { + hook.second(std::forward(args)...); } } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 9ae89719f..bd7e032a6 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -519,70 +519,93 @@ void RegisterDaytimeGoldSkultullas() { }); } -void RegisterHyperBosses() { - GameInteractor::Instance->RegisterGameHook([](void* refActor) { - // Run the update function a second time to make bosses move and act twice as fast. +bool IsHyperBossesActive() { + return CVarGetInteger("gHyperBosses", 0) || + (IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES); +} - Player* player = GET_PLAYER(gPlayState); - Actor* actor = static_cast(refActor); +void UpdateHyperBossesState() { + static uint32_t actorUpdateHookId = 0; + if (actorUpdateHookId != 0) { + GameInteractor::Instance->UnregisterGameHook(actorUpdateHookId); + actorUpdateHookId = 0; + } - uint8_t isBossActor = - actor->id == ACTOR_BOSS_GOMA || // Gohma - actor->id == ACTOR_BOSS_DODONGO || // King Dodongo - actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath - actor->id == ACTOR_BOSS_VA || // Barinade - actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon - actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder - actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse - actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying) - actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks - actor->id == ACTOR_BOSS_MO || // Morpha - actor->id == ACTOR_BOSS_SST || // Bongo Bongo - actor->id == ACTOR_BOSS_TW || // Twinrova - actor->id == ACTOR_BOSS_GANON || // Ganondorf - actor->id == ACTOR_BOSS_GANON2; // Ganon + if (IsHyperBossesActive()) { + actorUpdateHookId = GameInteractor::Instance->RegisterGameHook([](void* refActor) { + // Run the update function a second time to make bosses move and act twice as fast. - uint8_t hyperBossesActive = - CVarGetInteger("gHyperBosses", 0) || - (IS_BOSS_RUSH && - gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES); + Player* player = GET_PLAYER(gPlayState); + Actor* actor = static_cast(refActor); - // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses. - if (hyperBossesActive && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) { - // Barinade needs to be updated in sequence to avoid unintended behaviour. - if (actor->id == ACTOR_BOSS_VA) { - // params -1 is BOSSVA_BODY - if (actor->params == -1) { - Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head; - while (actorList != NULL) { - GameInteractor::RawAction::UpdateActor(actorList); - actorList = actorList->next; + uint8_t isBossActor = + actor->id == ACTOR_BOSS_GOMA || // Gohma + actor->id == ACTOR_BOSS_DODONGO || // King Dodongo + actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath + actor->id == ACTOR_BOSS_VA || // Barinade + actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon + actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder + actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse + actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying) + actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks + actor->id == ACTOR_BOSS_MO || // Morpha + actor->id == ACTOR_BOSS_SST || // Bongo Bongo + actor->id == ACTOR_BOSS_TW || // Twinrova + actor->id == ACTOR_BOSS_GANON || // Ganondorf + actor->id == ACTOR_BOSS_GANON2; // Ganon + + // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses. + if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) { + // Barinade needs to be updated in sequence to avoid unintended behaviour. + if (actor->id == ACTOR_BOSS_VA) { + // params -1 is BOSSVA_BODY + if (actor->params == -1) { + Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head; + while (actorList != NULL) { + GameInteractor::RawAction::UpdateActor(actorList); + actorList = actorList->next; + } } + } else { + GameInteractor::RawAction::UpdateActor(actor); } - } else { - GameInteractor::RawAction::UpdateActor(actor); } - } + }); + } +} + +void RegisterHyperBosses() { + UpdateHyperBossesState(); + GameInteractor::Instance->RegisterGameHook([](int16_t fileNum) { + UpdateHyperBossesState(); }); } -void RegisterHyperEnemies() { - GameInteractor::Instance->RegisterGameHook([](void* refActor) { - // Run the update function a second time to make enemies and minibosses move and act twice as fast. +void UpdateHyperEnemiesState() { + static uint32_t actorUpdateHookId = 0; + if (actorUpdateHookId != 0) { + GameInteractor::Instance->UnregisterGameHook(actorUpdateHookId); + actorUpdateHookId = 0; + } - Player* player = GET_PLAYER(gPlayState); - Actor* actor = static_cast(refActor); + if (CVarGetInteger("gHyperEnemies", 0)) { + actorUpdateHookId = GameInteractor::Instance->RegisterGameHook([](void* refActor) { + // Run the update function a second time to make enemies and minibosses move and act twice as fast. - // Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies. - bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2; - bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; + Player* player = GET_PLAYER(gPlayState); + Actor* actor = static_cast(refActor); - // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. - if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy && - !Player_InBlockingCsMode(gPlayState, player)) { - GameInteractor::RawAction::UpdateActor(actor); - } - }); + // Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies. + bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2; + bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; + + // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. + if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy && + !Player_InBlockingCsMode(gPlayState, player)) { + GameInteractor::RawAction::UpdateActor(actor); + } + }); + } } void RegisterBonkDamage() { @@ -1371,7 +1394,7 @@ void InitMods() { RegisterPermanentHeartLoss(); RegisterDeleteFileOnDeath(); RegisterHyperBosses(); - RegisterHyperEnemies(); + UpdateHyperEnemiesState(); RegisterBonkDamage(); RegisterMenuPathFix(); RegisterMirrorModeHandler(); diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index 57ebedfd9..2755924f2 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -12,6 +12,8 @@ void UpdateMirrorModeState(int32_t sceneNum); void UpdateHurtContainerModeState(bool newState); void PatchToTMedallions(); void UpdatePermanentHeartLossState(); +void UpdateHyperEnemiesState(); +void UpdateHyperBossesState(); void InitMods(); void UpdatePatchHand(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 4450d3aa1..a0ac4bf9f 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -959,9 +959,13 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Bonking into trees will have a chance to drop up to 3 sticks. Must already have obtained sticks."); UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); - UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false); + if (UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false)) { + UpdateHyperBossesState(); + } UIWidgets::Tooltip("All major bosses move and act twice as fast."); - UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false); + if (UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false)) { + UpdateHyperEnemiesState(); + } UIWidgets::Tooltip("All regular enemies and mini-bosses move and act twice as fast."); UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); From e05f558ef33a9630a8dea003e5b191521fb5a7c2 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 15 Feb 2024 20:12:19 -0600 Subject: [PATCH 082/300] Fix issue with bombchus always showing as major (#3303) --- soh/soh/OTRGlobals.cpp | 6 +++--- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a5983c457..9548de28d 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -534,7 +534,7 @@ extern "C" void VanillaItemTable_Init() { static GetItemEntry getItemTable[] = { GET_ITEM(ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_5), GET_ITEM(ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_NUTS_5), - GET_ITEM(ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_10), + GET_ITEM(ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_10), GET_ITEM(ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOW), GET_ITEM(ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_SLINGSHOT), GET_ITEM(ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOOMERANG), @@ -637,8 +637,8 @@ extern "C" void VanillaItemTable_Init() { GET_ITEM(ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_20), GET_ITEM(ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBS_30), GET_ITEM(ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_SEEDS_30), - GET_ITEM(ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_5), - GET_ITEM(ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BOMBCHUS_20), + GET_ITEM(ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_5), + GET_ITEM(ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, GI_BOMBCHUS_20), GET_ITEM(ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_FISH), GET_ITEM(ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BUGS), GET_ITEM(ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, GI_BLUE_FIRE), diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 6bbb48488..dfd8fae27 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -646,9 +646,17 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { if (!isVanilla) { getItemCategory = this->getItemEntry.getItemCategory; - // If they don't have bombchu's yet consider the bombchu item major - if (this->getItemEntry.gid == GID_BOMBCHU && INV_CONTENT(ITEM_BOMBCHU) != ITEM_BOMBCHU) { - getItemCategory = ITEM_CATEGORY_MAJOR; + // If they have bombchus, don't consider the bombchu item major + if ( + INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && + ((this->getItemEntry.modIndex == MOD_RANDOMIZER && this->getItemEntry.getItemId == RG_PROGRESSIVE_BOMBCHUS) || + (this->getItemEntry.modIndex == MOD_NONE && ( + this->getItemEntry.getItemId == GI_BOMBCHUS_5 || + this->getItemEntry.getItemId == GI_BOMBCHUS_10 || + this->getItemEntry.getItemId == GI_BOMBCHUS_20 + ))) + ) { + getItemCategory = ITEM_CATEGORY_JUNK; // If it's a bottle and they already have one, consider the item lesser } else if ( (this->getItemEntry.modIndex == MOD_RANDOMIZER && this->getItemEntry.getItemId >= RG_BOTTLE_WITH_RED_POTION && this->getItemEntry.getItemId <= RG_BOTTLE_WITH_BIG_POE) || From 1bc15d5bf3042d4fd64e1952eb68c47a7d5d8061 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:13:49 -0500 Subject: [PATCH 083/300] document dependencies per distro (#3933) * start on arch * noconfirm * git * noconfirm * just skip cache * cmake * ninja * gcc * lsb * sdl2 * png * sdl net * boost * imagemagick and add opensuse * non interactive * git * cmake * add a bunch * things * more * try to matrix * soh otr i guess * needs * trying to figure out how matrix include works * make the matrix? * matrix debug * install? * echo? * yuck * cannot locate package false * parens for good measure * lsb * libsdl2 * suse * i forgot opensuse uses gcc-c++ instead of g++ for the package name * png * sdl * more * suse packages.... * fedora cmake * 2? * png * handle old sdl2 net * apt * not sure if this is a problem for both clang and gcc on opensuse or just clang * devel * cmake min version * def don't want this here but it's here for now * does this do anything * mantic because cmake version * libopengl? * fedora ninja * fedora g++ * lsb * fedora sdl * libpng * do a build * clang fix * give early returns values * ImageMagick * Update BUILDING.md * something * plain boost instead of devel? * not packing so we don't need this part * base? * don't have it can't need it * just use boost download on opensuse i guess * move workflow * bring back the file * lus main? * detach --- .github/workflows/test-builds-on-distros.yml | 61 +++++++++++++++++++ docs/BUILDING.md | 40 ++++++++++-- soh/CMakeLists.txt | 10 ++- soh/src/code/z_camera.c | 4 +- .../actors/ovl_player_actor/z_player.c | 4 +- 5 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/test-builds-on-distros.yml diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml new file mode 100644 index 000000000..fd8b3c929 --- /dev/null +++ b/.github/workflows/test-builds-on-distros.yml @@ -0,0 +1,61 @@ +name: test-builds-on-distros +on: + workflow_dispatch: # by request +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + build: + strategy: + matrix: + image: ["archlinux:base", "opensuse/tumbleweed:latest", "ubuntu:mantic", "debian:bookworm", "fedora:39"] + cc: ["gcc", "clang"] + include: + - cxx: g++ + cc: gcc + - cxx: clang++ + cc: clang + runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} + container: + image: ${{ matrix.image }} + steps: + - name: Install dependencies (pacman) + if: ${{ matrix.image == 'archlinux:base' }} + run: | + echo arch + echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost + pacman -Syu --noconfirm + pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost + - name: Install dependencies (dnf) + if: ${{ matrix.image == 'fedora:39' }} + run: | + echo fedora + echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel + dnf -y upgrade + dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel + - name: Install dependencies (apt) + if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }} + run: | + echo debian based + echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev + apt-get update + apt-get -y full-upgrade + apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev + - name: Install dependencies (zypper) + if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }} + run: | + echo openSUSE + echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel + zypper --non-interactive dup + zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel + - uses: actions/checkout@v3 + with: + submodules: true + - name: Build SoH + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_REMOTE_CONTROL=1 + cmake --build build-cmake --config Release -j3 + env: + CC: ${{ matrix.cc }} + CXX: ${{ matrix.cxx }} diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 56ff9718f..eabc18ec8 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -84,17 +84,49 @@ cd "build/x64" ``` ## Linux -Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld, pulseaudio-libs` +### Install dependencies +#### Debian/Ubuntu +```sh +# using gcc +apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev -**Important: For maximum performance make sure you have ninja build tools installed!** +# or using clang +apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev +``` +#### Arch +```sh +# using gcc +pacman -S gcc git cmake ninja lsb-release sdl2 libpng sdl2_net boost -_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._ +# or using clang +pacman -S clang git cmake ninja lsb-release sdl2 libpng sdl2_net boost +``` +#### Fedora +```sh +# using gcc +dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel + +# or using clang +dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel +``` +#### openSUSE +```sh +# using gcc +zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel boost + +# or using clang +zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel boost +``` + +### Build + +_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._ ```bash # Clone the repo git clone https://github.com/HarbourMasters/Shipwright.git cd Shipwright -# Clone the submodule libultraship +# Clone the submodules git submodule update --init # Copy the baserom to the OTRExporter folder cp OTRExporter diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 228303558..f653c5de5 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -356,7 +356,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS}) if (BUILD_REMOTE_CONTROL) find_package(SDL2_net) - set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS}) + + if(NOT SDL2_net_FOUND) + message(STATUS "SDL2_net not found (it's possible the version installed is too old). Disabling BUILD_REMOTE_CONTROL.") + set(BUILD_REMOTE_CONTROL 0) + else() + set(SDL2-NET-INCLUDE ${SDL_NET_INCLUDE_DIRS}) + endif() endif() target_include_directories(${PROJECT_NAME} PRIVATE assets @@ -623,6 +629,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") -Wno-parentheses -Wno-narrowing -Wno-missing-braces + -Wno-int-conversion + -Wno-implicit-int $<$: -Werror-implicit-function-declaration -Wno-incompatible-pointer-types diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index b5a0318f6..90634ea31 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1679,7 +1679,9 @@ s32 Camera_Normal1(Camera* camera) { if (anim->startSwingTimer <= 0) { // idle camera re-center - if (CVarGetInteger("gA11yDisableIdleCam", 0)) return; + if (CVarGetInteger("gA11yDisableIdleCam", 0)) { + return 1; + } eyeAdjustment.pitch = atEyeNextGeo.pitch; eyeAdjustment.yaw = Camera_LERPCeilS(anim->swingYawTarget, atEyeNextGeo.yaw, 1.0f / camera->yawUpdateRateInv, 0xA); diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 0651f900b..71a6c1c22 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6613,7 +6613,9 @@ s32 func_8083E5A8(Player* this, PlayState* play) { if(gSaveContext.pendingIceTrapCount) { gSaveContext.pendingIceTrapCount--; GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP)); - if (CVarGetInteger("gAddTraps.enabled", 0)) return; + if (CVarGetInteger("gAddTraps.enabled", 0)) { + return 1; + } this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); this->actor.colChkInfo.damage = 0; func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20); From 457a75e9f87268106d648d26b3983fdfcbc59f98 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 16 Feb 2024 02:15:44 +0000 Subject: [PATCH 084/300] More Sword Toggle Options (#3889) * Sword Unequipping Toggle * better macro * less ugly format * cvar prefix * Update soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c * Update soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c --------- Co-authored-by: Garrett Cox --- soh/soh/Enhancements/enhancementTypes.h | 6 ++++ soh/soh/SohMenuBar.cpp | 12 ++++++++ .../ovl_kaleido_scope/z_kaleido_equipment.c | 29 ++++++++++++++----- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h index c8461bbf1..56160567a 100644 --- a/soh/soh/Enhancements/enhancementTypes.h +++ b/soh/soh/Enhancements/enhancementTypes.h @@ -78,4 +78,10 @@ typedef enum { DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, } DekuStickType; +typedef enum { + SWORD_TOGGLE_NONE, + SWORD_TOGGLE_CHILD, + SWORD_TOGGLE_BOTH_AGES, +} SwordToggleMode; + #endif diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index a0ac4bf9f..21241bad8 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -105,6 +105,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large "OHKO" }; static const char* timeTravelOptions[3] = { "Disabled", "Ocarina of Time", "Any Ocarina" }; + static const char* swordToggleModes[3] = { "Disabled", "Child Toggle", "Both Ages (May lead to unintended behaviour)"}; extern "C" SaveContext gSaveContext; @@ -1006,6 +1007,17 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons"); UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); + if (CVarGetInteger("gEquipmentCanBeRemoved", 0)) { + UIWidgets::PaddedText("Sword Toggle Options", true, false); + UIWidgets::EnhancementCombobox("gEnhancements.SwordToggle", swordToggleModes, SWORD_TOGGLE_NONE); + UIWidgets::Tooltip( + "Introduces Options for unequipping Link's sword\n\n" + "None: Only Biggoron's Sword/Giant's Knife can be toggled. Doing so will equip the Master Sword.\n\n" + "Child Toggle: This will allow for completely unequipping any sword as child link.\n\n" + "Both Ages: Any sword can be unequipped as either age. This may lead to swordless glitches as Adult.\n" + ); + } + UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); UIWidgets::Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index def71a66b..cf4344027 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -2,6 +2,7 @@ #include "textures/icon_item_static/icon_item_static.h" #include "textures/parameter_static/parameter_static.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" +#include "soh/Enhancements/enhancementTypes.h" static u8 sChildUpgrades[] = { UPG_BULLET_BAG, UPG_BOMB_BAG, UPG_STRENGTH, UPG_SCALE }; static u8 sAdultUpgrades[] = { UPG_QUIVER, UPG_BOMB_BAG, UPG_STRENGTH, UPG_SCALE }; @@ -562,20 +563,32 @@ void KaleidoScope_DrawEquipment(PlayState* play) { if (CHECK_AGE_REQ_EQUIP(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP])) { if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + // #Region SoH [Enhancements] // Allow Link to remove his equipment from the equipment subscreen by toggling on/off // Shields will be un-equipped entirely, and tunics/boots will revert to Kokiri Tunic/Kokiri Boots // Only BGS/Giant's Knife is affected, and it will revert to Master Sword. // If we have the feature toggled on if (CVarGetInteger("gEquipmentCanBeRemoved", 0)) { - - // If we're on the "swords" section of the equipment screen AND we're on a currently-equipped BGS/Giant's Knife - if (pauseCtx->cursorY[PAUSE_EQUIP] == 0 && pauseCtx->cursorX[PAUSE_EQUIP] == 3 - && CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_BIGGORON && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)){ // And we have the Master Sword - Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER); // "Unequip" it by equipping Master Sword - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; - gSaveContext.infTable[29] = 0; - goto RESUME_EQUIPMENT_SWORD; // Skip to here so we don't re-equip it + + if (CVarGetInteger("gEnhancements.SwordToggle", SWORD_TOGGLE_NONE) == SWORD_TOGGLE_BOTH_AGES || + (CVarGetInteger("gEnhancements.SwordToggle", SWORD_TOGGLE_NONE) == SWORD_TOGGLE_CHILD) && LINK_IS_CHILD) { + // If we're on the "swords" section of the equipment screen AND we're on a currently-equipped sword + if (pauseCtx->cursorY[PAUSE_EQUIP] == 0 && pauseCtx->cursorX[PAUSE_EQUIP] == CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD)) { + Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_NONE); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; + Flags_SetInfTable(INFTABLE_SWORDLESS); + goto RESUME_EQUIPMENT_SWORD; // Skip to here so we don't re-equip it + } + } else { + // If we're on the "swords" section of the equipment screen AND we're on a currently-equipped BGS/Giant's Knife + if (pauseCtx->cursorY[PAUSE_EQUIP] == 0 && pauseCtx->cursorX[PAUSE_EQUIP] == 3 + && CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_BIGGORON && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)){ // And we have the Master Sword + Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER); // "Unequip" it by equipping Master Sword + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + Flags_UnsetInfTable(INFTABLE_SWORDLESS); + goto RESUME_EQUIPMENT_SWORD; // Skip to here so we don't re-equip it + } } // If we're on the "shields" section of the equipment screen AND we're on a currently-equipped shield From 4797c9ad354adef62084509d9ae1ee504c702cf1 Mon Sep 17 00:00:00 2001 From: DeusVexus <10972000+DeusVexus@users.noreply.github.com> Date: Thu, 15 Feb 2024 18:29:09 -0800 Subject: [PATCH 085/300] Adds the Keese and Guay don't target you cheat (#3267) * Adds the Keese and Guay don't target you cheat that makes keese and guay ignore you as if you are wearing the skull mask * changed instances of CVar_GetS32 to CVarGetInteger added the cvar to presets.h --------- Co-authored-by: Garrett Cox --- soh/soh/Enhancements/presets.h | 1 + soh/soh/SohMenuBar.cpp | 2 ++ soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c | 6 ++++-- soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c | 6 ++++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 572439e22..d16e343e1 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -312,6 +312,7 @@ const std::vector cheatCvars = { "gSwitchAge", "gSwitchTimeline", "gNoRedeadFreeze", + "gNoKeeseGuayTarget", "gBombTimerMultiplier", "gNoFishDespawn", "gNoBugsDespawn", diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 21241bad8..96d99fbb1 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1545,6 +1545,8 @@ void DrawCheatsMenu() { UIWidgets::Tooltip("This syncs the ingame time with the real world time"); UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", "gNoRedeadFreeze", true, false); UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream"); + UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", "gNoKeeseGuayTarget", true, false); + UIWidgets::Tooltip("Keese and Guay no longer target you and simply ignore you as if you were wearing the skull mask"); { static int32_t betaQuestEnabled = CVarGetInteger("gEnableBetaQuest", 0); static int32_t lastBetaQuestEnabled = betaQuestEnabled; diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index cbbba524d..ea0432f27 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -282,7 +282,8 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { this->timer--; } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && - (this->actor.yDistToWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL)) { + (this->actor.yDistToWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL) && + !CVarGetInteger("gNoKeeseGuayTarget", 0)) { EnCrow_SetupDiveAttack(this); } } @@ -319,7 +320,8 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || (this->collider.base.atFlags & AT_HIT) || (this->actor.bgCheckFlags & 9) || - (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->actor.yDistToWater > -40.0f)) { + (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->actor.yDistToWater > -40.0f) || + CVarGetInteger("gNoKeeseGuayTarget", 0)) { if (this->collider.base.atFlags & AT_HIT) { this->collider.base.atFlags &= ~AT_HIT; Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_ATTACK); diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index bf7b79b7f..f37bc73db 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -415,7 +415,8 @@ void EnFirefly_FlyIdle(EnFirefly* this, PlayState* play) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.wallYaw, 2, 0xC00, 0x300); } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 200.0f) && - (Player_GetMask(play) != PLAYER_MASK_SKULL)) { + (Player_GetMask(play) != PLAYER_MASK_SKULL) && + !CVarGetInteger("gNoKeeseGuayTarget", 0)) { EnFirefly_SetupDiveAttack(this); } } @@ -493,7 +494,8 @@ void EnFirefly_DiveAttack(EnFirefly* this, PlayState* play) { } Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); } - if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL)) { + if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || + CVarGetInteger("gNoKeeseGuayTarget", 0)) { EnFirefly_SetupFlyAway(this); } } From 30a063b75d504aaecec4b44a6f7d81f15fe778ff Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 15 Feb 2024 19:44:40 -0700 Subject: [PATCH 086/300] [Tweak] Move Personal Notes to Save File (#3909) * Moves personal notes to the save file under a new itemTracker save section. * Update soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp --------- Co-authored-by: Archez --- .../randomizer/randomizer_item_tracker.cpp | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f24ab818b..f63b37b62 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -30,6 +30,8 @@ void DrawBottle(ItemTrackerItem item); void DrawQuest(ItemTrackerItem item); void DrawSong(ItemTrackerItem item); +int itemTrackerSectionId; + bool shouldUpdateVectors = true; std::vector mainWindowItems = {}; @@ -282,11 +284,6 @@ void ItemTrackerOnFrame() { } } -void SaveNotes(uint32_t fileNum) { - CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); -} - bool IsValidSaveFile() { bool validSave = gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2; return validSave; @@ -734,7 +731,7 @@ void DrawNotes(bool resizeable = false) { } if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { notesNeedSave = false; - SaveNotes(gSaveContext.fileNum); + SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); } ImGui::EndGroup(); } @@ -959,6 +956,26 @@ void UpdateVectors() { shouldUpdateVectors = false; } +void ItemTrackerInitFile(bool isDebug) { + itemTrackerNotes.clear(); + itemTrackerNotes.push_back(0); +} + +void ItemTrackerSaveFile(SaveContext* saveContext, int sectionID, bool fullSave) { + SaveManager::Instance->SaveData("personalNotes", std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str()); +} + +void ItemTrackerLoadFile() { + std::string initialTrackerNotes = ""; + SaveManager::Instance->LoadData("personalNotes", initialTrackerNotes); + itemTrackerNotes.resize(initialTrackerNotes.length() + 1); + if (initialTrackerNotes != "") { + SohUtils::CopyStringToCharArray(itemTrackerNotes.Data, initialTrackerNotes.c_str(), itemTrackerNotes.size()); + } else { + itemTrackerNotes.push_back(0); + } +} + void ItemTrackerWindow::DrawElement() { UpdateVectors(); @@ -1223,14 +1240,9 @@ void ItemTrackerWindow::InitElement() { itemTrackerNotes.push_back(0); } - GameInteractor::Instance->RegisterGameHook([](uint32_t fileNum) { - const char* initialTrackerNotes = CVarGetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), ""); - itemTrackerNotes.resize(strlen(initialTrackerNotes) + 1); - strcpy(itemTrackerNotes.Data, initialTrackerNotes); - }); - GameInteractor::Instance->RegisterGameHook([](uint32_t fileNum) { - CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), ""); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - }); + SaveManager::Instance->AddInitFunction(ItemTrackerInitFile); + itemTrackerSectionId = SaveManager::Instance->AddSaveFunction("itemTrackerData", 1, ItemTrackerSaveFile, true, -1); + SaveManager::Instance->AddLoadFunction("itemTrackerData", 1, ItemTrackerLoadFile); + GameInteractor::Instance->RegisterGameHook(ItemTrackerOnFrame); } From 7319e4db5799ac36983eacec1ad5e7edcef150c7 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 16 Feb 2024 03:44:46 +0100 Subject: [PATCH 087/300] More player documentation from decomp (#3819) * FallImpactInfo & AnimSfx stuff * IA function naming & Player_UseItem * ActionChange * Speed modes * Fix build * Misc cleanup * Name Player_Action funcs * PlayerAgeProperties * Most of the Player struct * Update z_player.c --------- Co-authored-by: Garrett Cox --- soh/include/z64player.h | 341 +- .../GameInteractor_RawAction.cpp | 4 +- soh/src/code/code_800430A0.c | 2 +- soh/src/code/z_onepointdemo.c | 8 +- .../overlays/actors/ovl_Boss_Fd/z_boss_fd.c | 8 +- .../actors/ovl_Boss_Ganon2/z_boss_ganon2.c | 6 +- .../overlays/actors/ovl_Boss_Mo/z_boss_mo.c | 12 +- .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 16 +- .../overlays/actors/ovl_Boss_Tw/z_boss_tw.c | 16 +- .../overlays/actors/ovl_Door_Ana/z_door_ana.c | 2 +- .../actors/ovl_En_Bdfire/z_en_bdfire.c | 6 +- soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c | 8 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 2 +- soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c | 16 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 2 +- .../actors/ovl_En_Siofuki/z_en_siofuki.c | 2 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 2 +- .../ovl_En_Syateki_Itm/z_en_syateki_itm.c | 2 +- .../actors/ovl_player_actor/z_player.c | 3017 +++++++++-------- 19 files changed, 1814 insertions(+), 1658 deletions(-) diff --git a/soh/include/z64player.h b/soh/include/z64player.h index e5f4b826d..d03b64da5 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -345,7 +345,7 @@ typedef enum { #define PLAYER_LIMB_BUF_COUNT LIMB_BUF_COUNT(PLAYER_LIMB_MAX) typedef struct { - /* 0x00 */ f32 unk_00; + /* 0x00 */ f32 ceilingCheckHeight; /* 0x04 */ f32 unk_04; /* 0x08 */ f32 unk_08; /* 0x0C */ f32 unk_0C; @@ -359,7 +359,7 @@ typedef struct { /* 0x2C */ f32 unk_2C; /* 0x30 */ f32 unk_30; /* 0x34 */ f32 unk_34; - /* 0x38 */ f32 unk_38; + /* 0x38 */ f32 wallCheckRadius; /* 0x3C */ f32 unk_3C; /* 0x40 */ f32 unk_40; /* 0x44 */ Vec3s unk_44; @@ -489,180 +489,187 @@ typedef s32 (*UpperActionFunc)(struct Player*, struct PlayState*); typedef void (*PlayerFuncA74)(struct PlayState*, struct Player*); typedef struct Player { - /* 0x0000 */ Actor actor; - /* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic` - /* 0x014D */ s8 currentSwordItemId; - /* 0x014E */ s8 currentShield; // current shield from `PlayerShield` - /* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots` - /* 0x0150 */ s8 heldItemButton; // Button index for the item currently used - /* 0x0151 */ s8 heldItemAction; // Item action for the item currently used - /* 0x0152 */ u8 heldItemId; // Item id for the item currently used - /* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots` - /* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear - /* 0x0155 */ char unk_155[0x003]; - /* 0x0158 */ u8 modelGroup; - /* 0x0159 */ u8 nextModelGroup; - /* 0x015A */ s8 itemChangeType; - /* 0x015B */ u8 modelAnimType; - /* 0x015C */ u8 leftHandType; - /* 0x015D */ u8 rightHandType; - /* 0x015E */ u8 sheathType; - /* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask` - /* 0x0160 */ Gfx** rightHandDLists; - /* 0x0164 */ Gfx** leftHandDLists; - /* 0x0168 */ Gfx** sheathDLists; - /* 0x016C */ Gfx** waistDLists; - /* 0x0170 */ u8 giObjectLoading; + /* 0x0000 */ Actor actor; + /* 0x014C */ s8 currentTunic; // current tunic from `PlayerTunic` + /* 0x014D */ s8 currentSwordItemId; + /* 0x014E */ s8 currentShield; // current shield from `PlayerShield` + /* 0x014F */ s8 currentBoots; // current boots from `PlayerBoots` + /* 0x0150 */ s8 heldItemButton; // Button index for the item currently used + /* 0x0151 */ s8 heldItemAction; // Item action for the item currently used + /* 0x0152 */ u8 heldItemId; // Item id for the item currently used + /* 0x0153 */ s8 prevBoots; // previous boots from `PlayerBoots` + /* 0x0154 */ s8 itemAction; // the difference between this and heldItemAction is unclear + /* 0x0155 */ char unk_155[0x003]; + /* 0x0158 */ u8 modelGroup; + /* 0x0159 */ u8 nextModelGroup; + /* 0x015A */ s8 itemChangeType; + /* 0x015B */ u8 modelAnimType; + /* 0x015C */ u8 leftHandType; + /* 0x015D */ u8 rightHandType; + /* 0x015E */ u8 sheathType; + /* 0x015F */ u8 currentMask; // current mask equipped from `PlayerMask` + /* 0x0160 */ Gfx** rightHandDLists; + /* 0x0164 */ Gfx** leftHandDLists; + /* 0x0168 */ Gfx** sheathDLists; + /* 0x016C */ Gfx** waistDLists; + /* 0x0170 */ u8 giObjectLoading; /* 0x0174 */ DmaRequest giObjectDmaRequest; /* 0x0194 */ OSMesgQueue giObjectLoadQueue; - /* 0x01AC */ OSMesg giObjectLoadMsg; - /* 0x01B0 */ void* giObjectSegment; // also used for title card textures - /* 0x01B4 */ SkelAnime skelAnime; - /* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT]; - /* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT]; - /* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT]; - /* 0x03A8 */ s16 unk_3A8[2]; - /* 0x03AC */ Actor* heldActor; - /* 0x03B0 */ Vec3f leftHandPos; - /* 0x03BC */ Vec3s unk_3BC; - /* 0x03C4 */ Actor* unk_3C4; - /* 0x03C8 */ Vec3f unk_3C8; - /* 0x03D4 */ char unk_3D4[0x058]; - /* 0x042C */ s8 doorType; - /* 0x042D */ s8 doorDirection; - /* 0x042E */ s16 doorTimer; - /* 0x0430 */ Actor* doorActor; - /* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream - /* 0x0436 */ u16 getItemDirection; - /* 0x0438 */ Actor* interactRangeActor; - /* 0x043C */ s8 mountSide; - /* 0x043D */ char unk_43D[0x003]; - /* 0x0440 */ Actor* rideActor; - /* 0x0444 */ u8 csAction; - /* 0x0445 */ u8 prevCsAction; - /* 0x0446 */ u8 cueId; - /* 0x0447 */ u8 unk_447; - /* 0x0448 */ Actor* csActor; - /* 0x044C */ char unk_44C[0x004]; - /* 0x0450 */ Vec3f unk_450; - /* 0x045C */ Vec3f unk_45C; - /* 0x0468 */ char unk_468[0x002]; - /* 0x046A */ s16 doorBgCamIndex; - /* 0x046C */ s16 subCamId; - /* 0x046E */ char unk_46E[0x02A]; + /* 0x01AC */ OSMesg giObjectLoadMsg; + /* 0x01B0 */ void* giObjectSegment; // also used for title card textures + /* 0x01B4 */ SkelAnime skelAnime; + /* 0x01F8 */ Vec3s jointTable[PLAYER_LIMB_BUF_COUNT]; + /* 0x0288 */ Vec3s morphTable[PLAYER_LIMB_BUF_COUNT]; + /* 0x0318 */ Vec3s blendTable[PLAYER_LIMB_BUF_COUNT]; + /* 0x03A8 */ s16 unk_3A8[2]; + /* 0x03AC */ Actor* heldActor; + /* 0x03B0 */ Vec3f leftHandPos; + /* 0x03BC */ Vec3s unk_3BC; + /* 0x03C4 */ Actor* unk_3C4; + /* 0x03C8 */ Vec3f unk_3C8; + /* 0x03D4 */ char unk_3D4[0x058]; + /* 0x042C */ s8 doorType; + /* 0x042D */ s8 doorDirection; + /* 0x042E */ s16 doorTimer; + /* 0x0430 */ Actor* doorActor; + /* 0x0434 */ s16 getItemId; // Upstream TODO: Document why this is s16 while it's s8 upstream + /* 0x0436 */ u16 getItemDirection; + /* 0x0438 */ Actor* interactRangeActor; + /* 0x043C */ s8 mountSide; + /* 0x043D */ char unk_43D[0x003]; + /* 0x0440 */ Actor* rideActor; + /* 0x0444 */ u8 csAction; + /* 0x0445 */ u8 prevCsAction; + /* 0x0446 */ u8 cueId; + /* 0x0447 */ u8 unk_447; + /* 0x0448 */ Actor* csActor; // Actor involved in a `csAction`. Typically the actor that invoked the cutscene. + /* 0x044C */ char unk_44C[0x004]; + /* 0x0450 */ Vec3f unk_450; + /* 0x045C */ Vec3f unk_45C; + /* 0x0468 */ char unk_468[0x002]; + /* 0x046A */ s16 doorBgCamIndex; + /* 0x046C */ s16 subCamId; + /* 0x046E */ char unk_46E[0x02A]; /* 0x0498 */ ColliderCylinder cylinder; /* 0x04E4 */ ColliderQuad meleeWeaponQuads[2]; /* 0x05E4 */ ColliderQuad shieldQuad; - /* 0x0664 */ Actor* unk_664; - /* 0x0668 */ char unk_668[0x004]; - /* 0x066C */ s32 unk_66C; - /* 0x0670 */ s32 meleeWeaponEffectIndex; + /* 0x0664 */ Actor* unk_664; + /* 0x0668 */ char unk_668[0x004]; + /* 0x066C */ s32 unk_66C; + /* 0x0670 */ s32 meleeWeaponEffectIndex; /* 0x0674 */ PlayerActionFunc actionFunc; /* 0x0678 */ PlayerAgeProperties* ageProperties; - /* 0x067C */ u32 stateFlags1; - /* 0x0680 */ u32 stateFlags2; - /* 0x0684 */ Actor* unk_684; - /* 0x0688 */ Actor* boomerangActor; - /* 0x068C */ Actor* naviActor; - /* 0x0690 */ s16 naviTextId; - /* 0x0692 */ u8 stateFlags3; - /* 0x0693 */ s8 exchangeItemId; - /* 0x0694 */ Actor* targetActor; - /* 0x0698 */ f32 targetActorDistance; - /* 0x069C */ char unk_69C[0x004]; - /* 0x06A0 */ f32 unk_6A0; - /* 0x06A4 */ f32 closestSecretDistSq; - /* 0x06A8 */ Actor* unk_6A8; - /* 0x06AC */ s8 unk_6AC; - /* 0x06AD */ u8 unk_6AD; - /* 0x06AE */ u16 unk_6AE; - /* 0x06B0 */ s16 unk_6B0; - /* 0x06B2 */ char unk_6B4[0x004]; - /* 0x06B6 */ s16 unk_6B6; - /* 0x06B8 */ s16 unk_6B8; - /* 0x06BA */ s16 unk_6BA; - /* 0x06BC */ s16 unk_6BC; - /* 0x06BE */ s16 unk_6BE; - /* 0x06C0 */ s16 unk_6C0; - /* 0x06C2 */ s16 unk_6C2; - /* 0x06C4 */ f32 unk_6C4; - /* 0x06C8 */ SkelAnime upperSkelAnime; - /* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT]; - /* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT]; + /* 0x067C */ u32 stateFlags1; + /* 0x0680 */ u32 stateFlags2; + /* 0x0684 */ Actor* unk_684; + /* 0x0688 */ Actor* boomerangActor; + /* 0x068C */ Actor* naviActor; + /* 0x0690 */ s16 naviTextId; + /* 0x0692 */ u8 stateFlags3; + /* 0x0693 */ s8 exchangeItemId; + /* 0x0694 */ Actor* targetActor; + /* 0x0698 */ f32 targetActorDistance; + /* 0x069C */ char unk_69C[0x004]; + /* 0x06A0 */ f32 unk_6A0; + /* 0x06A4 */ f32 closestSecretDistSq; + /* 0x06A8 */ Actor* unk_6A8; + /* 0x06AC */ s8 unk_6AC; + /* 0x06AD */ u8 unk_6AD; + /* 0x06AE */ u16 unk_6AE; + /* 0x06B0 */ s16 unk_6B0; + /* 0x06B2 */ char unk_6B4[0x004]; + /* 0x06B6 */ s16 unk_6B6; + /* 0x06B8 */ s16 unk_6B8; + /* 0x06BA */ s16 unk_6BA; + /* 0x06BC */ s16 unk_6BC; + /* 0x06BE */ s16 unk_6BE; + /* 0x06C0 */ s16 unk_6C0; + /* 0x06C2 */ s16 unk_6C2; + /* 0x06C4 */ f32 unk_6C4; + /* 0x06C8 */ SkelAnime upperSkelAnime; + /* 0x070C */ Vec3s upperJointTable[PLAYER_LIMB_BUF_COUNT]; + /* 0x079C */ Vec3s upperMorphTable[PLAYER_LIMB_BUF_COUNT]; /* 0x082C */ UpperActionFunc upperActionFunc; - /* 0x0830 */ f32 upperAnimBlendWeight; - /* 0x0834 */ s16 unk_834; - /* 0x0836 */ s8 unk_836; - /* 0x0837 */ u8 unk_837; - /* 0x0838 */ f32 linearVelocity; - /* 0x083C */ s16 currentYaw; - /* 0x083E */ s16 targetYaw; - /* 0x0840 */ u16 underwaterTimer; - /* 0x0842 */ s8 meleeWeaponAnimation; - /* 0x0843 */ s8 meleeWeaponState; - /* 0x0844 */ s8 unk_844; - /* 0x0845 */ u8 unk_845; - /* 0x0846 */ u8 unk_846; - /* 0x0847 */ s8 unk_847[4]; - /* 0x084B */ s8 unk_84B[4]; - /* 0x084F */ s8 unk_84F; - /* 0x0850 */ s16 unk_850; // multipurpose timer - /* 0x0854 */ f32 unk_854; - /* 0x0858 */ f32 unk_858; - /* 0x085C */ f32 unk_85C; // stick length among other things - /* 0x0860 */ s16 unk_860; // stick flame timer among other things - /* 0x0862 */ s16 unk_862; // get item draw ID + 1 - /* 0x0864 */ f32 unk_864; - /* 0x0868 */ f32 unk_868; - /* 0x086C */ f32 unk_86C; - /* 0x0870 */ f32 unk_870; - /* 0x0874 */ f32 unk_874; - /* 0x0878 */ f32 unk_878; - /* 0x087C */ s16 unk_87C; - /* 0x087E */ s16 unk_87E; - /* 0x0880 */ f32 unk_880; - /* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found - /* 0x0888 */ f32 distToInteractWall; // distance to the colliding wall plane - /* 0x088C */ u8 unk_88C; - /* 0x088D */ u8 unk_88D; - /* 0x088E */ u8 unk_88E; - /* 0x088F */ u8 unk_88F; - /* 0x0890 */ u8 unk_890; - /* 0x0891 */ u8 shockTimer; - /* 0x0892 */ u8 unk_892; - /* 0x0893 */ u8 hoverBootsTimer; - /* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling - /* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down) - /* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope) - /* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful - /* 0x089C */ s16 unk_89C; - /* 0x089E */ u16 floorSfxOffset; - /* 0x08A0 */ u8 unk_8A0; - /* 0x08A1 */ u8 unk_8A1; - /* 0x08A2 */ s16 unk_8A2; - /* 0x08A4 */ f32 unk_8A4; - /* 0x08A8 */ f32 unk_8A8; - /* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces - /* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed + /* 0x0830 */ f32 upperAnimBlendWeight; + /* 0x0834 */ s16 unk_834; + /* 0x0836 */ s8 unk_836; + /* 0x0837 */ u8 unk_837; + /* 0x0838 */ f32 linearVelocity; + /* 0x083C */ s16 yaw; // General yaw value, used both for world and shape rotation. Current or target value depending on context. + /* 0x083E */ s16 zTargetYaw; // yaw relating to Z targeting/"parallel" mode + /* 0x0840 */ u16 underwaterTimer; + /* 0x0842 */ s8 meleeWeaponAnimation; + /* 0x0843 */ s8 meleeWeaponState; + /* 0x0844 */ s8 unk_844; + /* 0x0845 */ u8 unk_845; + /* 0x0846 */ u8 unk_846; + /* 0x0847 */ s8 unk_847[4]; + /* 0x084B */ s8 unk_84B[4]; + + /* 0x084F */ union { + s8 actionVar1; + } av1; // "Action Variable 1": context dependent variable that has different meanings depending on what action is currently running + + /* 0x0850 */ union { + s16 actionVar2; + } av2; // "Action Variable 2": context dependent variable that has different meanings depending on what action is currently running + + /* 0x0854 */ f32 unk_854; + /* 0x0858 */ f32 unk_858; + /* 0x085C */ f32 unk_85C; // stick length among other things + /* 0x0860 */ s16 unk_860; // stick flame timer among other things + /* 0x0862 */ s16 unk_862; // get item draw ID + 1 + /* 0x0864 */ f32 unk_864; + /* 0x0868 */ f32 unk_868; + /* 0x086C */ f32 unk_86C; + /* 0x0870 */ f32 unk_870; + /* 0x0874 */ f32 unk_874; + /* 0x0878 */ f32 unk_878; + /* 0x087C */ s16 unk_87C; + /* 0x087E */ s16 unk_87E; + /* 0x0880 */ f32 unk_880; + /* 0x0884 */ f32 yDistToLedge; // y distance to ground above an interact wall. LEDGE_DIST_MAX if no ground is found + /* 0x0888 */ f32 distToInteractWall; // xyz distance to the interact wall + /* 0x088C */ u8 ledgeClimbType; + /* 0x088D */ u8 ledgeClimbDelayTimer; + /* 0x088E */ u8 unk_88E; + /* 0x088F */ u8 unk_88F; + /* 0x0890 */ u8 unk_890; + /* 0x0891 */ u8 bodyShockTimer; + /* 0x0892 */ u8 unk_892; + /* 0x0893 */ u8 hoverBootsTimer; + /* 0x0894 */ s16 fallStartHeight; // last truncated Y position before falling + /* 0x0896 */ s16 fallDistance; // truncated Y distance the player has fallen so far (positive is down) + /* 0x0898 */ s16 floorPitch; // angle of the floor slope in the direction of current world yaw (positive for ascending slope) + /* 0x089A */ s16 floorPitchAlt; // the calculation for this value is bugged and doesn't represent anything meaningful + /* 0x089C */ s16 unk_89C; + /* 0x089E */ u16 floorSfxOffset; + /* 0x08A0 */ u8 unk_8A0; + /* 0x08A1 */ u8 unk_8A1; + /* 0x08A2 */ s16 unk_8A2; + /* 0x08A4 */ f32 unk_8A4; + /* 0x08A8 */ f32 unk_8A8; + /* 0x08AC */ f32 pushedSpeed; // Pushing player, examples include water currents, floor conveyors, climbing sloped surfaces + /* 0x08B0 */ s16 pushedYaw; // Yaw direction of player being pushed /* 0x08B4 */ WeaponInfo meleeWeaponInfo[3]; - /* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX]; - /* 0x09E0 */ MtxF mf_9E0; - /* 0x0A20 */ MtxF shieldMf; - /* 0x0A60 */ u8 isBurning; - /* 0x0A61 */ u8 flameTimers[PLAYER_BODYPART_MAX]; // one flame per body part - /* 0x0A73 */ u8 unk_A73; + /* 0x0908 */ Vec3f bodyPartsPos[PLAYER_BODYPART_MAX]; + /* 0x09E0 */ MtxF mf_9E0; + /* 0x0A20 */ MtxF shieldMf; + /* 0x0A60 */ u8 bodyIsBurning; + /* 0x0A61 */ u8 bodyFlameTimers[PLAYER_BODYPART_MAX]; // one flame per body part + /* 0x0A73 */ u8 unk_A73; /* 0x0A74 */ PlayerFuncA74 func_A74; - /* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame) - /* 0x0A79 */ u8 unk_A79; - /* 0x0A7A */ u8 unk_A7A; - /* 0x0A7B */ u8 unk_A7B; - /* 0x0A7C */ f32 unk_A7C; - /* 0x0A80 */ s16 unk_A80; - /* 0x0A82 */ u16 unk_A82; - /* 0x0A84 */ s16 unk_A84; - /* 0x0A86 */ s8 unk_A86; - /* 0x0A87 */ u8 unk_A87; - /* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position + /* 0x0A78 */ s8 invincibilityTimer; // prevents damage when nonzero (positive = visible, counts towards zero each frame) + /* 0x0A79 */ u8 floorTypeTimer; // counts up every frame the current floor type is the same as the last frame + /* 0x0A7A */ u8 floorProperty; + /* 0x0A7B */ u8 prevFloorType; + /* 0x0A7C */ f32 prevControlStickMagnitude; + /* 0x0A80 */ s16 prevControlStickAngle; + /* 0x0A82 */ u16 prevFloorSfxOffset; + /* 0x0A84 */ s16 unk_A84; + /* 0x0A86 */ s8 unk_A86; + /* 0x0A87 */ u8 unk_A87; + /* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position // #region SOH [General] // Upstream TODO: Rename these to be more obviously SoH specific /* */ PendingFlag pendingFlag; @@ -670,7 +677,7 @@ typedef struct Player { // #endregion // #region SOH [Enhancements] // Upstream TODO: Rename this to make it more obvious it is apart of an enhancement - /* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still? + /* */ u8 boomerangQuickRecall; // Has the player pressed the boomerang button while it's in the air still? // #endregion u8 ivanFloating; u8 ivanDamageMultiplier; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 854b7dc11..6d66d1c8b 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -111,9 +111,9 @@ void GameInteractor::RawAction::FreezePlayer() { void GameInteractor::RawAction::BurnPlayer() { Player* player = GET_PLAYER(gPlayState); for (int i = 0; i < 18; i++) { - player->flameTimers[i] = Rand_S16Offset(0, 200); + player->bodyFlameTimers[i] = Rand_S16Offset(0, 200); } - player->isBurning = true; + player->bodyIsBurning = true; func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0); } diff --git a/soh/src/code/code_800430A0.c b/soh/src/code/code_800430A0.c index abaf88405..379f4a3e6 100644 --- a/soh/src/code/code_800430A0.c +++ b/soh/src/code/code_800430A0.c @@ -48,7 +48,7 @@ void func_800432A0(CollisionContext* colCtx, s32 bgId, Actor* actor) { s16 rot = colCtx->dyna.bgActors[bgId].curTransform.rot.y - colCtx->dyna.bgActors[bgId].prevTransform.rot.y; if (actor->id == ACTOR_PLAYER) { - ((Player*)actor)->currentYaw += rot; + ((Player*)actor)->yaw += rot; } actor->shape.rot.y += rot; diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 411f4fb63..2ece7c2f1 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -634,7 +634,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); csCam->roll = 0; csCam->fov = 75.0f; - player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = spD0.yaw + 0x7FFF; + player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spD0.yaw + 0x7FFF; func_8002DF54(play, NULL, 8); break; case 3240: @@ -674,7 +674,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Quake_SetCountdown(i, D_80120698 - 20); break; case 3390: - player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = -0x3FD9; + player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = -0x3FD9; csInfo->keyFrames = D_80121DB4; csInfo->keyFrameCnt = 9; @@ -697,7 +697,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor D_80121F1C[0].eyeTargetInit = play->view.eye; D_80121F1C[0].fovTargetInit = play->view.fovy; Actor_GetFocus(&spA0, actor); - player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = spA0.rot.y; + player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spA0.rot.y; csInfo->keyFrames = D_80121F1C; csInfo->keyFrameCnt = 4; @@ -817,7 +817,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrameCnt = 2; } - player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = 0x3FFC; + player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = 0x3FFC; func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_8002DF54(play, NULL, 8); break; diff --git a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c index e74f3c0e4..0d33533ae 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c @@ -1480,11 +1480,11 @@ void BossFd_UpdateEffects(BossFd* this, PlayState* play) { if ((this->timers[3] == 0) && (sqrtf(SQ(diff.x) + SQ(diff.y) + SQ(diff.z)) < 20.0f)) { this->timers[3] = 50; func_8002F6D4(play, NULL, 5.0f, effect->kbAngle, 0.0f, 0x30); - if (player->isBurning == false) { - for (i2 = 0; i2 < ARRAY_COUNT(player->flameTimers); i2++) { - player->flameTimers[i2] = Rand_S16Offset(0, 200); + if (player->bodyIsBurning == false) { + for (i2 = 0; i2 < ARRAY_COUNT(player->bodyFlameTimers); i2++) { + player->bodyFlameTimers[i2] = Rand_S16Offset(0, 200); } - player->isBurning = true; + player->bodyIsBurning = true; } } if (effect->timer2 == 0) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index 5ec12f093..ba4a4fbc6 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -1918,11 +1918,11 @@ void func_80902348(BossGanon2* this, PlayState* play) { temp_f12 = -200.0f - player->actor.world.pos.z; if (sqrtf(SQ(temp_f2) + SQ(temp_f12)) > 784.0f) { - for (j = 0; j < ARRAY_COUNT(player->flameTimers); j++) { - player->flameTimers[j] = Rand_S16Offset(0, 200); + for (j = 0; j < ARRAY_COUNT(player->bodyFlameTimers); j++) { + player->bodyFlameTimers[j] = Rand_S16Offset(0, 200); } - player->isBurning = true; + player->bodyIsBurning = true; func_8002F6D4(play, &this->actor, 10.0f, Math_Atan2S(temp_f12, temp_f2), 0.0f, 0x10); sBossGanon2Zelda->unk_3C8 = 8; } diff --git a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c index 78534e851..74684df71 100644 --- a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c +++ b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c @@ -775,7 +775,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { } } if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_GRAB) { - player->unk_850 = 0xA; + player->av2.actionVar2 = 0xA; player->actor.speedXZ = player->actor.velocity.y = 0; Math_ApproachF(&player->actor.world.pos.x, this->grabPosRot.pos.x, 0.5f, 20.0f); Math_ApproachF(&player->actor.world.pos.y, this->grabPosRot.pos.y, 0.5f, 20.0f); @@ -833,7 +833,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed); } } - player->unk_850 = 0xA; + player->av2.actionVar2 = 0xA; player->actor.world.pos.x = this->grabPosRot.pos.x; player->actor.world.pos.y = this->grabPosRot.pos.y; player->actor.world.pos.z = this->grabPosRot.pos.z; @@ -852,7 +852,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { this->work[MO_TENT_ACTION_STATE] = MO_TENT_RETREAT; this->work[MO_TENT_INVINC_TIMER] = 50; if (&this->actor == player->actor.parent) { - player->unk_850 = 0x65; + player->av2.actionVar2 = 0x65; player->actor.parent = NULL; player->csAction = 0; if (this->timers[0] == 0) { @@ -882,7 +882,7 @@ void BossMo_Tentacle(BossMo* this, PlayState* play) { case MO_TENT_CUT: func_80078914(&this->tentTipPos, NA_SE_EV_WATER_WALL - SFX_FLAG); if (&this->actor == player->actor.parent) { - player->unk_850 = 0x65; + player->av2.actionVar2 = 0x65; player->actor.parent = NULL; player->csAction = 0; } @@ -1804,7 +1804,7 @@ void BossMo_CoreCollisionCheck(BossMo* this, PlayState* play) { sMorphaTent2->tent2KillTimer = 1; } if (player->actor.parent != NULL) { - player->unk_850 = 0x65; + player->av2.actionVar2 = 0x65; player->actor.parent = NULL; player->csAction = 0; } @@ -1823,7 +1823,7 @@ void BossMo_CoreCollisionCheck(BossMo* this, PlayState* play) { sMorphaTent1->timers[0] = 40; sMorphaTent1->actor.flags &= ~ACTOR_FLAG_TARGETABLE; if (player->actor.parent == &sMorphaTent1->actor) { - player->unk_850 = 0x65; + player->av2.actionVar2 = 0x65; player->actor.parent = NULL; player->csAction = 0; } diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index e811c0a35..b9f5c6f2c 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -384,8 +384,8 @@ void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { player->actor.world.pos.z = sRoomCenter.z; player->linearVelocity = player->actor.velocity.y = 0.0f; player->actor.shape.rot.y = -0x8000; - player->targetYaw = -0x8000; - player->currentYaw = -0x8000; + player->zTargetYaw = -0x8000; + player->yaw = -0x8000; player->fallStartHeight = 0; player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED; @@ -443,8 +443,8 @@ void BossSst_HeadIntro(BossSst* this, PlayState* play) { player->actor.world.pos.z = sRoomCenter.z; player->linearVelocity = 0; player->actor.shape.rot.y = -0x8000; - player->targetYaw = -0x8000; - player->currentYaw = -0x8000; + player->zTargetYaw = -0x8000; + player->yaw = -0x8000; } Math_Vec3f_Copy(&sCameraAt, &player->actor.world.pos); @@ -1757,7 +1757,7 @@ void BossSst_HandClap(BossSst* this, PlayState* play) { } if (player->actor.parent == &this->actor) { - player->unk_850 = 0; + player->av2.actionVar2 = 0; player->actor.world.pos = this->actor.world.pos; } } @@ -1852,7 +1852,7 @@ void BossSst_HandGrab(BossSst* this, PlayState* play) { this->actor.world.pos.x += this->actor.speedXZ * Math_SinS(this->actor.world.rot.y); this->actor.world.pos.z += this->actor.speedXZ * Math_CosS(this->actor.world.rot.y); if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { - player->unk_850 = 0; + player->av2.actionVar2 = 0; player->actor.world.pos = this->actor.world.pos; player->actor.shape.rot.y = this->actor.shape.rot.y; } @@ -1946,7 +1946,7 @@ void BossSst_HandSwing(BossSst* this, PlayState* play) { } if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { - player->unk_850 = 0; + player->av2.actionVar2 = 0; Math_Vec3f_Copy(&player->actor.world.pos, &this->actor.world.pos); player->actor.shape.rot.x = this->actor.shape.rot.x; player->actor.shape.rot.z = (this->vParity * -0x4000) + this->actor.shape.rot.z; @@ -2429,7 +2429,7 @@ void BossSst_HandReleasePlayer(BossSst* this, PlayState* play, s32 dropPlayer) { if (player->actor.parent == &this->actor) { player->actor.parent = NULL; - player->unk_850 = 100; + player->av2.actionVar2 = 100; this->colliderJntSph.base.ocFlags1 |= OC1_ON; OTHER_HAND(this)->colliderJntSph.base.ocFlags1 |= OC1_ON; if (dropPlayer) { diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 4f0eadd4b..9d0a68c38 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -777,12 +777,12 @@ s32 BossTw_BeamHitPlayerCheck(BossTw* this, PlayState* play) { if (sFreezeState == 0) { sFreezeState = 1; } - } else if (!player->isBurning) { - for (i = 0; i < ARRAY_COUNT(player->flameTimers); i++) { - player->flameTimers[i] = Rand_S16Offset(0, 200); + } else if (!player->bodyIsBurning) { + for (i = 0; i < ARRAY_COUNT(player->bodyFlameTimers); i++) { + player->bodyFlameTimers[i] = Rand_S16Offset(0, 200); } - player->isBurning = true; + player->bodyIsBurning = true; Player_PlaySfx(&player->actor, player->ageProperties->unk_92 + NA_SE_VO_LI_DEMO_DAMAGE); } } @@ -3154,7 +3154,7 @@ void BossTw_TwinrovaUpdate(Actor* thisx, PlayState* play2) { } } - if (player->isBurning && sShieldIceCharge != 0) { + if (player->bodyIsBurning && sShieldIceCharge != 0) { sShieldIceCharge = 4; } } @@ -4039,15 +4039,15 @@ void BossTw_BlastFire(BossTw* this, PlayState* play) { yDiff = sKoumePtr->groundBlastPos2.y - player->actor.world.pos.y; zDiff = sKoumePtr->groundBlastPos2.z - player->actor.world.pos.z; - if (!player->isBurning && (player->actor.bgCheckFlags & 1) && (fabsf(yDiff) < 10.0f) && + if (!player->bodyIsBurning && (player->actor.bgCheckFlags & 1) && (fabsf(yDiff) < 10.0f) && (sqrtf(SQ(xDiff) + SQ(zDiff)) < (sKoumePtr->workf[UNK_F13] * 4550.0f))) { s16 j; for (j = 0; j < 18; j++) { - player->flameTimers[j] = Rand_S16Offset(0, 200); + player->bodyFlameTimers[j] = Rand_S16Offset(0, 200); } - player->isBurning = 1; + player->bodyIsBurning = 1; if (this->work[BURN_TMR] == 0) { Player_PlaySfx(&player->actor, player->ageProperties->unk_92 + NA_SE_VO_LI_DEMO_DAMAGE); diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index bbd9b2826..22c850111 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -135,7 +135,7 @@ void DoorAna_WaitOpen(DoorAna* this, PlayState* play) { player = GET_PLAYER(play); if (Math_StepToF(&this->actor.scale.x, 0.01f, 0.001f)) { if ((this->actor.targetMode != 0) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (player->stateFlags1 & PLAYER_STATE1_FLOOR_DISABLED) && - (player->unk_84F == 0)) { + (player->av1.actionVar1 == 0)) { destinationIdx = ((this->actor.params >> 0xC) & 7) - 1; Play_SetupRespawnPoint(play, RESPAWN_MODE_RETURN, 0x4FF); gSaveContext.respawn[RESPAWN_MODE_RETURN].pos.y = this->actor.world.pos.y; diff --git a/soh/src/overlays/actors/ovl_En_Bdfire/z_en_bdfire.c b/soh/src/overlays/actors/ovl_En_Bdfire/z_en_bdfire.c index a3d6c923d..ab0b82d65 100644 --- a/soh/src/overlays/actors/ovl_En_Bdfire/z_en_bdfire.c +++ b/soh/src/overlays/actors/ovl_En_Bdfire/z_en_bdfire.c @@ -174,13 +174,13 @@ void func_809BC598(EnBdfire* this, PlayState* play) { Actor_Kill(&this->actor); return; } - } else if (!player->isBurning) { + } else if (!player->bodyIsBurning) { distToBurn = (this->actor.scale.x * 130.0f) / 4.2000003f; if (this->actor.xyzDistToPlayerSq < SQ(distToBurn)) { for (i = 0; i < 18; i++) { - player->flameTimers[i] = Rand_S16Offset(0, 200); + player->bodyFlameTimers[i] = Rand_S16Offset(0, 200); } - player->isBurning = true; + player->bodyIsBurning = true; func_8002F6D4(play, &this->actor, 20.0f, this->actor.world.rot.y, 0.0f, 8); osSyncPrintf("POWER\n"); } diff --git a/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c b/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c index 893f326d8..da6f43388 100644 --- a/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c +++ b/soh/src/overlays/actors/ovl_En_Dha/z_en_dha.c @@ -248,7 +248,7 @@ void EnDha_Wait(EnDha* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; } if (this->actor.home.rot.z != 0) { @@ -288,7 +288,7 @@ void EnDha_Wait(EnDha* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; } this->actor.home.rot.z = 1; @@ -309,7 +309,7 @@ void EnDha_TakeDamage(EnDha* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; } Math_SmoothStepToS(&this->limbAngleX[1], 0, 1, 2000, 0); @@ -347,7 +347,7 @@ void EnDha_Die(EnDha* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && (&this->actor == player->actor.parent)) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; } Math_SmoothStepToS(&this->limbAngleX[1], 0, 1, 0x7D0, 0); diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 3cb02e441..36c9c2818 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -616,7 +616,7 @@ void EnFr_Idle(EnFr* this, PlayState* play) { player->actor.world.pos.x = this->actor.world.pos.x; // x = 990.0f player->actor.world.pos.y = this->actor.world.pos.y; // y = 205.0f player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f - player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y; + player->yaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y; this->reward = GI_NONE; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = EnFr_Activate; diff --git a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c index 6190e2db9..43f6a6665 100644 --- a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c +++ b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c @@ -615,7 +615,7 @@ void EnMb_Stunned(EnMb* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); this->attack = ENMB_ATTACK_NONE; } @@ -740,7 +740,7 @@ void EnMb_SpearPatrolEndCharge(EnMb* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); } @@ -967,7 +967,7 @@ void EnMb_SpearPatrolPrepareAndCharge(EnMb* this, PlayState* play) { hasHitPlayer = true; player->actor.world.pos.z = this->actor.world.pos.z + Math_SinS(this->actor.shape.rot.y) * 10.0f + Math_CosS(this->actor.shape.rot.y) * 89.0f; - player->unk_850 = 0; + player->av2.actionVar2 = 0; player->actor.speedXZ = 0.0f; player->actor.velocity.y = 0.0f; } @@ -978,7 +978,7 @@ void EnMb_SpearPatrolPrepareAndCharge(EnMb* this, PlayState* play) { if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); } } @@ -1036,7 +1036,7 @@ void EnMb_SpearPatrolImmediateCharge(EnMb* this, PlayState* play) { hasHitPlayer = true; player->actor.world.pos.z = this->actor.world.pos.z + Math_SinS(this->actor.shape.rot.y) * 10.0f + Math_CosS(this->actor.shape.rot.y) * 89.0f; - player->unk_850 = 0; + player->av2.actionVar2 = 0; player->actor.speedXZ = 0.0f; player->actor.velocity.y = 0.0f; } @@ -1047,7 +1047,7 @@ void EnMb_SpearPatrolImmediateCharge(EnMb* this, PlayState* play) { if (player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); } this->attack = ENMB_ATTACK_NONE; @@ -1342,7 +1342,7 @@ void EnMb_SpearDead(EnMb* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 4.0f, this->actor.world.rot.y, 4.0f); this->attack = ENMB_ATTACK_NONE; } @@ -1425,7 +1425,7 @@ void EnMb_CheckColliding(EnMb* this, PlayState* play) { if ((player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY) && player->actor.parent == &this->actor) { player->stateFlags2 &= ~PLAYER_STATE2_GRABBED_BY_ENEMY; player->actor.parent = NULL; - player->unk_850 = 200; + player->av2.actionVar2 = 200; func_8002F71C(play, &this->actor, 6.0f, this->actor.world.rot.y, 6.0f); } this->damageEffect = this->actor.colChkInfo.damageEffect; diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 49e88f903..105db6719 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -190,7 +190,7 @@ void func_80AFB950(EnSi* this, PlayState* play) { player->actor.freezeTimer = 0; func_8083C148(GET_PLAYER(play), play); func_80078884(NA_SE_SY_CAMERA_ZOOM_UP); - player->currentYaw = player->actor.shape.rot.y; + player->yaw = player->actor.shape.rot.y; } } } diff --git a/soh/src/overlays/actors/ovl_En_Siofuki/z_en_siofuki.c b/soh/src/overlays/actors/ovl_En_Siofuki/z_en_siofuki.c index 81138e23c..e577a3d45 100644 --- a/soh/src/overlays/actors/ovl_En_Siofuki/z_en_siofuki.c +++ b/soh/src/overlays/actors/ovl_En_Siofuki/z_en_siofuki.c @@ -170,7 +170,7 @@ void func_80AFBE8C(EnSiofuki* this, PlayState* play) { } else { if (this->applySpeed) { player->linearVelocity = this->appliedSpeed + player->linearVelocity; - player->currentYaw = this->appliedYaw; + player->yaw = this->appliedYaw; } this->targetAppliedSpeed = 0.0f; diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index f2ff5f684..67c695872 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1367,7 +1367,7 @@ void EnSkj_SariasSongShortStumpUpdate(Actor* thisx, PlayState* play) { void EnSkj_TurnPlayer(EnSkj* this, Player* player) { Math_SmoothStepToS(&player->actor.shape.rot.y, this->actor.world.rot.y, 5, 2000, 0); player->actor.world.rot.y = player->actor.shape.rot.y; - player->currentYaw = player->actor.shape.rot.y; + player->yaw = player->actor.shape.rot.y; } void EnSkj_SetupWaitForOcarina(EnSkj* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c index 05b76cb0e..f0d9d3897 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c @@ -107,7 +107,7 @@ void EnSyatekiItm_Idle(EnSyatekiItm* this, PlayState* play) { player->actor.world.pos.x = -12.0f; player->actor.world.pos.y = 20.0f; player->actor.world.pos.z = 182.0f; - player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = 0x7F03; + player->yaw = player->actor.world.rot.y = player->actor.shape.rot.y = 0x7F03; player->actor.world.rot.x = player->actor.shape.rot.x = player->actor.world.rot.z = player->actor.shape.rot.z = 0; s32 ammunition = 15; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 71a6c1c22..d1c224088 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -65,9 +65,9 @@ typedef struct { typedef struct { /* 0x00 */ s8 damage; - /* 0x01 */ u8 unk_01; - /* 0x02 */ u8 unk_02; - /* 0x03 */ u8 unk_03; + /* 0x01 */ u8 rumbleStrength; + /* 0x02 */ u8 rumbleDuration; + /* 0x03 */ u8 rumbleDecreaseRate; /* 0x04 */ u16 sfxId; } FallImpactInfo; // size = 0x06 @@ -76,9 +76,28 @@ typedef struct { /* 0x0C */ s16 yaw; } SpecialRespawnInfo; // size = 0x10 +typedef enum { + /* 1 */ ANIMSFX_TYPE_1 = 1, + /* 2 */ ANIMSFX_TYPE_2, + /* 3 */ ANIMSFX_TYPE_3, + /* 4 */ ANIMSFX_TYPE_4, + /* 5 */ ANIMSFX_TYPE_5, + /* 6 */ ANIMSFX_TYPE_6, + /* 7 */ ANIMSFX_TYPE_7, + /* 8 */ ANIMSFX_TYPE_8, + /* 9 */ ANIMSFX_TYPE_9 +} AnimSfxType; + +#define ANIMSFX_SHIFT_TYPE(type) ((type) << 11) + +#define ANIMSFX_DATA(type, frame) ((ANIMSFX_SHIFT_TYPE(type) | ((frame)&0x7FF))) + +#define ANIMSFX_GET_TYPE(data) ((data)&0x7800) +#define ANIMSFX_GET_FRAME(data) ((data)&0x7FF) + typedef struct { /* 0x00 */ u16 sfxId; - /* 0x02 */ s16 field; + /* 0x02 */ s16 data; } AnimSfxEntry; // size = 0x04 typedef struct { @@ -120,24 +139,26 @@ typedef struct { }; } struct_80854B18; // size = 0x08 -void func_80833770(PlayState* play, Player* this); -void func_80833790(PlayState* play, Player* this); -void func_8083379C(PlayState* play, Player* this); -void func_8083377C(PlayState* play, Player* this); -void func_808337D4(PlayState* play, Player* this); -void func_80833910(PlayState* play, Player* this); -void func_80833984(PlayState* play, Player* this); void Player_InitItemAction(PlayState* play, Player* this, s8 itemAction); -s32 func_8083485C(Player* this, PlayState* play); -s32 func_808349DC(Player* this, PlayState* play); + +void Player_InitDefaultIA(PlayState* play, Player* this); +void Player_InitHammerIA(PlayState* play, Player* this); +void Player_InitBowOrSlingshotIA(PlayState* play, Player* this); +void Player_InitDekuStickIA(PlayState* play, Player* this); +void Player_InitExplosiveIA(PlayState* play, Player* this); +void Player_InitHookshotIA(PlayState* play, Player* this); +void Player_InitBoomerangIA(PlayState* play, Player* this); + s32 Player_UpperAction_ChangeHeldItem(Player* this, PlayState* play); +s32 func_8083485C(Player* this, PlayState* play); +s32 Player_UpperAction_Sword(Player* this, PlayState* play); s32 func_80834B5C(Player* this, PlayState* play); s32 func_80834C74(Player* this, PlayState* play); s32 func_8083501C(Player* this, PlayState* play); s32 func_808351D4(Player* this, PlayState* play); // Arrow nocked s32 func_808353D8(Player* this, PlayState* play); // Aiming in first person s32 func_80835588(Player* this, PlayState* play); -s32 func_808356E8(Player* this, PlayState* play); +s32 Player_UpperAction_CarryActor(Player* this, PlayState* play); s32 func_80835800(Player* this, PlayState* play); s32 func_80835884(Player* this, PlayState* play); // Start aiming boomerang s32 func_808358F0(Player* this, PlayState* play); // Aim boomerang @@ -145,65 +166,14 @@ s32 func_808359FC(Player* this, PlayState* play); // Throw boomerang s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play); // Throw boomerang Ivan s32 func_80835B60(Player* this, PlayState* play); // Boomerang active s32 func_80835C08(Player* this, PlayState* play); + void Player_UseItem(PlayState* play, Player* this, s32 item); void func_80839F90(Player* this, PlayState* play); -s32 func_80838A14(Player* this, PlayState* play); -s32 func_80839800(Player* this, PlayState* play); -s32 func_8083B040(Player* this, PlayState* play); -s32 func_8083B998(Player* this, PlayState* play); -s32 func_8083B644(Player* this, PlayState* play); -s32 func_8083BDBC(Player* this, PlayState* play); -s32 func_8083C1DC(Player* this, PlayState* play); -s32 func_8083C2B0(Player* this, PlayState* play); -s32 func_8083C544(Player* this, PlayState* play); s32 func_8083C61C(PlayState* play, Player* this); void func_8083CA20(PlayState* play, Player* this); void func_8083CA54(PlayState* play, Player* this); void func_8083CA9C(PlayState* play, Player* this); -s32 func_8083E0FC(Player* this, PlayState* play); void Player_SetPendingFlag(Player* this, PlayState* play); -s32 func_8083E5A8(Player* this, PlayState* play); -s32 func_8083EB44(Player* this, PlayState* play); -s32 func_8083F7BC(Player* this, PlayState* play); -void func_80840450(Player* this, PlayState* play); -void func_808407CC(Player* this, PlayState* play); -void func_80840BC8(Player* this, PlayState* play); -void func_80840DE4(Player* this, PlayState* play); -void func_808414F8(Player* this, PlayState* play); -void func_8084170C(Player* this, PlayState* play); -void func_808417FC(Player* this, PlayState* play); -void func_8084193C(Player* this, PlayState* play); -void func_80841BA8(Player* this, PlayState* play); -void func_80842180(Player* this, PlayState* play); -void func_8084227C(Player* this, PlayState* play); -void func_8084279C(Player* this, PlayState* play); -void func_808423EC(Player* this, PlayState* play); -void func_8084251C(Player* this, PlayState* play); -void func_80843188(Player* this, PlayState* play); -void func_808435C4(Player* this, PlayState* play); -void func_8084370C(Player* this, PlayState* play); -void func_8084377C(Player* this, PlayState* play); -void func_80843954(Player* this, PlayState* play); -void func_80843A38(Player* this, PlayState* play); -void func_80843CEC(Player* this, PlayState* play); -void func_8084411C(Player* this, PlayState* play); -void func_80844708(Player* this, PlayState* play); -void func_80844A44(Player* this, PlayState* play); -void func_80844AF4(Player* this, PlayState* play); -void func_80844E68(Player* this, PlayState* play); -void func_80845000(Player* this, PlayState* play); -void func_80845308(Player* this, PlayState* play); -void func_80845668(Player* this, PlayState* play); -void func_808458D0(Player* this, PlayState* play); -void func_80845CA4(Player* this, PlayState* play); -void func_80845EF8(Player* this, PlayState* play); -void func_80846050(Player* this, PlayState* play); -void func_80846120(Player* this, PlayState* play); -void func_80846260(Player* this, PlayState* play); -void func_80846358(Player* this, PlayState* play); -void func_80846408(Player* this, PlayState* play); -void func_808464B0(Player* this, PlayState* play); -void func_80846578(Player* this, PlayState* play); void func_80846648(PlayState* play, Player* this); void func_80846660(PlayState* play, Player* this); void func_808467D4(PlayState* play, Player* this); @@ -212,59 +182,10 @@ void func_808468E8(PlayState* play, Player* this); void func_80846978(PlayState* play, Player* this); void func_808469BC(PlayState* play, Player* this); void func_80846A68(PlayState* play, Player* this); -void func_8084B1D8(Player* this, PlayState* play); -void func_8084B530(Player* this, PlayState* play); -void func_8084B78C(Player* this, PlayState* play); -void func_8084B898(Player* this, PlayState* play); -void func_8084B9E4(Player* this, PlayState* play); -void func_8084BBE4(Player* this, PlayState* play); -void func_8084BDFC(Player* this, PlayState* play); -void func_8084BF1C(Player* this, PlayState* play); void Player_UpdateCommon(Player* this, PlayState* play, Input* input); -void func_8084C5F8(Player* this, PlayState* play); -void func_8084C760(Player* this, PlayState* play); -void func_8084C81C(Player* this, PlayState* play); -void func_8084CC98(Player* this, PlayState* play); -void func_8084D3E4(Player* this, PlayState* play); -void func_8084D610(Player* this, PlayState* play); -void func_8084D7C4(Player* this, PlayState* play); -void func_8084D84C(Player* this, PlayState* play); -void func_8084DAB4(Player* this, PlayState* play); -void func_8084DC48(Player* this, PlayState* play); -void func_8084E1EC(Player* this, PlayState* play); -void func_8084E30C(Player* this, PlayState* play); -void func_8084E368(Player* this, PlayState* play); -void func_8084E3C4(Player* this, PlayState* play); -void func_8084E604(Player* this, PlayState* play); -void func_8084E6D4(Player* this, PlayState* play); -void func_8084E9AC(Player* this, PlayState* play); -void func_8084EAC0(Player* this, PlayState* play); -void func_8084ECA4(Player* this, PlayState* play); -void func_8084EED8(Player* this, PlayState* play); -void func_8084EFC0(Player* this, PlayState* play); -void func_8084F104(Player* this, PlayState* play); -void func_8084F390(Player* this, PlayState* play); -void func_8084F608(Player* this, PlayState* play); -void func_8084F698(Player* this, PlayState* play); -void func_8084F710(Player* this, PlayState* play); -void func_8084F88C(Player* this, PlayState* play); -void func_8084F9A0(Player* this, PlayState* play); -void func_8084F9C0(Player* this, PlayState* play); -void func_8084FA54(Player* this, PlayState* play); -void func_8084FB10(Player* this, PlayState* play); -void func_8084FBF4(Player* this, PlayState* play); s32 func_8084FCAC(Player* this, PlayState* play); void func_8084FF7C(Player* this); void Player_UpdateBunnyEars(Player* this); -s32 func_80850224(Player* this, PlayState* play); -void func_808502D0(Player* this, PlayState* play); -void func_808505DC(Player* this, PlayState* play); -void func_8085063C(Player* this, PlayState* play); -void func_8085076C(Player* this, PlayState* play); -void func_808507F4(Player* this, PlayState* play); -void func_80850AEC(Player* this, PlayState* play); -void func_80850C68(Player* this, PlayState* play); -void func_80850E84(Player* this, PlayState* play); void func_80851008(PlayState* play, Player* this, void* anim); void func_80851030(PlayState* play, Player* this, void* anim); void func_80851050(PlayState* play, Player* this, void* anim); @@ -339,8 +260,7 @@ void func_808528C8(PlayState* play, Player* this, CsCmdActorAction* arg2); void func_80852944(PlayState* play, Player* this, CsCmdActorAction* arg2); void func_808529D0(PlayState* play, Player* this, CsCmdActorAction* arg2); void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2); -void func_80852E14(Player* this, PlayState* play); -s32 Player_IsDroppingFish(PlayState* play); +int Player_IsDroppingFish(PlayState* play); s32 Player_StartFishing(PlayState* play); s32 func_80852F38(PlayState* play, Player* this); s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction); @@ -349,6 +269,95 @@ s32 Player_InflictDamage(PlayState* play, s32 damage); s32 Player_InflictDamageModified(PlayState* play, s32 damage, u8 modified); void Player_StartTalking(PlayState* play, Actor* actor); +void Player_Action_80840450(Player* this, PlayState* play); +void Player_Action_808407CC(Player* this, PlayState* play); +void Player_Action_80840BC8(Player* this, PlayState* play); +void Player_Action_80840DE4(Player* this, PlayState* play); +void Player_Action_808414F8(Player* this, PlayState* play); +void Player_Action_8084170C(Player* this, PlayState* play); +void Player_Action_808417FC(Player* this, PlayState* play); +void Player_Action_8084193C(Player* this, PlayState* play); +void Player_Action_80841BA8(Player* this, PlayState* play); +void Player_Action_80842180(Player* this, PlayState* play); +void Player_Action_8084227C(Player* this, PlayState* play); +void Player_Action_8084279C(Player* this, PlayState* play); +void Player_Action_808423EC(Player* this, PlayState* play); +void Player_Action_8084251C(Player* this, PlayState* play); +void Player_Action_80843188(Player* this, PlayState* play); +void Player_Action_808435C4(Player* this, PlayState* play); +void Player_Action_8084370C(Player* this, PlayState* play); +void Player_Action_8084377C(Player* this, PlayState* play); +void Player_Action_80843954(Player* this, PlayState* play); +void Player_Action_80843A38(Player* this, PlayState* play); +void Player_Action_80843CEC(Player* this, PlayState* play); +void Player_Action_8084411C(Player* this, PlayState* play); +void Player_Action_80844708(Player* this, PlayState* play); +void Player_Action_80844A44(Player* this, PlayState* play); +void Player_Action_80844AF4(Player* this, PlayState* play); +void Player_Action_80844E68(Player* this, PlayState* play); +void Player_Action_80845000(Player* this, PlayState* play); +void Player_Action_80845308(Player* this, PlayState* play); +void Player_Action_80845668(Player* this, PlayState* play); +void Player_Action_808458D0(Player* this, PlayState* play); +void Player_Action_80845CA4(Player* this, PlayState* play); +void Player_Action_80845EF8(Player* this, PlayState* play); +void Player_Action_80846050(Player* this, PlayState* play); +void Player_Action_80846120(Player* this, PlayState* play); +void Player_Action_80846260(Player* this, PlayState* play); +void Player_Action_80846358(Player* this, PlayState* play); +void Player_Action_80846408(Player* this, PlayState* play); +void Player_Action_808464B0(Player* this, PlayState* play); +void Player_Action_80846578(Player* this, PlayState* play); +void Player_Action_8084B1D8(Player* this, PlayState* play); +void Player_Action_8084B530(Player* this, PlayState* play); +void Player_Action_8084B78C(Player* this, PlayState* play); +void Player_Action_8084B898(Player* this, PlayState* play); +void Player_Action_8084B9E4(Player* this, PlayState* play); +void Player_Action_8084BBE4(Player* this, PlayState* play); +void Player_Action_8084BDFC(Player* this, PlayState* play); +void Player_Action_8084BF1C(Player* this, PlayState* play); +void Player_Action_8084C5F8(Player* this, PlayState* play); +void Player_Action_8084C760(Player* this, PlayState* play); +void Player_Action_8084C81C(Player* this, PlayState* play); +void Player_Action_8084CC98(Player* this, PlayState* play); +void Player_Action_8084D3E4(Player* this, PlayState* play); +void Player_Action_8084D610(Player* this, PlayState* play); +void Player_Action_8084D7C4(Player* this, PlayState* play); +void Player_Action_8084D84C(Player* this, PlayState* play); +void Player_Action_8084DAB4(Player* this, PlayState* play); +void Player_Action_8084DC48(Player* this, PlayState* play); +void Player_Action_8084E1EC(Player* this, PlayState* play); +void Player_Action_8084E30C(Player* this, PlayState* play); +void Player_Action_8084E368(Player* this, PlayState* play); +void Player_Action_8084E3C4(Player* this, PlayState* play); +void Player_Action_8084E604(Player* this, PlayState* play); +void Player_Action_8084E6D4(Player* this, PlayState* play); +void Player_Action_8084E9AC(Player* this, PlayState* play); +void Player_Action_8084EAC0(Player* this, PlayState* play); +void Player_Action_8084ECA4(Player* this, PlayState* play); +void Player_Action_8084EED8(Player* this, PlayState* play); +void Player_Action_8084EFC0(Player* this, PlayState* play); +void Player_Action_8084F104(Player* this, PlayState* play); +void Player_Action_8084F390(Player* this, PlayState* play); +void Player_Action_8084F608(Player* this, PlayState* play); +void Player_Action_8084F698(Player* this, PlayState* play); +void Player_Action_8084F710(Player* this, PlayState* play); +void Player_Action_8084F88C(Player* this, PlayState* play); +void Player_Action_8084F9A0(Player* this, PlayState* play); +void Player_Action_8084F9C0(Player* this, PlayState* play); +void Player_Action_8084FA54(Player* this, PlayState* play); +void Player_Action_8084FB10(Player* this, PlayState* play); +void Player_Action_8084FBF4(Player* this, PlayState* play); +void Player_Action_808502D0(Player* this, PlayState* play); +void Player_Action_808505DC(Player* this, PlayState* play); +void Player_Action_8085063C(Player* this, PlayState* play); +void Player_Action_8085076C(Player* this, PlayState* play); +void Player_Action_808507F4(Player* this, PlayState* play); +void Player_Action_80850AEC(Player* this, PlayState* play); +void Player_Action_80850C68(Player* this, PlayState* play); +void Player_Action_80850E84(Player* this, PlayState* play); +void Player_Action_CsAction(Player* this, PlayState* play); + // .bss part 1 static s32 D_80858AA0; static s32 D_80858AA4; @@ -384,108 +393,108 @@ static u8 sUpperBodyLimbCopyMap[PLAYER_LIMB_MAX] = { static PlayerAgeProperties sAgeProperties[] = { { - 56.0f, - 90.0f, - 1.0f, - 111.0f, - 70.0f, - 79.4f, - 59.0f, - 41.0f, - 19.0f, - 36.0f, - 44.8f, - 56.0f, - 68.0f, - 70.0f, - 18.0f, - 15.0f, - 70.0f, - { 9, 4671, 359 }, + 56.0f, // ceilingCheckHeight + 90.0f, // unk_04 + 1.0f, // unk_08 + 111.0f, // unk_0C + 70.0f, // unk_10 + 79.4f, // unk_14 + 59.0f, // unk_18 + 41.0f, // unk_1C + 19.0f, // unk_20 + 36.0f, // unk_24 + 44.8f, // unk_28 + 56.0f, // unk_2C + 68.0f, // unk_30 + 70.0f, // unk_34 + 18.0f, // wallCheckRadius + 15.0f, // unk_3C + 70.0f, // unk_40 + { 9, 4671, 359 }, // unk_44 { { 8, 4694, 380 }, { 9, 6122, 359 }, { 8, 4694, 380 }, { 9, 6122, 359 }, - }, + }, // unk_4A { { 9, 6122, 359 }, { 9, 7693, 380 }, { 9, 6122, 359 }, { 9, 7693, 380 }, - }, + }, // unk_62 { { 8, 4694, 380 }, { 9, 6122, 359 }, - }, + }, // unk_7A { { -1592, 4694, 380 }, { -1591, 6122, 359 }, - }, - 0, - 0x80, - &gPlayerAnim_link_demo_Tbox_open, - &gPlayerAnim_link_demo_back_to_past, - &gPlayerAnim_link_demo_return_to_past, - &gPlayerAnim_link_normal_climb_startA, - &gPlayerAnim_link_normal_climb_startB, + }, // unk_86 + 0, // unk_92 + 0x80, // unk_94 + &gPlayerAnim_link_demo_Tbox_open, // unk_98 + &gPlayerAnim_link_demo_back_to_past, // unk_9C + &gPlayerAnim_link_demo_return_to_past, // unk_A0 + &gPlayerAnim_link_normal_climb_startA, // unk_A4 + &gPlayerAnim_link_normal_climb_startB, // unk_A8 { &gPlayerAnim_link_normal_climb_upL, &gPlayerAnim_link_normal_climb_upR, &gPlayerAnim_link_normal_Fclimb_upL, - &gPlayerAnim_link_normal_Fclimb_upR }, - { &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, - { &gPlayerAnim_link_normal_climb_endAL, &gPlayerAnim_link_normal_climb_endAR }, - { &gPlayerAnim_link_normal_climb_endBR, &gPlayerAnim_link_normal_climb_endBL }, + &gPlayerAnim_link_normal_Fclimb_upR }, // unk_AC + { &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, // unk_BC + { &gPlayerAnim_link_normal_climb_endAL, &gPlayerAnim_link_normal_climb_endAR }, // unk_C4 + { &gPlayerAnim_link_normal_climb_endBR, &gPlayerAnim_link_normal_climb_endBL }, // unk_CC }, { - 40.0f, - 60.0f, - 11.0f / 17.0f, - 71.0f, - 50.0f, - 47.0f, - 39.0f, - 27.0f, - 19.0f, - 22.0f, - 29.6f, - 32.0f, - 48.0f, - 70.0f * (11.0f / 17.0f), - 14.0f, - 12.0f, - 55.0f, - { -24, 3565, 876 }, + 40.0f, // ceilingCheckHeight + 60.0f, // unk_04 + 11.0f / 17.0f, // unk_08 + 71.0f, // unk_0C + 50.0f, // unk_10 + 47.0f, // unk_14 + 39.0f, // unk_18 + 27.0f, // unk_1C + 19.0f, // unk_20 + 22.0f, // unk_24 + 29.6f, // unk_28 + 32.0f, // unk_2C + 48.0f, // unk_30 + 70.0f * (11.0f / 17.0f), // unk_34 + 14.0f, // wallCheckRadius + 12.0f, // unk_3C + 55.0f, // unk_40 + { -24, 3565, 876 }, // unk_44 { { -24, 3474, 862 }, { -24, 4977, 937 }, { 8, 4694, 380 }, { 9, 6122, 359 }, - }, + }, // unk_4A { { -24, 4977, 937 }, { -24, 6495, 937 }, { 9, 6122, 359 }, { 9, 7693, 380 }, - }, + }, // unk_62 { { 8, 4694, 380 }, { 9, 6122, 359 }, - }, + }, // unk_7A { { -1592, 4694, 380 }, { -1591, 6122, 359 }, - }, - 0x20, - 0, - &gPlayerAnim_clink_demo_Tbox_open, - &gPlayerAnim_clink_demo_goto_future, - &gPlayerAnim_clink_demo_return_to_future, - &gPlayerAnim_clink_normal_climb_startA, - &gPlayerAnim_clink_normal_climb_startB, + }, // unk_86 + 0x20, // unk_92 + 0, // unk_94 + &gPlayerAnim_clink_demo_Tbox_open, // unk_98 + &gPlayerAnim_clink_demo_goto_future, // unk_9C + &gPlayerAnim_clink_demo_return_to_future, // unk_A0 + &gPlayerAnim_clink_normal_climb_startA, // unk_A4 + &gPlayerAnim_clink_normal_climb_startB, // unk_A8 { &gPlayerAnim_clink_normal_climb_upL, &gPlayerAnim_clink_normal_climb_upR, &gPlayerAnim_link_normal_Fclimb_upL, - &gPlayerAnim_link_normal_Fclimb_upR }, - { &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, - { &gPlayerAnim_clink_normal_climb_endAL, &gPlayerAnim_clink_normal_climb_endAR }, - { &gPlayerAnim_clink_normal_climb_endBR, &gPlayerAnim_clink_normal_climb_endBL }, + &gPlayerAnim_link_normal_Fclimb_upR }, // unk_AC + { &gPlayerAnim_link_normal_Fclimb_sideL, &gPlayerAnim_link_normal_Fclimb_sideR }, // unk_BC + { &gPlayerAnim_clink_normal_climb_endAL, &gPlayerAnim_clink_normal_climb_endAR }, // unk_C4 + { &gPlayerAnim_clink_normal_climb_endBR, &gPlayerAnim_clink_normal_climb_endBL }, // unk_CC }, }; @@ -499,7 +508,7 @@ static f32 D_808535E8 = 1.0f; static f32 D_808535EC = 1.0f; static u32 sTouchedWallFlags = 0; static u32 sConveyorSpeed = 0; -static s16 sIsFloorConveyor = 0; +static s16 sIsFloorConveyor = false; static s16 sConveyorYaw = 0; static f32 sYDistToFloor = 0.0f; static s32 sPrevFloorProperty = 0; @@ -955,50 +964,53 @@ static LinkAnimationHeader* D_80853D7C[][2] = { }; static AnimSfxEntry D_80853DEC[] = { - { NA_SE_VO_LI_SNEEZE, -0x2008 }, + { NA_SE_VO_LI_SNEEZE, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 8) }, }; static AnimSfxEntry D_80853DF0[] = { - { NA_SE_VO_LI_SWEAT, -0x2012 }, + { NA_SE_VO_LI_SWEAT, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 18) }, }; static AnimSfxEntry D_80853DF4[] = { - { NA_SE_VO_LI_BREATH_REST, -0x200D }, + { NA_SE_VO_LI_BREATH_REST, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 13) }, }; static AnimSfxEntry D_80853DF8[] = { - { NA_SE_VO_LI_BREATH_REST, -0x200A }, + { NA_SE_VO_LI_BREATH_REST, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 10) }, }; static AnimSfxEntry D_80853DFC[] = { - { NA_SE_PL_CALM_HIT, 0x82C }, { NA_SE_PL_CALM_HIT, 0x830 }, { NA_SE_PL_CALM_HIT, 0x834 }, - { NA_SE_PL_CALM_HIT, 0x838 }, { NA_SE_PL_CALM_HIT, -0x83C }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 44) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 48) }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 52) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 56) }, + { NA_SE_PL_CALM_HIT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 60) }, }; static AnimSfxEntry D_80853E10[] = { - { 0, 0x4019 }, { 0, 0x401E }, { 0, 0x402C }, { 0, 0x4030 }, { 0, 0x4034 }, { 0, -0x4038 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 25) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 30) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 44) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 48) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 52) }, { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 56) }, }; static AnimSfxEntry D_80853E28[] = { - { NA_SE_IT_SHIELD_POSTURE, 0x810 }, - { NA_SE_IT_SHIELD_POSTURE, 0x814 }, - { NA_SE_IT_SHIELD_POSTURE, -0x846 }, + { NA_SE_IT_SHIELD_POSTURE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 16) }, + { NA_SE_IT_SHIELD_POSTURE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) }, + { NA_SE_IT_SHIELD_POSTURE, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 70) }, }; static AnimSfxEntry D_80853E34[] = { - { NA_SE_IT_HAMMER_SWING, 0x80A }, - { NA_SE_VO_LI_AUTO_JUMP, 0x200A }, - { NA_SE_IT_SWORD_SWING, 0x816 }, - { NA_SE_VO_LI_SWORD_N, -0x2016 }, + { NA_SE_IT_HAMMER_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) }, + { NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 10) }, + { NA_SE_IT_SWORD_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 22) }, + { NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 22) }, }; static AnimSfxEntry D_80853E44[] = { - { NA_SE_IT_SWORD_SWING, 0x827 }, - { NA_SE_VO_LI_SWORD_N, -0x2027 }, + { NA_SE_IT_SWORD_SWING, ANIMSFX_DATA(ANIMSFX_TYPE_1, 39) }, + { NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 39) }, }; static AnimSfxEntry D_80853E4C[] = { - { NA_SE_VO_LI_RELAX, -0x2014 }, + { NA_SE_VO_LI_RELAX, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) }, }; static AnimSfxEntry* D_80853E50[] = { @@ -1081,143 +1093,143 @@ u8 gWalkSpeedToggle1; u8 gWalkSpeedToggle2; static s32 (*sItemActionUpdateFuncs[])(Player* this, PlayState* play) = { - func_8083485C, // PLAYER_IA_NONE - func_8083485C, // PLAYER_IA_SWORD_CS - func_8083485C, // PLAYER_IA_FISHING_POLE - func_808349DC, // PLAYER_IA_SWORD_MASTER - func_808349DC, // PLAYER_IA_SWORD_KOKIRI - func_808349DC, // PLAYER_IA_SWORD_BIGGORON - func_8083485C, // PLAYER_IA_DEKU_STICK - func_8083485C, // PLAYER_IA_HAMMER - func_8083501C, // PLAYER_IA_BOW - func_8083501C, // PLAYER_IA_BOW_FIRE - func_8083501C, // PLAYER_IA_BOW_ICE - func_8083501C, // PLAYER_IA_BOW_LIGHT - func_8083501C, // PLAYER_IA_BOW_0C - func_8083501C, // PLAYER_IA_BOW_0D - func_8083501C, // PLAYER_IA_BOW_0E - func_8083501C, // PLAYER_IA_SLINGSHOT - func_8083501C, // PLAYER_IA_HOOKSHOT - func_8083501C, // PLAYER_IA_LONGSHOT - func_808356E8, // PLAYER_IA_BOMB - func_808356E8, // PLAYER_IA_BOMBCHU - func_80835800, // PLAYER_IA_BOOMERANG - func_8083485C, // PLAYER_IA_MAGIC_SPELL_15 - func_8083485C, // PLAYER_IA_MAGIC_SPELL_16 - func_8083485C, // PLAYER_IA_MAGIC_SPELL_17 - func_8083485C, // PLAYER_IA_FARORES_WIND - func_8083485C, // PLAYER_IA_NAYRUS_LOVE - func_8083485C, // PLAYER_IA_DINS_FIRE - func_8083485C, // PLAYER_IA_DEKU_NUT - func_8083485C, // PLAYER_IA_OCARINA_FAIRY - func_8083485C, // PLAYER_IA_OCARINA_OF_TIME - func_8083485C, // PLAYER_IA_BOTTLE - func_8083485C, // PLAYER_IA_BOTTLE_FISH - func_8083485C, // PLAYER_IA_BOTTLE_FIRE - func_8083485C, // PLAYER_IA_BOTTLE_BUG - func_8083485C, // PLAYER_IA_BOTTLE_POE - func_8083485C, // PLAYER_IA_BOTTLE_BIG_POE - func_8083485C, // PLAYER_IA_BOTTLE_RUTOS_LETTER - func_8083485C, // PLAYER_IA_BOTTLE_POTION_RED - func_8083485C, // PLAYER_IA_BOTTLE_POTION_BLUE - func_8083485C, // PLAYER_IA_BOTTLE_POTION_GREEN - func_8083485C, // PLAYER_IA_BOTTLE_MILK_FULL - func_8083485C, // PLAYER_IA_BOTTLE_MILK_HALF - func_8083485C, // PLAYER_IA_BOTTLE_FAIRY - func_8083485C, // PLAYER_IA_ZELDAS_LETTER - func_8083485C, // PLAYER_IA_WEIRD_EGG - func_8083485C, // PLAYER_IA_CHICKEN - func_8083485C, // PLAYER_IA_MAGIC_BEAN - func_8083485C, // PLAYER_IA_POCKET_EGG - func_8083485C, // PLAYER_IA_POCKET_CUCCO - func_8083485C, // PLAYER_IA_COJIRO - func_8083485C, // PLAYER_IA_ODD_MUSHROOM - func_8083485C, // PLAYER_IA_ODD_POTION - func_8083485C, // PLAYER_IA_POACHERS_SAW - func_8083485C, // PLAYER_IA_BROKEN_GORONS_SWORD - func_8083485C, // PLAYER_IA_PRESCRIPTION - func_8083485C, // PLAYER_IA_FROG - func_8083485C, // PLAYER_IA_EYEDROPS - func_8083485C, // PLAYER_IA_CLAIM_CHECK - func_8083485C, // PLAYER_IA_MASK_KEATON - func_8083485C, // PLAYER_IA_MASK_SKULL - func_8083485C, // PLAYER_IA_MASK_SPOOKY - func_8083485C, // PLAYER_IA_MASK_BUNNY_HOOD - func_8083485C, // PLAYER_IA_MASK_GORON - func_8083485C, // PLAYER_IA_MASK_ZORA - func_8083485C, // PLAYER_IA_MASK_GERUDO - func_8083485C, // PLAYER_IA_MASK_TRUTH - func_8083485C, // PLAYER_IA_LENS_OF_TRUTH + func_8083485C, // PLAYER_IA_NONE + func_8083485C, // PLAYER_IA_SWORD_CS + func_8083485C, // PLAYER_IA_FISHING_POLE + Player_UpperAction_Sword, // PLAYER_IA_SWORD_MASTER + Player_UpperAction_Sword, // PLAYER_IA_SWORD_KOKIRI + Player_UpperAction_Sword, // PLAYER_IA_SWORD_BIGGORON + func_8083485C, // PLAYER_IA_DEKU_STICK + func_8083485C, // PLAYER_IA_HAMMER + func_8083501C, // PLAYER_IA_BOW + func_8083501C, // PLAYER_IA_BOW_FIRE + func_8083501C, // PLAYER_IA_BOW_ICE + func_8083501C, // PLAYER_IA_BOW_LIGHT + func_8083501C, // PLAYER_IA_BOW_0C + func_8083501C, // PLAYER_IA_BOW_0D + func_8083501C, // PLAYER_IA_BOW_0E + func_8083501C, // PLAYER_IA_SLINGSHOT + func_8083501C, // PLAYER_IA_HOOKSHOT + func_8083501C, // PLAYER_IA_LONGSHOT + Player_UpperAction_CarryActor, // PLAYER_IA_BOMB + Player_UpperAction_CarryActor, // PLAYER_IA_BOMBCHU + func_80835800, // PLAYER_IA_BOOMERANG + func_8083485C, // PLAYER_IA_MAGIC_SPELL_15 + func_8083485C, // PLAYER_IA_MAGIC_SPELL_16 + func_8083485C, // PLAYER_IA_MAGIC_SPELL_17 + func_8083485C, // PLAYER_IA_FARORES_WIND + func_8083485C, // PLAYER_IA_NAYRUS_LOVE + func_8083485C, // PLAYER_IA_DINS_FIRE + func_8083485C, // PLAYER_IA_DEKU_NUT + func_8083485C, // PLAYER_IA_OCARINA_FAIRY + func_8083485C, // PLAYER_IA_OCARINA_OF_TIME + func_8083485C, // PLAYER_IA_BOTTLE + func_8083485C, // PLAYER_IA_BOTTLE_FISH + func_8083485C, // PLAYER_IA_BOTTLE_FIRE + func_8083485C, // PLAYER_IA_BOTTLE_BUG + func_8083485C, // PLAYER_IA_BOTTLE_POE + func_8083485C, // PLAYER_IA_BOTTLE_BIG_POE + func_8083485C, // PLAYER_IA_BOTTLE_RUTOS_LETTER + func_8083485C, // PLAYER_IA_BOTTLE_POTION_RED + func_8083485C, // PLAYER_IA_BOTTLE_POTION_BLUE + func_8083485C, // PLAYER_IA_BOTTLE_POTION_GREEN + func_8083485C, // PLAYER_IA_BOTTLE_MILK_FULL + func_8083485C, // PLAYER_IA_BOTTLE_MILK_HALF + func_8083485C, // PLAYER_IA_BOTTLE_FAIRY + func_8083485C, // PLAYER_IA_ZELDAS_LETTER + func_8083485C, // PLAYER_IA_WEIRD_EGG + func_8083485C, // PLAYER_IA_CHICKEN + func_8083485C, // PLAYER_IA_MAGIC_BEAN + func_8083485C, // PLAYER_IA_POCKET_EGG + func_8083485C, // PLAYER_IA_POCKET_CUCCO + func_8083485C, // PLAYER_IA_COJIRO + func_8083485C, // PLAYER_IA_ODD_MUSHROOM + func_8083485C, // PLAYER_IA_ODD_POTION + func_8083485C, // PLAYER_IA_POACHERS_SAW + func_8083485C, // PLAYER_IA_BROKEN_GORONS_SWORD + func_8083485C, // PLAYER_IA_PRESCRIPTION + func_8083485C, // PLAYER_IA_FROG + func_8083485C, // PLAYER_IA_EYEDROPS + func_8083485C, // PLAYER_IA_CLAIM_CHECK + func_8083485C, // PLAYER_IA_MASK_KEATON + func_8083485C, // PLAYER_IA_MASK_SKULL + func_8083485C, // PLAYER_IA_MASK_SPOOKY + func_8083485C, // PLAYER_IA_MASK_BUNNY_HOOD + func_8083485C, // PLAYER_IA_MASK_GORON + func_8083485C, // PLAYER_IA_MASK_ZORA + func_8083485C, // PLAYER_IA_MASK_GERUDO + func_8083485C, // PLAYER_IA_MASK_TRUTH + func_8083485C, // PLAYER_IA_LENS_OF_TRUTH }; static void (*sItemActionInitFuncs[])(PlayState* play, Player* this) = { - func_80833770, // PLAYER_IA_NONE - func_80833770, // PLAYER_IA_SWORD_CS - func_80833770, // PLAYER_IA_FISHING_POLE - func_80833770, // PLAYER_IA_SWORD_MASTER - func_80833770, // PLAYER_IA_SWORD_KOKIRI - func_80833770, // PLAYER_IA_SWORD_BIGGORON - func_8083377C, // PLAYER_IA_DEKU_STICK - func_80833790, // PLAYER_IA_HAMMER - func_8083379C, // PLAYER_IA_BOW - func_8083379C, // PLAYER_IA_BOW_FIRE - func_8083379C, // PLAYER_IA_BOW_ICE - func_8083379C, // PLAYER_IA_BOW_LIGHT - func_8083379C, // PLAYER_IA_BOW_0C - func_8083379C, // PLAYER_IA_BOW_0D - func_8083379C, // PLAYER_IA_BOW_0E - func_8083379C, // PLAYER_IA_SLINGSHOT - func_80833910, // PLAYER_IA_HOOKSHOT - func_80833910, // PLAYER_IA_LONGSHOT - func_808337D4, // PLAYER_IA_BOMB - func_808337D4, // PLAYER_IA_BOMBCHU - func_80833984, // PLAYER_IA_BOOMERANG - func_80833770, // PLAYER_IA_MAGIC_SPELL_15 - func_80833770, // PLAYER_IA_MAGIC_SPELL_16 - func_80833770, // PLAYER_IA_MAGIC_SPELL_17 - func_80833770, // PLAYER_IA_FARORES_WIND - func_80833770, // PLAYER_IA_NAYRUS_LOVE - func_80833770, // PLAYER_IA_DINS_FIRE - func_80833770, // PLAYER_IA_DEKU_NUT - func_80833770, // PLAYER_IA_OCARINA_FAIRY - func_80833770, // PLAYER_IA_OCARINA_OF_TIME - func_80833770, // PLAYER_IA_BOTTLE - func_80833770, // PLAYER_IA_BOTTLE_FISH - func_80833770, // PLAYER_IA_BOTTLE_FIRE - func_80833770, // PLAYER_IA_BOTTLE_BUG - func_80833770, // PLAYER_IA_BOTTLE_POE - func_80833770, // PLAYER_IA_BOTTLE_BIG_POE - func_80833770, // PLAYER_IA_BOTTLE_RUTOS_LETTER - func_80833770, // PLAYER_IA_BOTTLE_POTION_RED - func_80833770, // PLAYER_IA_BOTTLE_POTION_BLUE - func_80833770, // PLAYER_IA_BOTTLE_POTION_GREEN - func_80833770, // PLAYER_IA_BOTTLE_MILK_FULL - func_80833770, // PLAYER_IA_BOTTLE_MILK_HALF - func_80833770, // PLAYER_IA_BOTTLE_FAIRY - func_80833770, // PLAYER_IA_ZELDAS_LETTER - func_80833770, // PLAYER_IA_WEIRD_EGG - func_80833770, // PLAYER_IA_CHICKEN - func_80833770, // PLAYER_IA_MAGIC_BEAN - func_80833770, // PLAYER_IA_POCKET_EGG - func_80833770, // PLAYER_IA_POCKET_CUCCO - func_80833770, // PLAYER_IA_COJIRO - func_80833770, // PLAYER_IA_ODD_MUSHROOM - func_80833770, // PLAYER_IA_ODD_POTION - func_80833770, // PLAYER_IA_POACHERS_SAW - func_80833770, // PLAYER_IA_BROKEN_GORONS_SWORD - func_80833770, // PLAYER_IA_PRESCRIPTION - func_80833770, // PLAYER_IA_FROG - func_80833770, // PLAYER_IA_EYEDROPS - func_80833770, // PLAYER_IA_CLAIM_CHECK - func_80833770, // PLAYER_IA_MASK_KEATON - func_80833770, // PLAYER_IA_MASK_SKULL - func_80833770, // PLAYER_IA_MASK_SPOOKY - func_80833770, // PLAYER_IA_MASK_BUNNY_HOOD - func_80833770, // PLAYER_IA_MASK_GORON - func_80833770, // PLAYER_IA_MASK_ZORA - func_80833770, // PLAYER_IA_MASK_GERUDO - func_80833770, // PLAYER_IA_MASK_TRUTH - func_80833770, // PLAYER_IA_LENS_OF_TRUTH + Player_InitDefaultIA, // PLAYER_IA_NONE + Player_InitDefaultIA, // PLAYER_IA_SWORD_CS + Player_InitDefaultIA, // PLAYER_IA_FISHING_POLE + Player_InitDefaultIA, // PLAYER_IA_SWORD_MASTER + Player_InitDefaultIA, // PLAYER_IA_SWORD_KOKIRI + Player_InitDefaultIA, // PLAYER_IA_SWORD_BIGGORON + Player_InitDekuStickIA, // PLAYER_IA_DEKU_STICK + Player_InitHammerIA, // PLAYER_IA_HAMMER + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_FIRE + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_ICE + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_LIGHT + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0C + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0D + Player_InitBowOrSlingshotIA, // PLAYER_IA_BOW_0E + Player_InitBowOrSlingshotIA, // PLAYER_IA_SLINGSHOT + Player_InitHookshotIA, // PLAYER_IA_HOOKSHOT + Player_InitHookshotIA, // PLAYER_IA_LONGSHOT + Player_InitExplosiveIA, // PLAYER_IA_BOMB + Player_InitExplosiveIA, // PLAYER_IA_BOMBCHU + Player_InitBoomerangIA, // PLAYER_IA_BOOMERANG + Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_15 + Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_16 + Player_InitDefaultIA, // PLAYER_IA_MAGIC_SPELL_17 + Player_InitDefaultIA, // PLAYER_IA_FARORES_WIND + Player_InitDefaultIA, // PLAYER_IA_NAYRUS_LOVE + Player_InitDefaultIA, // PLAYER_IA_DINS_FIRE + Player_InitDefaultIA, // PLAYER_IA_DEKU_NUT + Player_InitDefaultIA, // PLAYER_IA_OCARINA_FAIRY + Player_InitDefaultIA, // PLAYER_IA_OCARINA_OF_TIME + Player_InitDefaultIA, // PLAYER_IA_BOTTLE + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FISH + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FIRE + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_BUG + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POE + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_BIG_POE + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_RUTOS_LETTER + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_RED + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_BLUE + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_POTION_GREEN + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_MILK_FULL + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_MILK_HALF + Player_InitDefaultIA, // PLAYER_IA_BOTTLE_FAIRY + Player_InitDefaultIA, // PLAYER_IA_ZELDAS_LETTER + Player_InitDefaultIA, // PLAYER_IA_WEIRD_EGG + Player_InitDefaultIA, // PLAYER_IA_CHICKEN + Player_InitDefaultIA, // PLAYER_IA_MAGIC_BEAN + Player_InitDefaultIA, // PLAYER_IA_POCKET_EGG + Player_InitDefaultIA, // PLAYER_IA_POCKET_CUCCO + Player_InitDefaultIA, // PLAYER_IA_COJIRO + Player_InitDefaultIA, // PLAYER_IA_ODD_MUSHROOM + Player_InitDefaultIA, // PLAYER_IA_ODD_POTION + Player_InitDefaultIA, // PLAYER_IA_POACHERS_SAW + Player_InitDefaultIA, // PLAYER_IA_BROKEN_GORONS_SWORD + Player_InitDefaultIA, // PLAYER_IA_PRESCRIPTION + Player_InitDefaultIA, // PLAYER_IA_FROG + Player_InitDefaultIA, // PLAYER_IA_EYEDROPS + Player_InitDefaultIA, // PLAYER_IA_CLAIM_CHECK + Player_InitDefaultIA, // PLAYER_IA_MASK_KEATON + Player_InitDefaultIA, // PLAYER_IA_MASK_SKULL + Player_InitDefaultIA, // PLAYER_IA_MASK_SPOOKY + Player_InitDefaultIA, // PLAYER_IA_MASK_BUNNY_HOOD + Player_InitDefaultIA, // PLAYER_IA_MASK_GORON + Player_InitDefaultIA, // PLAYER_IA_MASK_ZORA + Player_InitDefaultIA, // PLAYER_IA_MASK_GERUDO + Player_InitDefaultIA, // PLAYER_IA_MASK_TRUTH + Player_InitDefaultIA, // PLAYER_IA_LENS_OF_TRUTH }; typedef enum { @@ -1555,15 +1567,15 @@ void func_80832564(PlayState* play, Player* this) { } s32 func_80832594(Player* this, s32 arg1, s32 arg2) { - s16 controlStickAngleDiff = this->unk_A80 - sControlStickAngle; + s16 controlStickAngleDiff = this->prevControlStickAngle - sControlStickAngle; - this->unk_850 += arg1 + (s16)(ABS(controlStickAngleDiff) * fabsf(sControlStickMagnitude) * 2.5415802156203426e-06f); + this->av2.actionVar2 += arg1 + (s16)(ABS(controlStickAngleDiff) * fabsf(sControlStickMagnitude) * 2.5415802156203426e-06f); if (CHECK_BTN_ANY(sControlInput->press.button, BTN_A | BTN_B)) { - this->unk_850 += 5; + this->av2.actionVar2 += 5; } - return this->unk_850 > arg2; + return this->av2.actionVar2 > arg2; } void func_80832630(PlayState* play) { @@ -1676,31 +1688,33 @@ void Player_ProcessAnimSfxList(Player* this, AnimSfxEntry* entry) { s32 pad; do { - s32 absData = ABS(entry->field); - s32 type = absData & 0x7800; - if (LinkAnimation_OnFrame(&this->skelAnime, fabsf(absData & 0x7FF))) { - if (type == 0x800) { + s32 absData = ABS(entry->data); + s32 type = ANIMSFX_GET_TYPE(absData); + + if (LinkAnimation_OnFrame(&this->skelAnime, fabsf(ANIMSFX_GET_FRAME(absData)))) { + if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_1)) { Player_PlaySfx(this, entry->sfxId); - } else if (type == 0x1000) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_2)) { func_80832770(this, entry->sfxId); - } else if (type == 0x1800) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_3)) { func_808327C4(this, entry->sfxId); - } else if (type == 0x2000) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_4)) { func_80832698(this, entry->sfxId); - } else if (type == 0x2800) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_5)) { func_808328A0(this); - } else if (type == 0x3000) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_6)) { func_808327F8(this, 6.0f); - } else if (type == 0x3800) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_7)) { func_80832854(this); - } else if (type == 0x4000) { + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_8)) { func_808327F8(this, 0.0f); - } else if (type == 0x4800) { - func_800F4010(&this->actor.projectedPos, this->ageProperties->unk_94 + NA_SE_PL_WALK_LADDER, 0.0f); + } else if (type == ANIMSFX_SHIFT_TYPE(ANIMSFX_TYPE_9)) { + func_800F4010(&this->actor.projectedPos, + NA_SE_PL_WALK_LADDER + this->ageProperties->unk_94, 0.0f); } } - cont = (entry->field >= 0); // stop processing if `data` is negative + cont = (entry->data >= 0); // stop processing if `data` is negative entry++; } while (cont); } @@ -1812,7 +1826,8 @@ void Player_AnimReplaceApplyFlags(PlayState* play, Player* this, s32 flags) { AnimationContext_DisableQueue(play); } -void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, f32 playbackSpeed) { +void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, + f32 playbackSpeed) { LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, playbackSpeed); Player_AnimReplaceApplyFlags(play, this, flags); } @@ -1829,7 +1844,8 @@ void Player_AnimReplaceNormalPlayOnceAdjusted(PlayState* play, Player* this, Lin Player_AnimReplacePlayOnceAdjusted(play, this, anim, 0x1C); } -void Player_AnimReplacePlayLoopSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, f32 playbackSpeed) { +void Player_AnimReplacePlayLoopSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, + f32 playbackSpeed) { LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, anim, playbackSpeed); Player_AnimReplaceApplyFlags(play, this, flags); } @@ -1850,8 +1866,8 @@ void Player_ProcessControlStick(PlayState* play, Player* this) { s8 phi_v1; s8 phi_v0; - this->unk_A7C = sControlStickMagnitude; - this->unk_A80 = sControlStickAngle; + this->prevControlStickMagnitude = sControlStickMagnitude; + this->prevControlStickAngle = sControlStickAngle; func_80077D10(&sControlStickMagnitude, &sControlStickAngle, sControlInput); @@ -1875,7 +1891,7 @@ void func_8083328C(PlayState* play, Player* this, LinkAnimationHeader* linkAnim) LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, linkAnim, D_808535E8); } -s32 func_808332B8(Player* this) { +int func_808332B8(Player* this) { return (this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (this->currentBoots != PLAYER_BOOTS_IRON); } @@ -1931,7 +1947,7 @@ LinkAnimationHeader* func_80833438(Player* this) { } } -s32 func_808334B4(Player* this) { +int func_808334B4(Player* this) { return func_808332E4(this) && (this->unk_834 != 0); } @@ -1975,8 +1991,8 @@ LinkAnimationHeader* func_808335F4(Player* this) { } } -void Player_SetUpperActionFunc(Player* this, UpperActionFunc arg1) { - this->upperActionFunc = arg1; +void Player_SetUpperActionFunc(Player* this, UpperActionFunc upperActionFunc) { + this->upperActionFunc = upperActionFunc; this->unk_836 = 0; this->upperAnimBlendWeight = 0.0f; func_808326F0(this); @@ -2019,17 +2035,17 @@ s8 Player_ItemToItemAction(s32 item) { } } -void func_80833770(PlayState* play, Player* this) { +void Player_InitDefaultIA(PlayState* play, Player* this) { } -void func_8083377C(PlayState* play, Player* this) { +void Player_InitDekuStickIA(PlayState* play, Player* this) { this->unk_85C = 1.0f; } -void func_80833790(PlayState* play, Player* this) { +void Player_InitHammerIA(PlayState* play, Player* this) { } -void func_8083379C(PlayState* play, Player* this) { +void Player_InitBowOrSlingshotIA(PlayState* play, Player* this) { this->stateFlags1 |= PLAYER_STATE1_ITEM_IN_HAND; if (this->heldItemAction != PLAYER_IA_SLINGSHOT) { @@ -2039,7 +2055,7 @@ void func_8083379C(PlayState* play, Player* this) { } } -void func_808337D4(PlayState* play, Player* this) { +void Player_InitExplosiveIA(PlayState* play, Player* this) { s32 explosiveType; ExplosiveInfo* explosiveInfo; Actor* spawnedActor; @@ -2052,9 +2068,9 @@ void func_808337D4(PlayState* play, Player* this) { explosiveType = Player_GetExplosiveHeld(this); explosiveInfo = &sExplosiveInfos[explosiveType]; - spawnedActor = Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, explosiveInfo->actorId, - this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, - this->actor.shape.rot.y, 0, 0); + spawnedActor = + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, explosiveInfo->actorId, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0); if (spawnedActor != NULL) { if ((explosiveType != 0) && (play->bombchuBowlingStatus != 0)) { if (!CVarGetInteger("gInfiniteAmmo", 0)) { @@ -2076,7 +2092,7 @@ void func_808337D4(PlayState* play, Player* this) { } } -void func_80833910(PlayState* play, Player* this) { +void Player_InitHookshotIA(PlayState* play, Player* this) { this->stateFlags1 |= PLAYER_STATE1_ITEM_IN_HAND; this->unk_860 = -3; @@ -2085,7 +2101,7 @@ void func_80833910(PlayState* play, Player* this) { this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0); } -void func_80833984(PlayState* play, Player* this) { +void Player_InitBoomerangIA(PlayState* play, Player* this) { this->stateFlags1 |= PLAYER_STATE1_BOOMERANG_IN_HAND; } @@ -2109,7 +2125,8 @@ void func_80833A20(Player* this, s32 newMeleeWeaponState) { u16 voiceSfx; if (this->meleeWeaponState == 0) { - if ((this->heldItemAction == PLAYER_IA_SWORD_BIGGORON) && (gSaveContext.swordHealth > 0.0f)) { + if ((this->heldItemAction == PLAYER_IA_SWORD_BIGGORON) && + (gSaveContext.swordHealth > 0.0f)) { itemSfx = NA_SE_IT_HAMMER_SWING; } else { itemSfx = NA_SE_IT_SWORD_SWING; @@ -2160,18 +2177,18 @@ s32 func_80833B54(Player* this) { if (this->stateFlags1 & PLAYER_STATE1_ENEMY_TARGET) { this->stateFlags1 &= ~PLAYER_STATE1_ENEMY_TARGET; if (this->linearVelocity == 0.0f) { - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } } return 0; } -s32 func_80833BCC(Player* this) { +int func_80833BCC(Player* this) { return func_8008E9C4(this) || func_80833B2C(this); } -s32 func_80833C04(Player* this) { +int func_80833C04(Player* this) { return func_80833B54(this) || func_80833B2C(this); } @@ -2251,13 +2268,15 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { } } else { maskItemAction = this->currentMask - 1 + PLAYER_IA_MASK_KEATON; + bool hasOnDpad = false; if (CVarGetInteger("gDpadEquips", 0) != 0) { for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) { hasOnDpad |= Player_ItemIsItemAction(DPAD_ITEM(buttonIndex), maskItemAction); } } - if (!Player_ItemIsItemAction(C_BTN_ITEM(0), maskItemAction) && !Player_ItemIsItemAction(C_BTN_ITEM(1), maskItemAction) && + if (!Player_ItemIsItemAction(C_BTN_ITEM(0), maskItemAction) && + !Player_ItemIsItemAction(C_BTN_ITEM(1), maskItemAction) && !Player_ItemIsItemAction(C_BTN_ITEM(2), maskItemAction) && !hasOnDpad) { this->currentMask = PLAYER_MASK_NONE; } @@ -2544,7 +2563,11 @@ s32 func_8083499C(Player* this, PlayState* play) { return 1; } -s32 func_808349DC(Player* this, PlayState* play) { +/** + * The actual sword weapon is not handled here. See `Player_ActionChange_7` for melee weapon usage. + * This upper body action allows for shielding or changing held items while a sword is in hand. + */ +s32 Player_UpperAction_Sword(Player* this, PlayState* play) { if (func_80834758(play, this) || func_8083499C(this, play)) { return 1; } else { @@ -2555,8 +2578,8 @@ s32 func_808349DC(Player* this, PlayState* play) { s32 Player_UpperAction_ChangeHeldItem(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->upperSkelAnime) || ((Player_ItemToItemAction(this->heldItemId) == this->heldItemAction) && - (sUseHeldItem = (sUseHeldItem || - ((this->modelAnimType != PLAYER_ANIMTYPE_3) && (play->shootingGalleryStatus == 0)))))) { + (sUseHeldItem = + (sUseHeldItem || ((this->modelAnimType != PLAYER_ANIMTYPE_3) && (play->shootingGalleryStatus == 0)))))) { Player_SetUpperActionFunc(this, sItemActionUpdateFuncs[this->heldItemAction]); this->unk_834 = 0; this->unk_6AC = 0; @@ -2609,7 +2632,8 @@ s32 func_80834C74(Player* this, PlayState* play) { if (sUseHeldItem || LinkAnimation_Update(play, &this->upperSkelAnime)) { Player_SetUpperActionFunc(this, sItemActionUpdateFuncs[this->heldItemAction]); - LinkAnimation_PlayLoop(play, &this->upperSkelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType)); + LinkAnimation_PlayLoop(play, &this->upperSkelAnime, + GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType)); this->unk_6AC = 0; this->upperActionFunc(this, play); return 0; @@ -2647,22 +2671,24 @@ s32 func_80834D2C(Player* this, PlayState* play) { return 1; } -s32 func_80834E44(PlayState* play) { +int func_80834E44(PlayState* play) { return (play->shootingGalleryStatus > 0) && CHECK_BTN_ALL(sControlInput->press.button, BTN_B); } -s32 func_80834E7C(PlayState* play) { +int func_80834E7C(PlayState* play) { u16 buttonsToCheck = BTN_A | BTN_B | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; if (CVarGetInteger("gDpadEquips", 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } return (play->shootingGalleryStatus != 0) && - ((play->shootingGalleryStatus < 0) || CHECK_BTN_ANY(sControlInput->cur.button, buttonsToCheck)); + ((play->shootingGalleryStatus < 0) || + CHECK_BTN_ANY(sControlInput->cur.button, buttonsToCheck)); } s32 func_80834EB8(Player* this, PlayState* play) { if ((this->unk_6AD == 0) || (this->unk_6AD == 2)) { - if (func_80833BCC(this) || (Camera_CheckValidMode(Play_GetCamera(play, 0), 7) == 0)) { + if (func_80833BCC(this) || + (Camera_CheckValidMode(Play_GetCamera(play, 0), 7) == 0)) { return 1; } this->unk_6AD = 2; @@ -2859,10 +2885,10 @@ void func_808355DC(Player* this) { this->stateFlags1 |= PLAYER_STATE1_TARGET_NOTHING; if (!(this->skelAnime.moveFlags & 0x80) && (this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x2000)) { - this->currentYaw = this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; + this->yaw = this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; } - this->targetYaw = this->actor.shape.rot.y; + this->zTargetYaw = this->actor.shape.rot.y; } s32 func_80835644(PlayState* play, Player* this, Actor* arg2) { @@ -2877,12 +2903,12 @@ s32 func_80835644(PlayState* play, Player* this, Actor* arg2) { void func_80835688(Player* this, PlayState* play) { if (!func_80835644(play, this, this->heldActor)) { - Player_SetUpperActionFunc(this, func_808356E8); + Player_SetUpperActionFunc(this, Player_UpperAction_CarryActor); LinkAnimation_PlayLoop(play, &this->upperSkelAnime, &gPlayerAnim_link_normal_carryB_wait); } } -s32 func_808356E8(Player* this, PlayState* play) { +s32 Player_UpperAction_CarryActor(Player* this, PlayState* play) { Actor* heldActor = this->heldActor; if (heldActor == NULL) { @@ -2974,8 +3000,8 @@ s32 func_808359FC(Player* this, PlayState* play) { f32 posZ = (Math_CosS(this->actor.shape.rot.y) * 10.0f) + this->actor.world.pos.z; s32 yaw = (this->unk_664 != NULL) ? this->actor.shape.rot.y + 14000 : this->actor.shape.rot.y; EnBoom* boomerang = - (EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 30.0f, - posZ, this->actor.focus.rot.x, yaw, 0, 0, true); + (EnBoom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOOM, posX, this->actor.world.pos.y + 30.0f, posZ, + this->actor.focus.rot.x, yaw, 0, 0, true); this->boomerangActor = &boomerang->actor; if (boomerang != NULL) { @@ -3024,7 +3050,7 @@ s32 func_80835B60(Player* this, PlayState* play) { Player_SetUpperActionFunc(this, func_80835C08); LinkAnimation_PlayOnce(play, &this->upperSkelAnime, &gPlayerAnim_link_boom_catch); func_808357E8(this, gPlayerLeftHandBoomerangDLs); - Player_PlaySfx(&this->actor, NA_SE_PL_CATCH_BOOMERANG); + Player_PlaySfx(this, NA_SE_PL_CATCH_BOOMERANG); func_80832698(this, NA_SE_VO_LI_SWORD_N); return 1; } @@ -3049,21 +3075,20 @@ s32 Player_SetupAction(PlayState* play, Player* this, PlayerActionFunc actionFun return 0; } - if (func_8084E3C4 == this->actionFunc) { + if (Player_Action_8084E3C4 == this->actionFunc) { Audio_OcaSetInstrument(0); this->stateFlags2 &= ~(PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR | PLAYER_STATE2_PLAY_FOR_ACTOR); - } else if (func_808507F4 == this->actionFunc) { + } else if (Player_Action_808507F4 == this->actionFunc) { func_80832340(play, this); } this->actionFunc = actionFunc; - if ((this->itemAction != this->heldItemAction) && - (!(flags & 1) || !(this->stateFlags1 & PLAYER_STATE1_SHIELDING))) { + if ((this->itemAction != this->heldItemAction) && (!(flags & 1) || !(this->stateFlags1 & PLAYER_STATE1_SHIELDING))) { func_8008EC70(this); } - if (!(flags & 1) && (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD))) { + if (!(flags & 1) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { func_80834644(play, this); this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING; } @@ -3075,8 +3100,8 @@ s32 Player_SetupAction(PlayState* play, Player* this, PlayerActionFunc actionFun this->stateFlags2 &= ~(PLAYER_STATE2_HOPPING | PLAYER_STATE2_OCARINA_PLAYING | PLAYER_STATE2_IDLING); this->stateFlags3 &= ~(PLAYER_STATE3_MIDAIR | PLAYER_STATE3_FINISHED_ATTACKING | PLAYER_STATE3_HOOKSHOT_TRAVELLING); - this->unk_84F = 0; - this->unk_850 = 0; + this->av1.actionVar1 = 0; + this->av2.actionVar2 = 0; this->unk_6AC = 0; @@ -3118,7 +3143,7 @@ void func_80835E44(PlayState* play, s16 camSetting) { void func_80835EA4(PlayState* play, s32 arg1) { func_80835E44(play, CAM_SET_TURN_AROUND); - Camera_SetCameraData(Play_GetCamera(play, 0), 4, 0, 0, arg1, 0, 0); + Camera_SetCameraData(Play_GetCamera(play, 0), 4, NULL, NULL, arg1, 0, 0); } void Player_DestroyHookshot(Player* this) { @@ -3143,8 +3168,7 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { if (((this->heldItemAction == this->itemAction) && (!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) || (Player_ActionToMeleeWeapon(itemAction) != 0) || (itemAction == PLAYER_IA_NONE))) || - ((this->itemAction < 0) && - ((Player_ActionToMeleeWeapon(itemAction) != 0) || (itemAction == PLAYER_IA_NONE)))) { + ((this->itemAction < 0) && ((Player_ActionToMeleeWeapon(itemAction) != 0) || (itemAction == PLAYER_IA_NONE)))) { if ((itemAction == PLAYER_IA_NONE) || !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || ((this->actor.bgCheckFlags & 1) && @@ -3156,11 +3180,11 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { (temp = Player_ActionToExplosive(this, itemAction), ((temp >= 0) && ((AMMO(sExplosiveInfos[temp].itemId) == 0) || (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3 && !CVarGetInteger("gRemoveExplosiveLimit", 0))))))) { + // Prevent some items from being used if player is out of ammo. + // Also prevent explosives from being used if there are 3 or more active (outside of bombchu bowling) func_80078884(NA_SE_SY_ERROR); - return; - } - - if (itemAction == PLAYER_IA_LENS_OF_TRUTH) { + } else if (itemAction == PLAYER_IA_LENS_OF_TRUTH) { + // Handle Lens of Truth if (Magic_RequestChange(play, 0, MAGIC_CONSUME_LENS)) { if (play->actorCtx.lensActive) { Actor_DisableLens(play); @@ -3171,20 +3195,15 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { } else { func_80078884(NA_SE_SY_ERROR); } - return; - } - - if (itemAction == PLAYER_IA_DEKU_NUT) { + } else if (itemAction == PLAYER_IA_DEKU_NUT) { + // Handle Deku Nuts if (AMMO(ITEM_NUT) != 0) { func_8083C61C(play, this); } else { func_80078884(NA_SE_SY_ERROR); } - return; - } - - temp = Player_ActionToMagicSpell(this, itemAction); - if (temp >= 0) { + } else if ((temp = Player_ActionToMagicSpell(this, itemAction)) >= 0) { + // Handle magic spells if (((itemAction == PLAYER_IA_FARORES_WIND) && (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 0)) || ((gSaveContext.magicCapacity != 0) && (gSaveContext.magicState == MAGIC_STATE_IDLE) && (gSaveContext.magic >= sMagicSpellCosts[temp]))) { @@ -3193,35 +3212,31 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { } else { func_80078884(NA_SE_SY_ERROR); } - return; - } - - if (itemAction >= PLAYER_IA_MASK_KEATON) { + } else if (itemAction >= PLAYER_IA_MASK_KEATON) { + // Handle wearable masks if (this->currentMask != PLAYER_MASK_NONE) { this->currentMask = PLAYER_MASK_NONE; } else { this->currentMask = itemAction - PLAYER_IA_MASK_KEATON + 1; } + sMaskMemory = this->currentMask; func_808328EC(this, NA_SE_PL_CHANGE_ARMS); - return; - } - - if (((itemAction >= PLAYER_IA_OCARINA_FAIRY) && (itemAction <= PLAYER_IA_OCARINA_OF_TIME)) || + } else if (((itemAction >= PLAYER_IA_OCARINA_FAIRY) && (itemAction <= PLAYER_IA_OCARINA_OF_TIME)) || (itemAction >= PLAYER_IA_BOTTLE_FISH)) { + // Handle "cutscene items" if (!func_8008E9C4(this) || ((itemAction >= PLAYER_IA_BOTTLE_POTION_RED) && (itemAction <= PLAYER_IA_BOTTLE_FAIRY))) { func_8002D53C(play, &play->actorCtx.titleCtx); this->unk_6AD = 4; this->itemAction = itemAction; } - return; - } - - if ((itemAction != this->heldItemAction) || - ((this->heldActor == 0) && (Player_ActionToExplosive(this, itemAction) >= 0))) { + } else if ((itemAction != this->heldItemAction) || + ((this->heldActor == NULL) && (Player_ActionToExplosive(this, itemAction) >= 0))) { + // Handle using a new held item this->nextModelGroup = Player_ActionToModelGroup(this, itemAction); nextAnimType = gPlayerModelTypes[this->nextModelGroup][PLAYER_MODELGROUPENTRY_ANIM]; + if ((this->heldItemAction >= 0) && (Player_ActionToMagicSpell(this, itemAction) < 0) && (item != this->heldItemId) && (sItemChangeTypes[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType] != @@ -3229,6 +3244,7 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { (!CVarGetInteger("gSeparateArrows", 0) || itemAction < PLAYER_IA_BOW || itemAction > PLAYER_IA_BOW_0E || this->heldItemAction < PLAYER_IA_BOW || this->heldItemAction > PLAYER_IA_BOW_0E)) { + // Start the held item change process this->heldItemId = item; this->stateFlags1 |= PLAYER_STATE1_START_PUTAWAY; } else { @@ -3237,10 +3253,10 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { Player_DetachHeldActor(play, this); Player_InitItemActionWithAnim(play, this, itemAction); } - return; + } else { + // Handle using the held item already in hand + sUseHeldItem = sHeldItemButtonIsHeldDown = true; } - - sUseHeldItem = sHeldItemButtonIsHeldDown = true; } } } @@ -3250,7 +3266,7 @@ void func_80836448(PlayState* play, Player* this, LinkAnimationHeader* anim) { func_80832564(play, this); - Player_SetupAction(play, this, cond ? func_8084E368 : func_80843CEC, 0); + Player_SetupAction(play, this, cond ? Player_Action_8084E368 : Player_Action_80843CEC, 0); this->stateFlags1 |= PLAYER_STATE1_DEAD; @@ -3267,7 +3283,7 @@ void func_80836448(PlayState* play, Player* this, LinkAnimationHeader* anim) { if (Inventory_ConsumeFairy(play)) { play->gameOverCtx.state = GAMEOVER_REVIVE_START; - this->unk_84F = 1; + this->av1.actionVar1 = 1; } else { play->gameOverCtx.state = GAMEOVER_DEATH_START; func_800F6AB0(0); @@ -3282,7 +3298,7 @@ void func_80836448(PlayState* play, Player* this, LinkAnimationHeader* anim) { } s32 Player_CanUpdateItems(Player* this) { - return (!(func_808458D0 == this->actionFunc) || + return (!(Player_Action_808458D0 == this->actionFunc) || ((this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) && ((this->heldItemId == ITEM_LAST_USED) || (this->heldItemId == ITEM_NONE)))) && (!(Player_UpperAction_ChangeHeldItem == this->upperActionFunc) || @@ -3291,12 +3307,12 @@ s32 Player_CanUpdateItems(Player* this) { s32 Player_UpdateUpperBody(Player* this, PlayState* play) { if (!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->actor.parent != NULL) && Player_HoldsHookshot(this)) { - Player_SetupAction(play, this, func_80850AEC, 1); + Player_SetupAction(play, this, Player_Action_80850AEC, 1); this->stateFlags3 |= PLAYER_STATE3_HOOKSHOT_TRAVELLING; Player_AnimPlayOnce(play, this, &gPlayerAnim_link_hook_fly_start); Player_AnimReplaceApplyFlags(play, this, 0x9B); func_80832224(this); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; this->actor.bgCheckFlags &= ~1; this->hoverBootsTimer = 0; this->unk_6AE |= 0x43; @@ -3306,7 +3322,7 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) { if (Player_CanUpdateItems(this)) { Player_UpdateItems(this, play); - if (func_8084E604 == this->actionFunc) { + if (Player_Action_8084E604 == this->actionFunc) { return 1; } } @@ -3336,7 +3352,7 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) { s32 func_80836898(PlayState* play, Player* this, PlayerFuncA74 func) { this->func_A74 = func; - Player_SetupAction(play, this, func_808458D0, 0); + Player_SetupAction(play, this, Player_Action_808458D0, 0); this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; return func_80832528(play, this); } @@ -3351,10 +3367,10 @@ void func_808368EC(Player* this, PlayState* play) { Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_664->focus.pos), 4000); } else if ((this->stateFlags1 & PLAYER_STATE1_TARGET_NOTHING) && !(this->stateFlags2 & (PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS))) { - Math_ScaledStepToS(&this->actor.shape.rot.y, this->targetYaw, 4000); + Math_ScaledStepToS(&this->actor.shape.rot.y, this->zTargetYaw, 4000); } } else if (!(this->stateFlags2 & PLAYER_STATE2_DISABLE_ROTATION_ALWAYS)) { - Math_ScaledStepToS(&this->actor.shape.rot.y, this->currentYaw, 2000); + Math_ScaledStepToS(&this->actor.shape.rot.y, this->yaw, 2000); } this->unk_87C = this->actor.shape.rot.y - previousYaw; @@ -3508,26 +3524,52 @@ void func_80836BEC(Player* this, PlayState* play) { } } +/** + * These defines exist to simplify the variable used to toggle the different speed modes. + * While the `speedMode` variable is a float and can contain a non-boolean value, + * `Player_CalcSpeedAndYawFromControlStick` never actually uses the value for anything. + * It simply checks if the value is non-zero to toggle the "curved" mode. + * In practice, 0.0f or 0.018f are the only values passed to this function. + * + * It's clear that this value was intended to mean something in the curved mode calculation at + * some point in development, but was either never implemented or removed. + * + * To see the difference between linear and curved mode, with interactive toggles for + * speed cap and floor pitch, see the following desmos graph: https://www.desmos.com/calculator/hri7dcws4c + */ + +// Linear mode is a straight line, increasing target speed at a steady rate relative to the control stick magnitude +#define SPEED_MODE_LINEAR 0.0f + +// Curved mode drops any input below 20 units of magnitude, resulting in zero for target speed. +// Beyond 20 units, a gradual curve slowly moves up until around the 40 unit mark +// when target speed ramps up very quickly. +#define SPEED_MODE_CURVED 0.018f + /** * Calculates target speed and yaw based on input from the control stick. * See `Player_GetMovementSpeedAndYaw` for detailed argument descriptions. * * @return true if the control stick has any magnitude, false otherwise. */ -s32 Player_CalcSpeedAndYawFromControlStick(PlayState* play, Player* this, f32* outSpeedTarget, s16* outYawTarget, f32 speedMode) { +s32 Player_CalcSpeedAndYawFromControlStick(PlayState* play, Player* this, f32* outSpeedTarget, s16* outYawTarget, + f32 speedMode) { f32 temp; f32 sinFloorPitch; f32 floorPitchInfluence; f32 speedCap; - if ((this->unk_6AD != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || (this->stateFlags1 & PLAYER_STATE1_LOADING)) { + if ((this->unk_6AD != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) || + (this->stateFlags1 & PLAYER_STATE1_LOADING)) { *outSpeedTarget = 0.0f; *outYawTarget = this->actor.shape.rot.y; } else { *outSpeedTarget = sControlStickMagnitude; *outYawTarget = sControlStickAngle; - if (speedMode != 0.0f) { + // The value of `speedMode` is never actually used. It only toggles this condition. + // See the definition of `SPEED_MODE_LINEAR` and `SPEED_MODE_CURVED` for more information. + if (speedMode != SPEED_MODE_LINEAR) { *outSpeedTarget -= 20.0f; if (*outSpeedTarget < 0.0f) { // If control stick magnitude is below 20, return zero speed. @@ -3537,7 +3579,7 @@ s32 Player_CalcSpeedAndYawFromControlStick(PlayState* play, Player* this, f32* o // it happens to give a desirable curve for grounded movement speed relative // to control stick magnitude. temp = 1.0f - Math_CosS(*outSpeedTarget * 450.0f); - *outSpeedTarget = ((temp * temp) * 30.0f) + 7.0f; + *outSpeedTarget = (SQ(temp) * 30.0f) + 7.0f; } } else { // Speed increases linearly relative to control stick magnitude @@ -3550,10 +3592,8 @@ s32 Player_CalcSpeedAndYawFromControlStick(PlayState* play, Player* this, f32* o floorPitchInfluence = CLAMP(sinFloorPitch, 0.0f, 0.6f); if (this->unk_6C4 != 0.0f) { - speedCap = speedCap - (this->unk_6C4 * 0.008f); - if (speedCap < 2.0f) { - speedCap = 2.0f; - } + speedCap -= (this->unk_6C4 * 0.008f); + speedCap = CLAMP_MIN(speedCap, 2.0f); } *outSpeedTarget = (*outSpeedTarget * 0.14f) - (8.0f * floorPitchInfluence * floorPitchInfluence); @@ -3583,7 +3623,8 @@ s32 func_8083721C(Player* this) { * * @return true if the control stick has any magnitude, false otherwise. */ -s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYawTarget, f32 speedMode, PlayState* play) { +s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYawTarget, f32 speedMode, + PlayState* play) { if (!Player_CalcSpeedAndYawFromControlStick(play, this, outSpeedTarget, outYawTarget, speedMode)) { *outYawTarget = this->actor.shape.rot.y; @@ -3593,7 +3634,7 @@ s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYaw return false; } } else if (func_80833B2C(this)) { - *outYawTarget = this->targetYaw; + *outYawTarget = this->zTargetYaw; } return false; @@ -3603,21 +3644,115 @@ s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYaw } } -static s8 D_808543E0[] = { 13, 2, 4, 9, 10, 11, 8, -7 }; -static s8 D_808543E8[] = { 13, 1, 2, 5, 3, 4, 9, 10, 11, 7, 8, -6 }; -static s8 D_808543F4[] = { 13, 1, 2, 3, 4, 9, 10, 11, 8, 7, -6 }; -static s8 D_80854400[] = { 13, 2, 4, 9, 10, 11, 8, -7 }; -static s8 D_80854408[] = { 13, 2, 4, 9, 10, 11, 12, 8, -7 }; -static s8 D_80854414[] = { -7 }; -static s8 D_80854418[] = { 0, 11, 1, 2, 3, 5, 4, 9, 8, 7, -6 }; -static s8 D_80854424[] = { 0, 11, 1, 2, 3, 12, 5, 4, 9, 8, 7, -6 }; -static s8 D_80854430[] = { 13, 1, 2, 3, 12, 5, 4, 9, 10, 11, 8, 7, -6 }; -static s8 D_80854440[] = { 10, 8, -7 }; -static s8 D_80854444[] = { 0, 12, 5, -4 }; +typedef enum { + /* 0 */ PLAYER_ACTION_CHG_0, + /* 1 */ PLAYER_ACTION_CHG_1, + /* 2 */ PLAYER_ACTION_CHG_2, + /* 3 */ PLAYER_ACTION_CHG_3, + /* 4 */ PLAYER_ACTION_CHG_4, + /* 5 */ PLAYER_ACTION_CHG_5, + /* 6 */ PLAYER_ACTION_CHG_6, + /* 7 */ PLAYER_ACTION_CHG_7, + /* 8 */ PLAYER_ACTION_CHG_8, + /* 9 */ PLAYER_ACTION_CHG_9, + /* 10 */ PLAYER_ACTION_CHG_10, + /* 11 */ PLAYER_ACTION_CHG_11, + /* 12 */ PLAYER_ACTION_CHG_12, + /* 13 */ PLAYER_ACTION_CHG_13 +} ActionChangeIndex; -static s32 (*D_80854448[])(Player* this, PlayState* play) = { - func_8083B998, func_80839800, func_8083E5A8, func_8083E0FC, func_8083B644, func_8083F7BC, func_8083C1DC, - func_80850224, func_8083C544, func_8083EB44, func_8083BDBC, func_8083C2B0, func_80838A14, func_8083B040, +static s8 sActionChangeList1[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, + PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7, +}; + +static s8 sActionChangeList2[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_5, + PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, + PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_7, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_6, +}; + +static s8 sActionChangeList3[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_3, + PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, + PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6, +}; + +static s8 sActionChangeList4[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, + PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7, +}; + +static s8 sActionChangeList5[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, + PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_12, PLAYER_ACTION_CHG_8, -PLAYER_ACTION_CHG_7, +}; + +static s8 sActionChangeList6[] = { + -PLAYER_ACTION_CHG_7, +}; + +static s8 sActionChangeList7[] = { + PLAYER_ACTION_CHG_0, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, + PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, + PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6, +}; + +static s8 sActionChangeList8[] = { + PLAYER_ACTION_CHG_0, PLAYER_ACTION_CHG_11, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, + PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_12, PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4, + PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6, +}; + +static s8 sActionChangeList9[] = { + PLAYER_ACTION_CHG_13, PLAYER_ACTION_CHG_1, PLAYER_ACTION_CHG_2, PLAYER_ACTION_CHG_3, PLAYER_ACTION_CHG_12, + PLAYER_ACTION_CHG_5, PLAYER_ACTION_CHG_4, PLAYER_ACTION_CHG_9, PLAYER_ACTION_CHG_10, PLAYER_ACTION_CHG_11, + PLAYER_ACTION_CHG_8, PLAYER_ACTION_CHG_7, -PLAYER_ACTION_CHG_6, +}; + +static s8 sActionChangeList10[] = { + PLAYER_ACTION_CHG_10, + PLAYER_ACTION_CHG_8, + -PLAYER_ACTION_CHG_7, +}; + +static s8 sActionChangeList11[] = { + PLAYER_ACTION_CHG_0, + PLAYER_ACTION_CHG_12, + PLAYER_ACTION_CHG_5, + -PLAYER_ACTION_CHG_4, +}; + +s32 Player_ActionChange_0(Player* this, PlayState* play); +s32 Player_ActionChange_1(Player* this, PlayState* play); +s32 Player_ActionChange_2(Player* this, PlayState* play); +s32 Player_ActionChange_3(Player* this, PlayState* play); +s32 Player_ActionChange_4(Player* this, PlayState* play); +s32 Player_ActionChange_5(Player* this, PlayState* play); +s32 Player_ActionChange_6(Player* this, PlayState* play); +s32 Player_ActionChange_7(Player* this, PlayState* play); +s32 Player_ActionChange_8(Player* this, PlayState* play); +s32 Player_ActionChange_9(Player* this, PlayState* play); +s32 Player_ActionChange_10(Player* this, PlayState* play); +s32 Player_ActionChange_11(Player* this, PlayState* play); +s32 Player_ActionChange_12(Player* this, PlayState* play); +s32 Player_ActionChange_13(Player* this, PlayState* play); + +static s32 (*sActionChangeFuncs[])(Player* this, PlayState* play) = { + /* PLAYER_ACTION_CHG_0 */ Player_ActionChange_0, + /* PLAYER_ACTION_CHG_1 */ Player_ActionChange_1, + /* PLAYER_ACTION_CHG_2 */ Player_ActionChange_2, + /* PLAYER_ACTION_CHG_3 */ Player_ActionChange_3, + /* PLAYER_ACTION_CHG_4 */ Player_ActionChange_4, + /* PLAYER_ACTION_CHG_5 */ Player_ActionChange_5, + /* PLAYER_ACTION_CHG_6 */ Player_ActionChange_6, + /* PLAYER_ACTION_CHG_7 */ Player_ActionChange_7, + /* PLAYER_ACTION_CHG_8 */ Player_ActionChange_8, + /* PLAYER_ACTION_CHG_9 */ Player_ActionChange_9, + /* PLAYER_ACTION_CHG_10 */ Player_ActionChange_10, + /* PLAYER_ACTION_CHG_11 */ Player_ActionChange_11, + /* PLAYER_ACTION_CHG_12 */ Player_ActionChange_12, + /* PLAYER_ACTION_CHG_13 */ Player_ActionChange_13, }; /** @@ -3640,9 +3775,10 @@ s32 Player_TryActionChangeList(PlayState* play, Player* this, s8* actionChangeLi s32 i; if (!(this->stateFlags1 & (PLAYER_STATE1_LOADING | PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE))) { - if (updateUpperBody != 0) { + if (updateUpperBody) { D_808535E0 = Player_UpdateUpperBody(this, play); - if (func_8084E604 == this->actionFunc) { + + if (Player_Action_8084E604 == this->actionFunc) { return true; } } @@ -3652,15 +3788,18 @@ s32 Player_TryActionChangeList(PlayState* play, Player* this, s8* actionChangeLi return true; } - if (!(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) && (Player_UpperAction_ChangeHeldItem != this->upperActionFunc)) { + if (!(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY) && + (Player_UpperAction_ChangeHeldItem != this->upperActionFunc)) { + // Process all entries in the Action Change List with a positive index while (*actionChangeList >= 0) { - if (D_80854448[*actionChangeList](this, play)) { + if (sActionChangeFuncs[*actionChangeList](this, play)) { return true; } actionChangeList++; } - if (D_80854448[-(*actionChangeList)](this, play)) { + // Try the last entry in the list. Negate the index to make it positive again. + if (sActionChangeFuncs[-(*actionChangeList)](this, play)) { return true; } } @@ -3670,15 +3809,15 @@ s32 Player_TryActionChangeList(PlayState* play, Player* this, s8* actionChangeLi } s32 func_808374A0(PlayState* play, Player* this, SkelAnime* skelAnime, f32 arg3) { - f32 sp24; - s16 sp22; + f32 speedTarget; + s16 yawTarget; if ((skelAnime->endFrame - arg3) <= skelAnime->curFrame) { - if (Player_TryActionChangeList(play, this, D_80854418, 1)) { + if (Player_TryActionChangeList(play, this, sActionChangeList7, true)) { return 0; } - if (Player_GetMovementSpeedAndYaw(this, &sp24, &sp22, 0.018f, play)) { + if (Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play)) { return 1; } } @@ -3755,7 +3894,7 @@ void func_80837704(PlayState* play, Player* this) { } void func_808377DC(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_80844E68, 1); + Player_SetupAction(play, this, Player_Action_80844E68, 1); func_80837704(play, this); } @@ -3833,7 +3972,7 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) { u32 dmgFlags; s32 temp; - Player_SetupAction(play, this, func_808502D0, 0); + Player_SetupAction(play, this, Player_Action_808502D0, 0); this->unk_844 = 8; if (!((arg2 >= PLAYER_MWA_FLIPSLASH_FINISH) && (arg2 <= PLAYER_MWA_JUMPSLASH_FINISH))) { func_80832318(this); @@ -3855,7 +3994,7 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) { Player_AnimReplaceApplyFlags(play, this, 0x209); } - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; if (Player_HoldsBrokenKnife(this)) { temp = 1; @@ -3915,9 +4054,9 @@ void func_80837B60(Player* this) { } void func_80837B9C(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084411C, 0); + Player_SetupAction(play, this, Player_Action_8084411C, 0); Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_landing_wait); - this->unk_850 = 1; + this->av2.actionVar2 = 1; if (this->unk_6AD != 3) { this->unk_6AD = 0; } @@ -3952,7 +4091,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, func_80837AE0(this, arg6); if (arg2 == 3) { - Player_SetupAction(play, this, func_8084FB10, 0); + Player_SetupAction(play, this, Player_Action_8084FB10, 0); anim = &gPlayerAnim_link_normal_ice_down; @@ -3962,18 +4101,18 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, Player_PlaySfx(this, NA_SE_PL_FREEZE_S); func_80832698(this, NA_SE_VO_LI_FREEZE); } else if (arg2 == 4) { - Player_SetupAction(play, this, func_8084FBF4, 0); + Player_SetupAction(play, this, Player_Action_8084FBF4, 0); Player_RequestRumble(this, 255, 80, 150, 0); Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_normal_electric_shock); func_80832224(this); - this->unk_850 = 20; + this->av2.actionVar2 = 20; } else { arg5 -= this->actor.shape.rot.y; if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { - Player_SetupAction(play, this, func_8084E30C, 0); + Player_SetupAction(play, this, Player_Action_8084E30C, 0); Player_RequestRumble(this, 180, 20, 50, 0); this->linearVelocity = 4.0f; @@ -3984,7 +4123,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, func_80832698(this, NA_SE_VO_LI_DAMAGE_S); } else if ((arg2 == 1) || (arg2 == 2) || !(this->actor.bgCheckFlags & 1) || (this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) { - Player_SetupAction(play, this, func_8084377C, 0); + Player_SetupAction(play, this, Player_Action_8084377C, 0); this->stateFlags3 |= PLAYER_STATE3_MIDAIR; @@ -3992,7 +4131,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, func_80832224(this); if (arg2 == 2) { - this->unk_850 = 4; + this->av2.actionVar2 = 4; this->actor.speedXZ = 3.0f; this->linearVelocity = 3.0f; @@ -4030,7 +4169,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, sp28 = D_808544B0; - Player_SetupAction(play, this, func_8084370C, 0); + Player_SetupAction(play, this, Player_Action_8084370C, 0); func_80833C3C(this); if (this->actor.colChkInfo.damage < 5) { @@ -4055,7 +4194,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 arg2, f32 arg3, f32 arg4, } this->actor.shape.rot.y += arg5; - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; this->actor.world.rot.y = this->actor.shape.rot.y; if (ABS(arg5) > 0x4000) { this->actor.shape.rot.y += 0x8000; @@ -4087,8 +4226,8 @@ s32 func_8083816C(s32 arg0) { void func_8083819C(Player* this, PlayState* play) { if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger("gFireproofDekuShield", 0) == 0)) { - Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, true); + Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, 1, true); Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); Message_StartTextbox(play, 0x305F, NULL); } @@ -4098,10 +4237,10 @@ void func_8083821C(Player* this) { s32 i; // clang-format off - for (i = 0; i < PLAYER_BODYPART_MAX; i++) { this->flameTimers[i] = Rand_S16Offset(0, 200); } + for (i = 0; i < PLAYER_BODYPART_MAX; i++) { this->bodyFlameTimers[i] = Rand_S16Offset(0, 200); } // clang-format on - this->isBurning = true; + this->bodyIsBurning = true; } void func_80838280(Player* this) { @@ -4168,7 +4307,7 @@ s32 func_808382DC(Player* this, PlayState* play) { func_80838280(this); if (this->unk_8A1 == 3) { - this->shockTimer = 40; + this->bodyShockTimer = 40; } this->actor.colChkInfo.damage += this->unk_8A0; @@ -4188,13 +4327,13 @@ s32 func_808382DC(Player* this, PlayState* play) { if (!Player_IsChildWithHylianShield(this)) { if (this->invincibilityTimer >= 0) { LinkAnimationHeader* anim; - s32 sp54 = func_80843188 == this->actionFunc; + s32 sp54 = Player_Action_80843188 == this->actionFunc; if (!func_808332B8(this)) { - Player_SetupAction(play, this, func_808435C4, 0); + Player_SetupAction(play, this, Player_Action_808435C4, 0); } - if (!(this->unk_84F = sp54)) { + if (!(this->av1.actionVar1 = sp54)) { Player_SetUpperActionFunc(this, func_80834BD4); if (this->unk_870 < 0.5f) { @@ -4217,7 +4356,7 @@ s32 func_808382DC(Player* this, PlayState* play) { if (!(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) { this->linearVelocity = -18.0f; - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } } @@ -4239,7 +4378,7 @@ s32 func_808382DC(Player* this, PlayState* play) { s32 sp4C; if (ac->flags & ACTOR_FLAG_PLAY_HIT_SFX) { - Player_PlaySfx(&this->actor, NA_SE_PL_BODY_HIT); + Player_PlaySfx(this, NA_SE_PL_BODY_HIT); } if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { @@ -4266,10 +4405,10 @@ s32 func_808382DC(Player* this, PlayState* play) { SurfaceType_IsWallDamage(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId)) || ((sp48 >= 0) && SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) && - (this->unk_A79 >= D_808544F4[sp48])) || + (this->floorTypeTimer >= D_808544F4[sp48])) || ((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) || - (this->unk_A79 >= D_808544F4[sp48])))) { - this->unk_A79 = 0; + (this->floorTypeTimer >= D_808544F4[sp48])))) { + this->floorTypeTimer = 0; this->actor.colChkInfo.damage = 4; func_80837C0C(play, this, 0, 4.0f, 5.0f, this->actor.shape.rot.y, 20); } else { @@ -4283,7 +4422,7 @@ s32 func_808382DC(Player* this, PlayState* play) { } void func_80838940(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play, u16 sfxId) { - Player_SetupAction(play, this, func_8084411C, 1); + Player_SetupAction(play, this, Player_Action_8084411C, 1); if (anim != NULL) { Player_AnimPlayOnceAdjusted(play, this, anim); @@ -4303,7 +4442,7 @@ void func_808389E8(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* func_80838940(this, anim, arg2, play, NA_SE_VO_LI_SWORD_N); } -s32 func_80838A14(Player* this, PlayState* play) { +s32 Player_ActionChange_12(Player* this, PlayState* play) { s32 sp3C; LinkAnimationHeader* anim; f32 sp34; @@ -4312,16 +4451,16 @@ s32 func_80838A14(Player* this, PlayState* play) { f32 wallPolyNormalZ; f32 sp24; - if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->unk_88C >= 2) && + if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->ledgeClimbType >= 2) && (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (this->ageProperties->unk_14 > this->yDistToLedge))) { sp3C = 0; if (func_808332B8(this)) { if (this->actor.yDistToWater < 50.0f) { - if ((this->unk_88C < 2) || (this->yDistToLedge > this->ageProperties->unk_10)) { + if ((this->ledgeClimbType < 2) || (this->yDistToLedge > this->ageProperties->unk_10)) { return 0; } - } else if ((this->currentBoots != PLAYER_BOOTS_IRON) || (this->unk_88C > 2)) { + } else if ((this->currentBoots != PLAYER_BOOTS_IRON) || (this->ledgeClimbType > 2)) { return 0; } } else if (!(this->actor.bgCheckFlags & 1) || @@ -4330,18 +4469,18 @@ s32 func_80838A14(Player* this, PlayState* play) { } if ((this->actor.wallBgId != BGCHECK_SCENE) && (sTouchedWallFlags & 0x40)) { - if (this->unk_88D >= 6) { + if (this->ledgeClimbDelayTimer >= 6) { this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_CLIMB; if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { sp3C = 1; } } - } else if ((this->unk_88D >= 6) || CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { + } else if ((this->ledgeClimbDelayTimer >= 6) || CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { sp3C = 1; } if (sp3C != 0) { - Player_SetupAction(play, this, func_80845668, 0); + Player_SetupAction(play, this, Player_Action_80845668, 0); this->stateFlags1 |= PLAYER_STATE1_JUMPING; @@ -4383,11 +4522,11 @@ s32 func_80838A14(Player* this, PlayState* play) { LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f); AnimationContext_DisableQueue(play); - this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw + 0x8000; + this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; return 1; } - } else if ((this->actor.bgCheckFlags & 1) && (this->unk_88C == 1) && (this->unk_88D >= 3)) { + } else if ((this->actor.bgCheckFlags & 1) && (this->ledgeClimbType == 1) && (this->ledgeClimbDelayTimer >= 3)) { temp = (this->yDistToLedge * 0.08f) + 5.5f; func_808389E8(this, &gPlayerAnim_link_normal_jump, temp, play); this->linearVelocity = 2.5f; @@ -4399,11 +4538,11 @@ s32 func_80838A14(Player* this, PlayState* play) { } void func_80838E70(PlayState* play, Player* this, f32 arg2, s16 arg3) { - Player_SetupAction(play, this, func_80845CA4, 0); + Player_SetupAction(play, this, Player_Action_80845CA4, 0); func_80832440(play, this); - this->unk_84F = 1; - this->unk_850 = 1; + this->av1.actionVar1 = 1; + this->av2.actionVar2 = 1; this->unk_450.x = (Math_SinS(arg3) * arg2) + this->actor.world.pos.x; this->unk_450.z = (Math_CosS(arg3) * arg2) + this->actor.world.pos.z; @@ -4412,12 +4551,12 @@ void func_80838E70(PlayState* play, Player* this, f32 arg2, s16 arg3) { } void func_80838F18(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084D610, 0); + Player_SetupAction(play, this, Player_Action_8084D610, 0); Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait); } void func_80838F5C(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084F88C, 0); + Player_SetupAction(play, this, Player_Action_8084F88C, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_FLOOR_DISABLED; @@ -4490,19 +4629,19 @@ u8 sReturnEntranceGroupIndices[] = { }; s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* poly, u32 bgId) { - s32 sp3C; + s32 exitIndex; s32 temp; s32 sp34; - f32 linearVel; + f32 speedXZ; s32 yaw; if (this->actor.category == ACTORCAT_PLAYER) { - sp3C = 0; + exitIndex = 0; if (!(this->stateFlags1 & PLAYER_STATE1_DEAD) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (this->csAction == 0) && !(this->stateFlags1 & PLAYER_STATE1_LOADING) && - (((poly != NULL) && (sp3C = SurfaceType_GetSceneExitIndex(&play->colCtx, poly, bgId), sp3C != 0)) || - (func_8083816C(sFloorType) && (this->unk_A7A == 12)))) { + (((poly != NULL) && (exitIndex = SurfaceType_GetSceneExitIndex(&play->colCtx, poly, bgId), exitIndex != 0)) || + (func_8083816C(sFloorType) && (this->floorProperty == 12)))) { sp34 = this->unk_A84 - (s32)this->actor.world.pos.y; @@ -4511,11 +4650,11 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol return 0; } - if (sp3C == 0) { + if (exitIndex == 0) { Play_TriggerVoidOut(play); Scene_SetTransitionForNextEntrance(play); } else { - play->nextEntranceIndex = play->setupExitList[sp3C - 1]; + play->nextEntranceIndex = play->setupExitList[exitIndex - 1]; // Main override for entrance rando and entrance skips if (IS_RANDO) { @@ -4562,17 +4701,17 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = NATURE_ID_DISABLED; } else { - linearVel = this->linearVelocity; + speedXZ = this->linearVelocity; - if (linearVel < 0.0f) { + if (speedXZ < 0.0f) { this->actor.world.rot.y += 0x8000; - linearVel = -linearVel; + speedXZ = -speedXZ; } - if (linearVel > R_RUN_SPEED_LIMIT / 100.0f) { + if (speedXZ > R_RUN_SPEED_LIMIT / 100.0f) { gSaveContext.entranceSpeed = R_RUN_SPEED_LIMIT / 100.0f; } else { - gSaveContext.entranceSpeed = linearVel; + gSaveContext.entranceSpeed = speedXZ; } if (sConveyorSpeed != 0) { @@ -4597,13 +4736,13 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol if (play->transitionTrigger == TRANS_TRIGGER_OFF) { if ((this->actor.world.pos.y < -4000.0f) || - (((this->unk_A7A == 5) || (this->unk_A7A == 12)) && + (((this->floorProperty == 5) || (this->floorProperty == 12)) && ((sYDistToFloor < 100.0f) || (this->fallDistance > 400.0f) || ((play->sceneNum != SCENE_SHADOW_TEMPLE) && (this->fallDistance > 200.0f)))) || ((play->sceneNum == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) && (this->fallDistance > 320.0f))) { if (this->actor.bgCheckFlags & 1) { - if (this->unk_A7A == 5) { + if (this->floorProperty == 5) { Play_TriggerRespawn(play); } else { Play_TriggerVoidOut(play); @@ -4612,11 +4751,11 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol func_80078884(NA_SE_OC_ABYSS); } else { func_80838F5C(play, this); - this->unk_850 = 9999; - if (this->unk_A7A == 5) { - this->unk_84F = -1; + this->av2.actionVar2 = 9999; + if (this->floorProperty == 5) { + this->av1.actionVar1 = -1; } else { - this->unk_84F = 1; + this->av1.actionVar1 = 1; } } } @@ -4671,7 +4810,8 @@ f32 func_8083973C(PlayState* play, Player* this, Vec3f* arg2, Vec3f* arg3) { * Point B of the line is at player's world position offset by the entire `offset` vector. * Point A and B are always at the same height, meaning this is a horizontal line test. */ -s32 Player_PosVsWallLineTest(PlayState* play, Player* this, Vec3f* offset, CollisionPoly** wallPoly, s32* bgId, Vec3f* posResult) { +s32 Player_PosVsWallLineTest(PlayState* play, Player* this, Vec3f* offset, CollisionPoly** wallPoly, s32* bgId, + Vec3f* posResult) { Vec3f posA; Vec3f posB; @@ -4684,7 +4824,7 @@ s32 Player_PosVsWallLineTest(PlayState* play, Player* this, Vec3f* offset, Colli return BgCheck_EntityLineTest1(&play->colCtx, &posA, &posB, posResult, wallPoly, true, false, false, true, bgId); } -s32 func_80839800(Player* this, PlayState* play) { +s32 Player_ActionChange_1(Player* this, PlayState* play) { DoorShutter* doorShutter; EnDoor* door; // Can also be DoorKiller* s32 doorDirection; @@ -4696,14 +4836,14 @@ s32 func_80839800(Player* this, PlayState* play) { s32 frontRoom; Actor* attachedActor; LinkAnimationHeader* sp5C; - CollisionPoly* sp58; - Vec3f sp4C; + CollisionPoly* groundPoly; + Vec3f checkPos; if ((this->doorType != PLAYER_DOORTYPE_NONE) && (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) || ((this->heldActor != NULL) && (this->heldActor->id == ACTOR_EN_RU1)))) { // Disable doors in Boss Rush so the player can't leave the boss rooms backwards. - if ((CHECK_BTN_ALL(sControlInput->press.button, BTN_A) || (func_8084F9A0 == this->actionFunc)) && !IS_BOSS_RUSH) { + if ((CHECK_BTN_ALL(sControlInput->press.button, BTN_A) || (Player_Action_8084F9A0 == this->actionFunc)) && !IS_BOSS_RUSH) { doorActor = this->doorActor; if (this->doorType <= PLAYER_DOORTYPE_AJAR) { @@ -4719,11 +4859,11 @@ s32 func_80839800(Player* this, PlayState* play) { if (this->doorType == PLAYER_DOORTYPE_SLIDING) { doorShutter = (DoorShutter*)doorActor; - this->currentYaw = doorShutter->dyna.actor.home.rot.y; + this->yaw = doorShutter->dyna.actor.home.rot.y; if (doorDirection > 0) { - this->currentYaw -= 0x8000; + this->yaw -= 0x8000; } - this->actor.shape.rot.y = this->currentYaw; + this->actor.shape.rot.y = this->yaw; if (this->linearVelocity <= 0.0f) { this->linearVelocity = 0.1f; @@ -4731,7 +4871,7 @@ s32 func_80839800(Player* this, PlayState* play) { func_80838E70(play, this, 50.0f, this->actor.shape.rot.y); - this->unk_84F = 0; + this->av1.actionVar1 = 0; this->unk_447 = this->doorType; this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -4744,7 +4884,7 @@ s32 func_80839800(Player* this, PlayState* play) { func_80832224(this); if (this->doorTimer != 0) { - this->unk_850 = 0; + this->av2.actionVar2 = 0; Player_AnimChangeOnceMorph(play, this, func_80833338(this)); this->skelAnime.endFrame = 0.0f; } else { @@ -4777,7 +4917,7 @@ s32 func_80839800(Player* this, PlayState* play) { sp5C = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_doorB, this->modelAnimType); } - Player_SetupAction(play, this, func_80845EF8, 0); + Player_SetupAction(play, this, Player_Action_80845EF8, 0); func_80832528(play, this); if (doorDirection < 0) { @@ -4786,7 +4926,7 @@ s32 func_80839800(Player* this, PlayState* play) { this->actor.shape.rot.y = doorActor->shape.rot.y - 0x8000; } - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; sp6C = (doorDirection * 22.0f); this->actor.world.pos.x = doorActor->world.pos.x + sp6C * sp74; @@ -4812,13 +4952,14 @@ s32 func_80839800(Player* this, PlayState* play) { Actor_DisableLens(play); if (((doorActor->params >> 7) & 7) == 3) { - sp4C.x = doorActor->world.pos.x - (sp6C * sp74); - sp4C.y = doorActor->world.pos.y + 10.0f; - sp4C.z = doorActor->world.pos.z - (sp6C * sp78); + checkPos.x = doorActor->world.pos.x - (sp6C * sp74); + checkPos.y = doorActor->world.pos.y + 10.0f; + checkPos.z = doorActor->world.pos.z - (sp6C * sp78); - BgCheck_EntityRaycastFloor1(&play->colCtx, &sp58, &sp4C); + BgCheck_EntityRaycastFloor1(&play->colCtx, &groundPoly, &checkPos); - if (Player_HandleExitsAndVoids(play, this, sp58, BGCHECK_SCENE)) { + //! @bug groundPoly's bgId is not guaranteed to be BGCHECK_SCENE + if (Player_HandleExitsAndVoids(play, this, groundPoly, BGCHECK_SCENE)) { gSaveContext.entranceSpeed = 2.0f; gSaveContext.entranceSound = NA_SE_OC_DOOR_OPEN; } @@ -4858,7 +4999,7 @@ s32 func_80839800(Player* this, PlayState* play) { void func_80839E88(Player* this, PlayState* play) { LinkAnimationHeader* anim; - Player_SetupAction(play, this, func_80840450, 1); + Player_SetupAction(play, this, Player_Action_80840450, 1); if (this->unk_870 < 0.5f) { anim = func_808334E4(this); @@ -4870,13 +5011,13 @@ void func_80839E88(Player* this, PlayState* play) { this->unk_874 = this->unk_870; Player_AnimPlayLoop(play, this, anim); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_80839F30(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_808407CC, 1); + Player_SetupAction(play, this, Player_Action_808407CC, 1); Player_AnimChangeOnceMorph(play, this, func_80833338(this)); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_80839F90(Player* this, PlayState* play) { @@ -4893,11 +5034,11 @@ void func_80839FFC(Player* this, PlayState* play) { PlayerActionFunc actionFunc; if (func_8008E9C4(this)) { - actionFunc = func_80840450; + actionFunc = Player_Action_80840450; } else if (func_80833B2C(this)) { - actionFunc = func_808407CC; + actionFunc = Player_Action_808407CC; } else { - actionFunc = func_80840BC8; + actionFunc = Player_Action_80840BC8; } Player_SetupAction(play, this, actionFunc, 1); @@ -4906,7 +5047,7 @@ void func_80839FFC(Player* this, PlayState* play) { void func_8083A060(Player* this, PlayState* play) { func_80839FFC(this, play); if (func_8008E9C4(this)) { - this->unk_850 = 1; + this->av2.actionVar2 = 1; } } @@ -4926,30 +5067,30 @@ void func_8083A0F4(PlayState* play, Player* this) { if (interactActorId == ACTOR_BG_TOKI_SWD) { this->interactRangeActor->parent = &this->actor; - Player_SetupAction(play, this, func_8084F608, 0); + Player_SetupAction(play, this, Player_Action_8084F608, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; sMaskMemory = PLAYER_MASK_NONE; } else { LinkAnimationHeader* anim; if (interactActorId == ACTOR_BG_HEAVY_BLOCK) { - Player_SetupAction(play, this, func_80846120, 0); + Player_SetupAction(play, this, Player_Action_80846120, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; anim = &gPlayerAnim_link_normal_heavy_carry; } else if ((interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 0xF) == 1)) { - Player_SetupAction(play, this, func_80846260, 0); + Player_SetupAction(play, this, Player_Action_80846260, 0); anim = &gPlayerAnim_link_silver_carry; } else if (((interactActorId == ACTOR_EN_BOMBF) || (interactActorId == ACTOR_EN_KUSA)) && (Player_GetStrength() <= PLAYER_STR_NONE)) { - Player_SetupAction(play, this, func_80846408, 0); + Player_SetupAction(play, this, Player_Action_80846408, 0); this->actor.world.pos.x = (Math_SinS(interactRangeActor->yawTowardsPlayer) * 20.0f) + interactRangeActor->world.pos.x; this->actor.world.pos.z = (Math_CosS(interactRangeActor->yawTowardsPlayer) * 20.0f) + interactRangeActor->world.pos.z; - this->currentYaw = this->actor.shape.rot.y = interactRangeActor->yawTowardsPlayer + 0x8000; + this->yaw = this->actor.shape.rot.y = interactRangeActor->yawTowardsPlayer + 0x8000; anim = &gPlayerAnim_link_normal_nocarry_free; } else { - Player_SetupAction(play, this, func_80846050, 0); + Player_SetupAction(play, this, Player_Action_80846050, 0); anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_carryB, this->modelAnimType); } @@ -4968,7 +5109,7 @@ void func_8083A0F4(PlayState* play, Player* this) { } void func_8083A2F8(PlayState* play, Player* this) { - func_80835DAC(play, this, func_8084B530, 0); + func_80835DAC(play, this, Player_Action_8084B530, 0); this->stateFlags1 |= PLAYER_STATE1_TEXT_ON_SCREEN | PLAYER_STATE1_IN_CUTSCENE; @@ -4979,37 +5120,37 @@ void func_8083A2F8(PlayState* play, Player* this) { } void func_8083A360(PlayState* play, Player* this) { - func_80835DAC(play, this, func_8084CC98, 0); + func_80835DAC(play, this, Player_Action_8084CC98, 0); } void func_8083A388(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084B78C, 0); + Player_SetupAction(play, this, Player_Action_8084B78C, 0); } void func_8083A3B0(PlayState* play, Player* this) { - s32 sp1C = this->unk_850; - s32 sp18 = this->unk_84F; + s32 sp1C = this->av2.actionVar2; + s32 sp18 = this->av1.actionVar1; - func_80835DAC(play, this, func_8084BF1C, 0); + func_80835DAC(play, this, Player_Action_8084BF1C, 0); this->actor.velocity.y = 0.0f; - this->unk_850 = sp1C; - this->unk_84F = sp18; + this->av2.actionVar2 = sp1C; + this->av1.actionVar1 = sp18; } void func_8083A40C(PlayState* play, Player* this) { - func_80835DAC(play, this, func_8084C760, 0); + func_80835DAC(play, this, Player_Action_8084C760, 0); } void func_8083A434(PlayState* play, Player* this) { - func_80835DAC(play, this, func_8084E6D4, 0); + func_80835DAC(play, this, Player_Action_8084E6D4, 0); this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_IN_CUTSCENE; if (this->getItemId == GI_HEART_CONTAINER_2) { - this->unk_850 = 20; + this->av2.actionVar2 = 20; } else if (this->getItemId >= 0 || (this->getItemEntry.objectId != OBJECT_INVALID && this->getItemEntry.getItemId >= 0)) { - this->unk_850 = 1; + this->av2.actionVar2 = 1; } else { this->getItemId = -this->getItemId; this->getItemEntry.getItemId = -this->getItemEntry.getItemId; @@ -5021,7 +5162,7 @@ s32 func_8083A4A8(Player* this, PlayState* play) { LinkAnimationHeader* anim; f32 temp; - yawDiff = this->currentYaw - this->actor.shape.rot.y; + yawDiff = this->yaw - this->actor.shape.rot.y; if ((ABS(yawDiff) < 0x1000) && (this->linearVelocity > 4.0f)) { anim = &gPlayerAnim_link_normal_run_jump; @@ -5036,7 +5177,7 @@ s32 func_8083A4A8(Player* this, PlayState* play) { } func_80838940(this, anim, temp, play, NA_SE_VO_LI_AUTO_JUMP); - this->unk_850 = 1; + this->av2.actionVar2 = 1; return 1; } @@ -5045,13 +5186,13 @@ void func_8083A5C4(PlayState* play, Player* this, CollisionPoly* arg2, f32 arg3, f32 nx = COLPOLY_GET_NORMAL(arg2->normal.x); f32 nz = COLPOLY_GET_NORMAL(arg2->normal.z); - Player_SetupAction(play, this, func_8084BBE4, 0); + Player_SetupAction(play, this, Player_Action_8084BBE4, 0); func_80832564(play, this); Player_AnimPlayOnce(play, this, anim); this->actor.world.pos.x -= (arg3 + 1.0f) * nx; this->actor.world.pos.z -= (arg3 + 1.0f) * nz; - this->actor.shape.rot.y = this->currentYaw = Math_Atan2S(nz, nx); + this->actor.shape.rot.y = this->yaw = Math_Atan2S(nz, nx); func_80832224(this); Player_SkelAnimeResetPrevTranslRot(this); @@ -5104,20 +5245,20 @@ s32 func_8083A6AC(Player* this, PlayState* play) { if (sp50) { func_80836898(play, this, func_8083A3B0); - this->currentYaw += 0x8000; - this->actor.shape.rot.y = this->currentYaw; + this->yaw += 0x8000; + this->actor.shape.rot.y = this->yaw; this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LADDER; Player_AnimReplaceApplyFlags(play, this, 0x9F); - this->unk_850 = -1; - this->unk_84F = sp50; + this->av2.actionVar2 = -1; + this->av1.actionVar1 = sp50; } else { this->stateFlags1 |= PLAYER_STATE1_HANGING_OFF_LEDGE; this->stateFlags1 &= ~PLAYER_STATE1_TARGET_NOTHING; } - Player_PlaySfx(&this->actor, NA_SE_PL_SLIPDOWN); + Player_PlaySfx(this, NA_SE_PL_SLIPDOWN); func_80832698(this, NA_SE_VO_LI_HANG); return 1; } @@ -5127,7 +5268,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) { } void func_8083A9B8(Player* this, LinkAnimationHeader* anim, PlayState* play) { - Player_SetupAction(play, this, func_8084BDFC, 0); + Player_SetupAction(play, this, Player_Action_8084BDFC, 0); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f); } @@ -5153,7 +5294,7 @@ void func_8083AA10(Player* this, PlayState* play) { } if (!(this->stateFlags3 & PLAYER_STATE3_MIDAIR) && !(this->skelAnime.moveFlags & 0x80) && - (func_8084411C != this->actionFunc) && (func_80844A44 != this->actionFunc)) { + (Player_Action_8084411C != this->actionFunc) && (Player_Action_80844A44 != this->actionFunc)) { if ((sPrevFloorProperty == 7) || (this->meleeWeaponState != 0)) { Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.prevPos); @@ -5167,12 +5308,12 @@ void func_8083AA10(Player* this, PlayState* play) { return; } - sp5C = (s16)(this->currentYaw - this->actor.shape.rot.y); + sp5C = (s16)(this->yaw - this->actor.shape.rot.y); - Player_SetupAction(play, this, func_8084411C, 1); + Player_SetupAction(play, this, Player_Action_8084411C, 1); func_80832440(play, this); - this->floorSfxOffset = this->unk_A82; + this->floorSfxOffset = this->prevFloorSfxOffset; if ((this->actor.bgCheckFlags & 4) && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (sPrevFloorProperty != 6) && (sPrevFloorProperty != 9) && (sYDistToFloor > 20.0f) && (this->meleeWeaponState == 0) && (ABS(sp5C) < 0x2000) && @@ -5186,7 +5327,7 @@ void func_8083AA10(Player* this, PlayState* play) { if (WaterBox_GetSurface1(play, &play->colCtx, sp44.x, sp44.z, &sp3C, &sp50) && ((sp3C - sp40) > 50.0f)) { func_808389E8(this, &gPlayerAnim_link_normal_run_jump_water_fall, 6.0f, play); - Player_SetupAction(play, this, func_80844A44, 0); + Player_SetupAction(play, this, Player_Action_80844A44, 0); return; } } @@ -5238,7 +5379,7 @@ s32 Player_StartCsAction(PlayState* play, Player* this) { // unk_6AD will get set to 3 in `Player_UpdateCommon` if `this->csAction` is non-zero // (with a special case for `PLAYER_CSACTION_7`) if (this->unk_6AD == 3) { - Player_SetupAction(play, this, func_80852E14, 0); + Player_SetupAction(play, this, Player_Action_CsAction, 0); if (this->doorBgCamIndex != 0) { this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; } @@ -5269,9 +5410,9 @@ void func_8083AE40(Player* this, s16 objectId) { } void func_8083AF44(PlayState* play, Player* this, s32 magicSpell) { - func_80835DE4(play, this, func_808507F4, 0); + func_80835DE4(play, this, Player_Action_808507F4, 0); - this->unk_84F = magicSpell - 3; + this->av1.actionVar1 = magicSpell - 3; //! @bug `MAGIC_CONSUME_WAIT_PREVIEW` is not guaranteed to succeed. //! Ideally, the return value of `Magic_RequestChange` should be checked before allowing the process of @@ -5319,7 +5460,7 @@ static LinkAnimationHeader* D_80854548[] = { &gPlayerAnim_link_normal_take_out, }; -s32 func_8083B040(Player* this, PlayState* play) { +s32 Player_ActionChange_13(Player* this, PlayState* play) { s32 sp2C; s32 sp28; GetItemEntry giEntry; @@ -5335,7 +5476,7 @@ s32 func_8083B040(Player* this, PlayState* play) { if ((sp2C != 3) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) { func_8083AF44(play, this, sp2C); } else { - Player_SetupAction(play, this, func_8085063C, 1); + Player_SetupAction(play, this, Player_Action_8085063C, 1); this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE; Player_AnimPlayOnce(play, this, func_80833338(this)); func_80835EA4(play, 4); @@ -5355,7 +5496,7 @@ s32 func_8083B040(Player* this, PlayState* play) { (this->exchangeItemId == EXCH_ITEM_BLUE_FIRE))))))) { if ((play->actorCtx.titleCtx.delayTimer == 0) && (play->actorCtx.titleCtx.alpha == 0)) { - func_80835DE4(play, this, func_8084F104, 0); + func_80835DE4(play, this, Player_Action_8084F104, 0); if (sp2C >= 0) { if (this->getItemEntry.objectId == OBJECT_INVALID) { @@ -5385,19 +5526,19 @@ s32 func_8083B040(Player* this, PlayState* play) { ((this->exchangeItemId != EXCH_ITEM_BEAN) || (this->itemAction == PLAYER_IA_MAGIC_BEAN))) { if (this->exchangeItemId == EXCH_ITEM_BEAN) { Inventory_ChangeAmmo(ITEM_BEAN, -1); - func_80835DE4(play, this, func_8084279C, 0); + func_80835DE4(play, this, Player_Action_8084279C, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; - this->unk_850 = 0x50; - this->unk_84F = -1; + this->av2.actionVar2 = 0x50; + this->av1.actionVar1 = -1; } targetActor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO; this->unk_664 = this->targetActor; } else if (sp2C == EXCH_ITEM_LETTER_RUTO) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; this->actor.textId = 0x4005; func_80835EA4(play, 1); } else { - this->unk_84F = 2; + this->av1.actionVar1 = 2; this->actor.textId = 0xCF; func_80835EA4(play, 4); } @@ -5405,10 +5546,10 @@ s32 func_8083B040(Player* this, PlayState* play) { this->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO; this->exchangeItemId = sp2C; - if (this->unk_84F < 0) { + if (this->av1.actionVar1 < 0) { Player_AnimChangeOnceMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check, this->modelAnimType)); } else { - Player_AnimPlayOnce(play, this, D_80854548[this->unk_84F]); + Player_AnimPlayOnce(play, this, D_80854548[this->av1.actionVar1]); } func_80832224(this); @@ -5419,20 +5560,20 @@ s32 func_8083B040(Player* this, PlayState* play) { sp2C = Player_ActionToBottle(this, this->itemAction); if (sp2C >= 0) { if (sp2C == 0xC) { - func_80835DE4(play, this, func_8084EED8, 0); + func_80835DE4(play, this, Player_Action_8084EED8, 0); Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_bottle_bug_out); func_80835EA4(play, 3); } else if ((sp2C > 0) && (sp2C < 4)) { - func_80835DE4(play, this, func_8084EFC0, 0); + func_80835DE4(play, this, Player_Action_8084EFC0, 0); Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_bottle_fish_out); func_80835EA4(play, (sp2C == 1) ? 1 : 5); } else { - func_80835DE4(play, this, func_8084EAC0, 0); + func_80835DE4(play, this, Player_Action_8084EAC0, 0); Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_start); func_80835EA4(play, 2); } } else { - func_80835DE4(play, this, func_8084E3C4, 0); + func_80835DE4(play, this, Player_Action_8084E3C4, 0); Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_okarina_start); this->stateFlags2 |= PLAYER_STATE2_OCARINA_PLAYING; func_80835EA4(play, (this->unk_6A8 != NULL) ? 0x5B : 0x5A); @@ -5443,8 +5584,8 @@ s32 func_8083B040(Player* this, PlayState* play) { } } else if (func_8083AD4C(play, this)) { if (!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { - Player_SetupAction(play, this, func_8084B1D8, 1); - this->unk_850 = 13; + Player_SetupAction(play, this, Player_Action_8084B1D8, 1); + this->av2.actionVar2 = 13; func_8083B010(this); } this->stateFlags1 |= PLAYER_STATE1_FIRST_PERSON; @@ -5467,14 +5608,15 @@ s32 func_8083B040(Player* this, PlayState* play) { return 0; } -s32 func_8083B644(Player* this, PlayState* play) { +s32 Player_ActionChange_4(Player* this, PlayState* play) { Actor* sp34 = this->targetActor; Actor* sp30 = this->unk_664; Actor* sp2C = NULL; s32 sp28 = 0; s32 sp24; - sp24 = (sp30 != NULL) && (CHECK_FLAG_ALL(sp30->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || (sp30->naviEnemyId != 0xFF)); + sp24 = (sp30 != NULL) && + (CHECK_FLAG_ALL(sp30->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || (sp30->naviEnemyId != 0xFF)); if (sp24 || (this->naviTextId != 0)) { sp28 = (this->naviTextId < 0) && ((ABS(this->naviTextId) & 0xFF00) != 0x200); @@ -5511,8 +5653,7 @@ s32 func_8083B644(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT; } - if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP) && - !sp28) { + if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP) && !sp28) { return 0; } @@ -5520,11 +5661,7 @@ s32 func_8083B644(Player* this, PlayState* play) { this->targetActor = NULL; if (sp28 || !sp24) { - if (this->naviTextId >= 0) { - sp2C->textId = this->naviTextId; - } else { - sp2C->textId = -this->naviTextId; - } + sp2C->textId = ABS(this->naviTextId); } else { if (sp2C->naviEnemyId != 0xFF) { sp2C->textId = sp2C->naviEnemyId + 0x600; @@ -5556,18 +5693,18 @@ s32 func_8083B8F4(Player* this, PlayState* play) { return 0; } -s32 func_8083B998(Player* this, PlayState* play) { +s32 Player_ActionChange_0(Player* this, PlayState* play) { if (this->unk_6AD != 0) { - func_8083B040(this, play); + Player_ActionChange_13(this, play); return 1; } - if ((this->unk_664 != NULL) && - (CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || (this->unk_664->naviEnemyId != 0xFF))) { + if ((this->unk_664 != NULL) && (CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || + (this->unk_664->naviEnemyId != 0xFF))) { this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT; - } else if ((this->naviTextId == 0 || CVarGetInteger("gNaviOnL", 0)) && !func_8008E9C4(this) && - CHECK_BTN_ALL(sControlInput->press.button, BTN_CUP) && (YREG(15) != 0x10) && (YREG(15) != 0x20) && - !func_8083B8F4(this, play)) { + } else if ((this->naviTextId == 0 || CVarGetInteger("gNaviOnL", 0)) && !func_8008E9C4(this) && CHECK_BTN_ALL(sControlInput->press.button, BTN_CUP) && + (YREG(15) != 0x10) && + (YREG(15) != 0x20) && !func_8083B8F4(this, play)) { func_80078884(NA_SE_SY_ERROR); } @@ -5576,11 +5713,11 @@ s32 func_8083B998(Player* this, PlayState* play) { void func_8083BA90(PlayState* play, Player* this, s32 arg2, f32 xzVelocity, f32 yVelocity) { func_80837948(play, this, arg2); - Player_SetupAction(play, this, func_80844AF4, 0); + Player_SetupAction(play, this, Player_Action_80844AF4, 0); this->stateFlags3 |= PLAYER_STATE3_MIDAIR; - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; this->linearVelocity = xzVelocity; this->actor.velocity.y = yVelocity; @@ -5612,8 +5749,9 @@ s32 func_8083BBA0(Player* this, PlayState* play) { } void func_8083BC04(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80844708, 0); - LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType), + Player_SetupAction(play, this, Player_Action_80844708, 0); + LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, + GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType), 1.25f * D_808535E8); gSaveContext.sohStats.count[COUNT_ROLLS]++; } @@ -5632,18 +5770,18 @@ void func_8083BCD0(Player* this, PlayState* play, s32 arg2) { if (arg2) {} - this->unk_850 = 1; - this->unk_84F = arg2; + this->av2.actionVar2 = 1; + this->av1.actionVar1 = arg2; - this->currentYaw = this->actor.shape.rot.y + (arg2 << 0xE); + this->yaw = this->actor.shape.rot.y + (arg2 << 0xE); this->linearVelocity = !(arg2 & 1) ? 6.0f : 8.5f; this->stateFlags2 |= PLAYER_STATE2_HOPPING; - Player_PlaySfx(&this->actor, ((arg2 << 0xE) == 0x8000) ? NA_SE_PL_ROLL : NA_SE_PL_SKIP); + Player_PlaySfx(this, ((arg2 << 0xE) == 0x8000) ? NA_SE_PL_ROLL : NA_SE_PL_SKIP); } -s32 func_8083BDBC(Player* this, PlayState* play) { +s32 Player_ActionChange_10(Player* this, PlayState* play) { s32 sp2C; if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && @@ -5660,7 +5798,7 @@ s32 func_8083BDBC(Player* this, PlayState* play) { func_8083BC04(this, play); } } else { - if (Player_GetMeleeWeaponHeld(this) && Player_CanUpdateItems(this)) { + if ((Player_GetMeleeWeaponHeld(this) != 0) && Player_CanUpdateItems(this)) { func_8083BA90(play, this, PLAYER_MWA_JUMPSLASH_START, 5.0f, 5.0f); } else { func_8083BC04(this, play); @@ -5711,7 +5849,7 @@ void func_8083BF50(Player* this, PlayState* play) { LinkAnimation_Change(play, &this->skelAnime, anim, 1.0f, 0.0f, Animation_GetLastFrame(anim), ANIMMODE_ONCE, 4.0f * sp30); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_8083C0B8(Player* this, PlayState* play) { @@ -5720,9 +5858,9 @@ void func_8083C0B8(Player* this, PlayState* play) { } void func_8083C0E8(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80840BC8, 1); + Player_SetupAction(play, this, Player_Action_80840BC8, 1); Player_AnimPlayOnce(play, this, func_80833338(this)); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_8083C148(Player* this, PlayState* play) { @@ -5741,7 +5879,7 @@ void func_8083C148(Player* this, PlayState* play) { this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_FIRST_PERSON); } -s32 func_8083C1DC(Player* this, PlayState* play) { +s32 Player_ActionChange_6(Player* this, PlayState* play) { if (!func_80833B54(this) && (D_808535E0 == 0) && !(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { if (func_8083BC7C(this, play)) { @@ -5757,7 +5895,7 @@ s32 func_8083C1DC(Player* this, PlayState* play) { return 0; } -s32 func_8083C2B0(Player* this, PlayState* play) { +s32 Player_ActionChange_11(Player* this, PlayState* play) { LinkAnimationHeader* anim; f32 frame; @@ -5768,7 +5906,7 @@ s32 func_8083C2B0(Player* this, PlayState* play) { func_80832318(this); Player_DetachHeldActor(play, this); - if (Player_SetupAction(play, this, func_80843188, 0)) { + if (Player_SetupAction(play, this, Player_Action_80843188, 0)) { this->stateFlags1 |= PLAYER_STATE1_SHIELDING; if (!Player_IsChildWithHylianShield(this)) { @@ -5795,7 +5933,7 @@ s32 func_8083C2B0(Player* this, PlayState* play) { Player_AnimReplaceApplyFlags(play, this, 4); } - Player_PlaySfx(&this->actor, NA_SE_IT_SHIELD_POSTURE); + Player_PlaySfx(this, NA_SE_IT_SHIELD_POSTURE); } return 1; @@ -5805,12 +5943,12 @@ s32 func_8083C2B0(Player* this, PlayState* play) { } s32 func_8083C484(Player* this, f32* arg1, s16* arg2) { - s16 yaw = this->currentYaw - *arg2; + s16 yaw = this->yaw - *arg2; if (ABS(yaw) > 0x6000) { if (func_8083721C(this)) { *arg1 = 0.0f; - *arg2 = this->currentYaw; + *arg2 = this->yaw; } else { return 1; } @@ -5825,7 +5963,7 @@ void func_8083C50C(Player* this) { } } -s32 func_8083C544(Player* this, PlayState* play) { +s32 Player_ActionChange_8(Player* this, PlayState* play) { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) { if (!(this->stateFlags1 & PLAYER_STATE1_SHIELDING) && (Player_GetMeleeWeaponHeld(this) != 0) && (this->unk_844 == 1) && (this->heldItemAction != PLAYER_IA_DEKU_STICK)) { @@ -5844,7 +5982,7 @@ s32 func_8083C544(Player* this, PlayState* play) { s32 func_8083C61C(PlayState* play, Player* this) { if ((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_2) && (this->actor.bgCheckFlags & 1) && (AMMO(ITEM_NUT) != 0)) { - Player_SetupAction(play, this, func_8084E604, 0); + Player_SetupAction(play, this, Player_Action_8084E604, 0); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_light_bom); this->unk_6AD = 0; return 1; @@ -5863,15 +6001,15 @@ s32 func_8083C6B8(PlayState* play, Player* this) { if (sUseHeldItem) { if (Player_GetBottleHeld(this) >= 0) { - Player_SetupAction(play, this, func_8084ECA4, 0); + Player_SetupAction(play, this, Player_Action_8084ECA4, 0); if (this->actor.yDistToWater > 12.0f) { - this->unk_850 = 1; + this->av2.actionVar2 = 1; } - Player_AnimPlayOnceAdjusted(play, this, D_80854554[this->unk_850].unk_00); + Player_AnimPlayOnceAdjusted(play, this, D_80854554[this->av2.actionVar2].unk_00); - Player_PlaySfx(&this->actor, NA_SE_IT_SWORD_SWING); + Player_PlaySfx(this, NA_SE_IT_SWORD_SWING); func_80832698(this, NA_SE_VO_LI_AUTO_JUMP); return 1; } @@ -5888,7 +6026,7 @@ s32 func_8083C6B8(PlayState* play, Player* this) { return 0; } - Player_SetupAction(play, this, func_80850C68, 0); + Player_SetupAction(play, this, Player_Action_80850C68, 0); this->unk_860 = 1; Player_ZeroSpeedXZ(this); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_fishing_throw); @@ -5905,9 +6043,9 @@ void func_8083C858(Player* this, PlayState* play) { PlayerActionFunc actionFunc; if (func_80833BCC(this)) { - actionFunc = func_8084227C; + actionFunc = Player_Action_8084227C; } else { - actionFunc = func_80842180; + actionFunc = Player_Action_80842180; } Player_SetupAction(play, this, actionFunc, 1); @@ -5918,7 +6056,7 @@ void func_8083C858(Player* this, PlayState* play) { } void func_8083C8DC(Player* this, PlayState* play, s16 arg2) { - this->actor.shape.rot.y = this->currentYaw = arg2; + this->actor.shape.rot.y = this->yaw = arg2; func_8083C858(this, play); } @@ -5931,10 +6069,10 @@ s32 func_8083C910(PlayState* play, Player* this, f32 arg2) { &sp2C) != 0) { sp28 -= this->actor.world.pos.y; if (this->ageProperties->unk_24 <= sp28) { - Player_SetupAction(play, this, func_8084D7C4, 0); + Player_SetupAction(play, this, Player_Action_8084D7C4, 0); Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim); this->stateFlags1 |= PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE; - this->unk_850 = 20; + this->av2.actionVar2 = 20; this->linearVelocity = 2.0f; Player_SetBootData(play, this); return 0; @@ -5948,7 +6086,7 @@ s32 func_8083C910(PlayState* play, Player* this, f32 arg2) { void func_8083CA20(PlayState* play, Player* this) { if (func_8083C910(play, this, 180.0f)) { - this->unk_850 = -20; + this->av2.actionVar2 = -20; } } @@ -5956,7 +6094,7 @@ void func_8083CA54(PlayState* play, Player* this) { this->linearVelocity = 2.0f; gSaveContext.entranceSpeed = 2.0f; if (func_8083C910(play, this, 120.0f)) { - this->unk_850 = -15; + this->av2.actionVar2 = -15; } } @@ -5968,47 +6106,47 @@ void func_8083CA9C(PlayState* play, Player* this) { this->linearVelocity = gSaveContext.entranceSpeed; if (func_8083C910(play, this, 800.0f)) { - this->unk_850 = -80 / this->linearVelocity; - if (this->unk_850 < -20) { - this->unk_850 = -20; + this->av2.actionVar2 = -80 / this->linearVelocity; + if (this->av2.actionVar2 < -20) { + this->av2.actionVar2 = -20; } } } void func_8083CB2C(Player* this, s16 yaw, PlayState* play) { - Player_SetupAction(play, this, func_808414F8, 1); + Player_SetupAction(play, this, Player_Action_808414F8, 1); LinkAnimation_CopyJointToMorph(play, &this->skelAnime); this->unk_864 = this->unk_868 = 0.0f; - this->currentYaw = yaw; + this->yaw = yaw; } void func_8083CB94(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80840DE4, 1); + Player_SetupAction(play, this, Player_Action_80840DE4, 1); Player_AnimChangeLoopMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_walk, this->modelAnimType)); } void func_8083CBF0(Player* this, s16 yaw, PlayState* play) { - Player_SetupAction(play, this, func_808423EC, 1); + Player_SetupAction(play, this, Player_Action_808423EC, 1); LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_anchor_back_walk, 2.2f, 0.0f, Animation_GetLastFrame(&gPlayerAnim_link_anchor_back_walk), ANIMMODE_ONCE, -6.0f); this->linearVelocity = 8.0f; - this->currentYaw = yaw; + this->yaw = yaw; } void func_8083CC9C(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084193C, 1); + Player_SetupAction(play, this, Player_Action_8084193C, 1); Player_AnimChangeLoopMorph(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_side_walkR, this->modelAnimType)); this->unk_868 = 0.0f; } void func_8083CD00(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084251C, 1); + Player_SetupAction(play, this, Player_Action_8084251C, 1); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_link_anchor_back_brake, 2.0f); } void func_8083CD54(PlayState* play, Player* this, s16 yaw) { - this->currentYaw = yaw; - Player_SetupAction(play, this, func_80841BA8, 1); + this->yaw = yaw; + Player_SetupAction(play, this, Player_Action_80841BA8, 1); this->unk_87E = 1200; this->unk_87E *= D_808535E8; LinkAnimation_Change(play, &this->skelAnime, D_80853914[PLAYER_ANIMGROUP_45_turn][this->modelAnimType], 1.0f, 0.0f, @@ -6018,7 +6156,7 @@ void func_8083CD54(PlayState* play, Player* this, s16 yaw) { void func_8083CE0C(Player* this, PlayState* play) { LinkAnimationHeader* anim; - Player_SetupAction(play, this, func_80840BC8, 1); + Player_SetupAction(play, this, Player_Action_80840BC8, 1); if (this->unk_870 < 0.5f) { anim = D_80853914[PLAYER_ANIMGROUP_waitR2wait][this->modelAnimType]; @@ -6027,13 +6165,13 @@ void func_8083CE0C(Player* this, PlayState* play) { } Player_AnimPlayOnce(play, this, anim); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_8083CEAC(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80840450, 1); + Player_SetupAction(play, this, Player_Action_80840450, 1); Player_AnimChangeOnceMorph(play, this, D_80853914[PLAYER_ANIMGROUP_wait2waitR][this->modelAnimType]); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } void func_8083CF10(Player* this, PlayState* play) { @@ -6082,7 +6220,7 @@ void func_8083D0A8(PlayState* play, Player* this, f32 arg2) { func_80832340(play, this); if (func_8083CFA8(play, this, arg2, 500)) { - Player_PlaySfx(&this->actor, NA_SE_EV_JUMP_OUT_WATER); + Player_PlaySfx(this, NA_SE_EV_JUMP_OUT_WATER); } Player_SetBootData(play, this); @@ -6093,7 +6231,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { if ((arg2 == NULL) || (CHECK_BTN_ALL(arg2->press.button, BTN_A) && (ABS(this->unk_6C2) < 12000) && (this->currentBoots != PLAYER_BOOTS_IRON))) { - Player_SetupAction(play, this, func_8084DC48, 0); + Player_SetupAction(play, this, Player_Action_8084DC48, 0); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_swimer_swim_deep_start); this->unk_6C2 = 0; @@ -6102,7 +6240,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { if (arg2 != NULL) { this->stateFlags2 |= PLAYER_STATE2_DIVING; - Player_PlaySfx(&this->actor, NA_SE_PL_DIVE_BUBBLE); + Player_PlaySfx(this, NA_SE_PL_DIVE_BUBBLE); } return 1; @@ -6116,13 +6254,13 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER; if (arg2 != NULL) { - Player_SetupAction(play, this, func_8084E1EC, 1); + Player_SetupAction(play, this, Player_Action_8084E1EC, 1); if (this->stateFlags1 & PLAYER_STATE1_GETTING_ITEM) { this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; } - this->unk_850 = 2; + this->av2.actionVar2 = 2; } func_80832340(play, this); @@ -6138,7 +6276,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { } if (func_8083CFA8(play, this, this->actor.velocity.y, 500)) { - Player_PlaySfx(&this->actor, NA_SE_PL_FACE_UP); + Player_PlaySfx(this, NA_SE_PL_FACE_UP); } return 1; @@ -6152,7 +6290,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { void func_8083D330(PlayState* play, Player* this) { Player_AnimPlayLoop(play, this, &gPlayerAnim_link_swimer_swim); this->unk_6C2 = 16000; - this->unk_850 = 1; + this->av2.actionVar2 = 1; } void func_8083D36C(PlayState* play, Player* this) { @@ -6162,12 +6300,12 @@ void func_8083D36C(PlayState* play, Player* this) { if ((this->currentBoots != PLAYER_BOOTS_IRON) && (this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) { this->stateFlags2 &= ~PLAYER_STATE2_UNDERWATER; func_8083D12C(play, this, 0); - this->unk_84F = 1; - } else if (func_80844A44 == this->actionFunc) { - Player_SetupAction(play, this, func_8084DC48, 0); + this->av1.actionVar1 = 1; + } else if (Player_Action_80844A44 == this->actionFunc) { + Player_SetupAction(play, this, Player_Action_8084DC48, 0); func_8083D330(play, this); } else { - Player_SetupAction(play, this, func_8084D610, 1); + Player_SetupAction(play, this, Player_Action_8084D610, 1); Player_AnimChangeOnceMorph(play, this, (this->actor.bgCheckFlags & 1) ? &gPlayerAnim_link_swimer_wait2swim_wait : &gPlayerAnim_link_swimer_land2swim_wait); @@ -6176,7 +6314,7 @@ void func_8083D36C(PlayState* play, Player* this) { if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (this->actor.yDistToWater < this->ageProperties->unk_2C)) { if (func_8083CFA8(play, this, this->actor.velocity.y, 500)) { - Player_PlaySfx(&this->actor, NA_SE_EV_DIVE_INTO_WATER); + Player_PlaySfx(this, NA_SE_EV_DIVE_INTO_WATER); if (this->fallDistance > 800.0f) { func_80832698(this, NA_SE_VO_LI_CLIMB_END); @@ -6203,14 +6341,14 @@ void func_8083D53C(PlayState* play, Player* this) { } } - if ((func_80845668 != this->actionFunc) && (func_8084BDFC != this->actionFunc)) { + if ((Player_Action_80845668 != this->actionFunc) && (Player_Action_8084BDFC != this->actionFunc)) { if (this->ageProperties->unk_2C < this->actor.yDistToWater) { if (!(this->stateFlags1 & PLAYER_STATE1_IN_WATER) || (!((this->currentBoots == PLAYER_BOOTS_IRON) && (this->actor.bgCheckFlags & 1)) && - (func_8084E30C != this->actionFunc) && (func_8084E368 != this->actionFunc) && - (func_8084D610 != this->actionFunc) && (func_8084D84C != this->actionFunc) && - (func_8084DAB4 != this->actionFunc) && (func_8084DC48 != this->actionFunc) && - (func_8084E1EC != this->actionFunc) && (func_8084D7C4 != this->actionFunc))) { + (Player_Action_8084E30C != this->actionFunc) && (Player_Action_8084E368 != this->actionFunc) && + (Player_Action_8084D610 != this->actionFunc) && (Player_Action_8084D84C != this->actionFunc) && + (Player_Action_8084DAB4 != this->actionFunc) && (Player_Action_8084DC48 != this->actionFunc) && + (Player_Action_8084E1EC != this->actionFunc) && (Player_Action_8084D7C4 != this->actionFunc))) { func_8083D36C(play, this); return; } @@ -6376,7 +6514,7 @@ void func_8083DDC8(Player* this, PlayState* play) { if (!func_8002DD78(this) && !func_808334B4(this) && (this->linearVelocity > 5.0f)) { temp1 = this->linearVelocity * 200.0f; - temp2 = (s16)(this->currentYaw - this->actor.shape.rot.y) * this->linearVelocity * 0.1f; + temp2 = (s16)(this->yaw - this->actor.shape.rot.y) * this->linearVelocity * 0.1f; temp1 = CLAMP(temp1, -4000, 4000); temp2 = CLAMP(-temp2, -4000, 4000); Math_ScaledStepToS(&this->unk_6BC, temp1, 900); @@ -6391,11 +6529,11 @@ void func_8083DDC8(Player* this, PlayState* play) { void func_8083DF68(Player* this, f32 arg1, s16 arg2) { Math_AsymStepToF(&this->linearVelocity, arg1, REG(19) / 100.0f, 1.5f); - Math_ScaledStepToS(&this->currentYaw, arg2, REG(27)); + Math_ScaledStepToS(&this->yaw, arg2, REG(27)); } void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { - s16 yawDiff = this->currentYaw - *arg2; + s16 yawDiff = this->yaw - *arg2; if (this->meleeWeaponState == 0) { float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f; @@ -6434,11 +6572,11 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (ABS(yawDiff) > 0x6000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) { - this->currentYaw = *arg2; + this->yaw = *arg2; } } else { Math_AsymStepToF(&this->linearVelocity, *arg1, 0.05f, 0.1f); - Math_ScaledStepToS(&this->currentYaw, *arg2, 200); + Math_ScaledStepToS(&this->yaw, *arg2, 200); } } @@ -6447,7 +6585,7 @@ static struct_80854578 D_80854578[] = { { &gPlayerAnim_link_uma_right_up, -34.16f, 7.91f }, }; -s32 func_8083E0FC(Player* this, PlayState* play) { +s32 Player_ActionChange_3(Player* this, PlayState* play) { EnHorse* rideActor = (EnHorse*)this->rideActor; f32 unk_04; f32 unk_08; @@ -6478,7 +6616,7 @@ s32 func_8083E0FC(Player* this, PlayState* play) { rideActor->actor.world.pos.z + rideActor->riderPos.z + ((unk_08 * sp38) - (unk_04 * sp34)); this->unk_878 = rideActor->actor.world.pos.y - this->actor.world.pos.y; - this->currentYaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y; Actor_MountHorse(play, this, &rideActor->actor); Player_AnimPlayOnce(play, this, D_80854578[temp].anim); @@ -6513,7 +6651,7 @@ s32 Player_HandleSlopes(PlayState* play, Player* this, CollisionPoly* floorPoly) f32 slopeSlowdownSpeedStep; s16 velYawToDownwardSlope; - if (!Player_InBlockingCsMode(play, this) && (func_8084F390 != this->actionFunc) && + if (!Player_InBlockingCsMode(play, this) && (Player_Action_8084F390 != this->actionFunc) && (SurfaceType_GetSlope(&play->colCtx, floorPoly, this->actor.floorBgId) == 1)) { playerVelYaw = Math_Atan2S(this->actor.velocity.z, this->actor.velocity.x); Player_GetSlopeDirection(floorPoly, &slopeNormal, &downwardSlopeYaw); @@ -6533,14 +6671,14 @@ s32 Player_HandleSlopes(PlayState* play, Player* this, CollisionPoly* floorPoly) Math_StepToF(&this->pushedSpeed, slopeSlowdownSpeed, slopeSlowdownSpeedStep); } else { // moving downward on the slope, causing player to slip - Player_SetupAction(play, this, func_8084F390, 0); + Player_SetupAction(play, this, Player_Action_8084F390, 0); func_80832564(play, this); if (sFloorShapePitch >= 0) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; } - Player_AnimChangeLoopMorph(play, this, sSlopeSlipAnims[this->unk_84F]); + Player_AnimChangeLoopMorph(play, this, sSlopeSlipAnims[this->av1.actionVar1]); this->linearVelocity = sqrtf(SQ(this->actor.velocity.x) + SQ(this->actor.velocity.z)); - this->currentYaw = playerVelYaw; + this->yaw = playerVelYaw; return true; } } @@ -6607,7 +6745,7 @@ void Player_SetPendingFlag(Player* this, PlayState* play) { this->pendingFlag.flagID = 0; } -s32 func_8083E5A8(Player* this, PlayState* play) { +s32 Player_ActionChange_2(Player* this, PlayState* play) { Actor* interactedActor; if(gSaveContext.pendingIceTrapCount) { @@ -6725,7 +6863,7 @@ s32 func_8083E5A8(Player* this, PlayState* play) { chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); this->actor.world.pos.z = chest->dyna.actor.world.pos.z - (Math_CosS(chest->dyna.actor.shape.rot.y) * 29.4343f); - this->currentYaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y; func_80832224(this); if ((giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) && @@ -6779,7 +6917,7 @@ s32 func_8083E5A8(Player* this, PlayState* play) { } void func_8083EA94(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80846578, 1); + Player_SetupAction(play, this, Player_Action_80846578, 1); Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_throw, this->modelAnimType)); } @@ -6792,7 +6930,7 @@ s32 func_8083EAF0(Player* this, Actor* actor) { return 1; } -s32 func_8083EB44(Player* this, PlayState* play) { +s32 Player_ActionChange_9(Player* this, PlayState* play) { u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; if (CVarGetInteger("gDpadEquips", 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; @@ -6801,7 +6939,7 @@ s32 func_8083EB44(Player* this, PlayState* play) { CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) { if (!func_80835644(play, this, this->heldActor)) { if (!func_8083EAF0(this, this->heldActor)) { - Player_SetupAction(play, this, func_808464B0, 1); + Player_SetupAction(play, this, Player_Action_808464B0, 1); Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_put, this->modelAnimType)); } else { func_8083EA94(this, play); @@ -6886,24 +7024,24 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) { this->stateFlags1 &= ~PLAYER_STATE1_IN_WATER; if ((sp8C != 0) || (wallFlags & 2)) { - if ((this->unk_84F = sp8C) != 0) { + if ((this->av1.actionVar1 = sp8C) != 0) { if (this->actor.bgCheckFlags & 1) { anim = &gPlayerAnim_link_normal_Fclimb_startA; } else { anim = &gPlayerAnim_link_normal_Fclimb_hold2upL; } - sp34 = (this->ageProperties->unk_38 - 1.0f) - sp34; + sp34 = (this->ageProperties->wallCheckRadius - 1.0f) - sp34; } else { anim = this->ageProperties->unk_A4; sp34 = sp34 - 1.0f; } - this->unk_850 = -2; + this->av2.actionVar2 = -2; this->actor.world.pos.y += phi_f20; - this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw + 0x8000; + this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; } else { anim = this->ageProperties->unk_A8; - this->unk_850 = -4; - this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw; + this->av2.actionVar2 = -4; + this->actor.shape.rot.y = this->yaw = this->actor.wallYaw; } this->actor.world.pos.x = (sp34 * wallPolyNormalX) + sp80; @@ -6923,7 +7061,7 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) { } void func_8083F070(Player* this, LinkAnimationHeader* anim, PlayState* play) { - func_80835DAC(play, this, func_8084C5F8, 0); + func_80835DAC(play, this, Player_Action_8084C5F8, 0); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, (4.0f / 3.0f)); } @@ -6985,7 +7123,7 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall func_80836898(play, this, func_8083A40C); this->stateFlags2 |= PLAYER_STATE2_CRAWLING; - this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw + 0x8000; + this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; this->actor.world.pos.x = xVertex1 + (distToInteractWall * wallPolyNormX); this->actor.world.pos.z = zVertex1 + (distToInteractWall * wallPolyNormZ); func_80832224(this); @@ -7046,7 +7184,7 @@ s32 func_8083F360(PlayState* play, Player* this, f32 arg1, f32 arg2, f32 arg3, f temp = Math_Atan2S(-temp2, -temp1); Math_ScaledStepToS(&this->actor.shape.rot.y, temp, 800); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; this->actor.world.pos.x = sp54.x - (Math_SinS(this->actor.shape.rot.y) * arg2); this->actor.world.pos.z = sp54.z - (Math_CosS(this->actor.shape.rot.y) * arg2); @@ -7059,7 +7197,7 @@ s32 func_8083F360(PlayState* play, Player* this, f32 arg1, f32 arg2, f32 arg3, f } s32 func_8083F524(PlayState* play, Player* this) { - return func_8083F360(play, this, 26.0f, this->ageProperties->unk_38 + 5.0f, 30.0f, 0.0f); + return func_8083F360(play, this, 26.0f, this->ageProperties->wallCheckRadius + 5.0f, 30.0f, 0.0f); } /** @@ -7079,7 +7217,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { } if (ABS(temp) > 0x4000) { - Player_SetupAction(play, this, func_8084C81C, 0); + Player_SetupAction(play, this, Player_Action_8084C81C, 0); if (this->linearVelocity > 0.0f) { this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; @@ -7118,7 +7256,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { } } - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; Player_ZeroSpeedXZ(this); return 1; @@ -7130,16 +7268,16 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { void func_8083F72C(Player* this, LinkAnimationHeader* anim, PlayState* play) { if (!func_80836898(play, this, func_8083A388)) { - Player_SetupAction(play, this, func_8084B78C, 0); + Player_SetupAction(play, this, Player_Action_8084B78C, 0); } Player_AnimPlayOnce(play, this, anim); func_80832224(this); - this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw + 0x8000; + this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; } -s32 func_8083F7BC(Player* this, PlayState* play) { +s32 Player_ActionChange_5(Player* this, PlayState* play) { DynaPolyActor* wallPolyActor; if (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) { @@ -7169,7 +7307,7 @@ s32 func_8083F7BC(Player* this, PlayState* play) { this->interactRangeActor = &wallPolyActor->actor; this->getItemId = GI_NONE; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; - this->currentYaw = this->actor.wallYaw + 0x8000; + this->yaw = this->actor.wallYaw + 0x8000; func_80832224(this); return 1; @@ -7215,13 +7353,13 @@ s32 func_8083F9D0(PlayState* play, Player* this) { } void func_8083FAB8(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084B898, 0); + Player_SetupAction(play, this, Player_Action_8084B898, 0); this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY; Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_push_start); } void func_8083FB14(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084B9E4, 0); + Player_SetupAction(play, this, Player_Action_8084B9E4, 0); this->stateFlags2 |= PLAYER_STATE2_MOVING_DYNAPOLY; Player_AnimPlayOnce(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_pull_start, this->modelAnimType)); } @@ -7264,7 +7402,7 @@ s32 func_8083FC68(Player* this, f32 arg1, s16 arg2) { } s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) { - s16 sp2E = *arg2 - this->targetYaw; + s16 sp2E = *arg2 - this->zTargetYaw; u16 sp2C = ABS(sp2E); if ((func_8002DD78(this) || func_808334B4(this)) && (this->unk_664 == NULL)) { @@ -7429,9 +7567,9 @@ void func_8084029C(Player* this, f32 arg1) { } } -void func_80840450(Player* this, PlayState* play) { - f32 sp44; - s16 sp42; +void Player_Action_80840450(Player* this, PlayState* play) { + f32 speedTarget; + s16 yawTarget; s32 temp1; u32 temp2; s16 temp3; @@ -7445,11 +7583,11 @@ void func_80840450(Player* this, PlayState* play) { } } - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80832DBC(this); Player_AnimPlayLoop(play, this, func_808334E4(this)); - this->unk_850 = 0; + this->av2.actionVar2 = 0; this->stateFlags3 &= ~PLAYER_STATE3_FINISHED_ATTACKING; } func_80833C3C(this); @@ -7459,33 +7597,33 @@ void func_80840450(Player* this, PlayState* play) { func_8083721C(this); - if (!Player_TryActionChangeList(play, this, D_808543E0, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList1, true)) { if (!func_80833B54(this) && (!func_80833B2C(this) || (func_80834B5C != this->upperActionFunc))) { func_8083CF10(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp44, &sp42, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); - temp1 = func_8083FC68(this, sp44, sp42); + temp1 = func_8083FC68(this, speedTarget, yawTarget); if (temp1 > 0) { - func_8083C8DC(this, play, sp42); + func_8083C8DC(this, play, yawTarget); return; } if (temp1 < 0) { - func_8083CBF0(this, sp42, play); + func_8083CBF0(this, yawTarget, play); return; } - if (sp44 > 4.0f) { + if (speedTarget > 4.0f) { func_8083CC9C(this, play); return; } func_8084029C(this, (this->linearVelocity * 0.3f) + 1.0f); - func_80840138(this, sp44, sp42); + func_80840138(this, speedTarget, yawTarget); temp2 = this->unk_868; if ((temp2 < 6) || ((temp2 - 0xE) < 6)) { @@ -7493,27 +7631,27 @@ void func_80840450(Player* this, PlayState* play) { return; } - temp3 = sp42 - this->currentYaw; + temp3 = yawTarget - this->yaw; temp4 = ABS(temp3); if (temp4 > 0x4000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 1.5f)) { - this->currentYaw = sp42; + this->yaw = yawTarget; } return; } - Math_AsymStepToF(&this->linearVelocity, sp44 * 0.3f, 2.0f, 1.5f); + Math_AsymStepToF(&this->linearVelocity, speedTarget * 0.3f, 2.0f, 1.5f); if (!(this->stateFlags3 & PLAYER_STATE3_FINISHED_ATTACKING)) { - Math_ScaledStepToS(&this->currentYaw, sp42, temp4 * 0.1f); + Math_ScaledStepToS(&this->yaw, yawTarget, temp4 * 0.1f); } } } -void func_808407CC(Player* this, PlayState* play) { - f32 sp3C; - s16 sp3A; +void Player_Action_808407CC(Player* this, PlayState* play) { + f32 speedTarget; + s16 yawTarget; s32 temp1; s16 temp2; s32 temp3; @@ -7525,15 +7663,15 @@ void func_808407CC(Player* this, PlayState* play) { func_8083721C(this); - if (!Player_TryActionChangeList(play, this, D_808543E8, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList2, true)) { if (func_80833B54(this)) { func_8083CEAC(this, play); return; } if (!func_80833B2C(this)) { - func_80835DAC(play, this, func_80840BC8, 1); - this->currentYaw = this->actor.shape.rot.y; + func_80835DAC(play, this, Player_Action_80840BC8, 1); + this->yaw = this->actor.shape.rot.y; return; } @@ -7542,35 +7680,35 @@ void func_808407CC(Player* this, PlayState* play) { return; } - Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); - temp1 = func_8083FD78(this, &sp3C, &sp3A, play); + temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play); if (temp1 > 0) { - func_8083C8DC(this, play, sp3A); + func_8083C8DC(this, play, yawTarget); return; } if (temp1 < 0) { - func_8083CB2C(this, sp3A, play); + func_8083CB2C(this, yawTarget, play); return; } - if (sp3C > 4.9f) { + if (speedTarget > 4.9f) { func_8083CC9C(this, play); func_80833C3C(this); return; } - if (sp3C != 0.0f) { + if (speedTarget != 0.0f) { func_8083CB94(this, play); return; } - temp2 = sp3A - this->actor.shape.rot.y; + temp2 = yawTarget - this->actor.shape.rot.y; temp3 = ABS(temp2); if (temp3 > 800) { - func_8083CD54(play, this, sp3A); + func_8083CD54(play, this, yawTarget); } } } @@ -7623,11 +7761,11 @@ void func_808409CC(PlayState* play, Player* this) { Animation_GetLastFrame(anim), ANIMMODE_ONCE, -6.0f); } -void func_80840BC8(Player* this, PlayState* play) { +void Player_Action_80840BC8(Player* this, PlayState* play) { s32 sp44; s32 sp40; - f32 sp3C; - s16 sp3A; + f32 speedTarget; + s16 yawTarget; s16 temp; sp44 = func_80833350(this); @@ -7638,11 +7776,11 @@ void func_80840BC8(Player* this, PlayState* play) { } if (sp40 != 0) { - if (this->unk_850 != 0) { - if (DECR(this->unk_850) == 0) { + if (this->av2.actionVar2 != 0) { + if (DECR(this->av2.actionVar2) == 0) { this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; } - this->skelAnime.jointTable[0].y = (this->skelAnime.jointTable[0].y + ((this->unk_850 & 1) * 0x50)) - 0x28; + this->skelAnime.jointTable[0].y = (this->skelAnime.jointTable[0].y + ((this->av2.actionVar2 & 1) * 0x50)) - 0x28; } else { func_80832DBC(this); func_808409CC(play, this); @@ -7651,8 +7789,8 @@ void func_80840BC8(Player* this, PlayState* play) { func_8083721C(this); - if (this->unk_850 == 0) { - if (!Player_TryActionChangeList(play, this, D_80854418, 1)) { + if (this->av2.actionVar2 == 0) { + if (!Player_TryActionChangeList(play, this, sActionChangeList7, true)) { if (func_80833B54(this)) { func_8083CEAC(this, play); return; @@ -7663,21 +7801,21 @@ void func_80840BC8(Player* this, PlayState* play) { return; } - Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, 0.018f, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play); - if (sp3C != 0.0f) { - func_8083C8DC(this, play, sp3A); + if (speedTarget != 0.0f) { + func_8083C8DC(this, play, yawTarget); return; } - temp = sp3A - this->actor.shape.rot.y; + temp = yawTarget - this->actor.shape.rot.y; if (ABS(temp) > 800) { - func_8083CD54(play, this, sp3A); + func_8083CD54(play, this, yawTarget); return; } - Math_ScaledStepToS(&this->actor.shape.rot.y, sp3A, 1200); - this->currentYaw = this->actor.shape.rot.y; + Math_ScaledStepToS(&this->actor.shape.rot.y, yawTarget, 1200); + this->yaw = this->actor.shape.rot.y; if (func_80833338(this) == this->skelAnime.animation) { func_8083DC54(this, play); } @@ -7685,11 +7823,11 @@ void func_80840BC8(Player* this, PlayState* play) { } } -void func_80840DE4(Player* this, PlayState* play) { +void Player_Action_80840DE4(Player* this, PlayState* play) { f32 frames; f32 coeff; - f32 sp44; - s16 sp42; + f32 speedTarget; + s16 yawTarget; s32 temp1; s16 temp2; s32 temp3; @@ -7711,7 +7849,7 @@ void func_80840DE4(Player* this, PlayState* play) { this->skelAnime.animLength = frames; this->skelAnime.endFrame = frames - 1.0f; - if ((s16)(this->currentYaw - this->actor.shape.rot.y) >= 0) { + if ((s16)(this->yaw - this->actor.shape.rot.y) >= 0) { direction = 1; } else { direction = -1; @@ -7725,7 +7863,7 @@ void func_80840DE4(Player* this, PlayState* play) { func_808327F8(this, this->linearVelocity); } - if (!Player_TryActionChangeList(play, this, D_808543F4, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList3, true)) { if (func_80833B54(this)) { func_8083CEAC(this, play); return; @@ -7736,42 +7874,42 @@ void func_80840DE4(Player* this, PlayState* play) { return; } - Player_GetMovementSpeedAndYaw(this, &sp44, &sp42, 0.0f, play); - temp1 = func_8083FD78(this, &sp44, &sp42, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); + temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play); if (temp1 > 0) { - func_8083C8DC(this, play, sp42); + func_8083C8DC(this, play, yawTarget); return; } if (temp1 < 0) { - func_8083CB2C(this, sp42, play); + func_8083CB2C(this, yawTarget, play); return; } - if (sp44 > 4.9f) { + if (speedTarget > 4.9f) { func_8083CC9C(this, play); func_80833C3C(this); return; } - if ((sp44 == 0.0f) && (this->linearVelocity == 0.0f)) { + if ((speedTarget == 0.0f) && (this->linearVelocity == 0.0f)) { func_80839F30(this, play); return; } - temp2 = sp42 - this->currentYaw; + temp2 = yawTarget - this->yaw; temp3 = ABS(temp2); if (temp3 > 0x4000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 1.5f)) { - this->currentYaw = sp42; + this->yaw = yawTarget; } return; } - Math_AsymStepToF(&this->linearVelocity, sp44 * 0.4f, 1.5f, 1.5f); - Math_ScaledStepToS(&this->currentYaw, sp42, temp3 * 0.1f); + Math_AsymStepToF(&this->linearVelocity, speedTarget * 0.4f, 1.5f, 1.5f); + Math_ScaledStepToS(&this->yaw, yawTarget, temp3 * 0.1f); } } @@ -7817,7 +7955,7 @@ void func_80841138(Player* this, PlayState* play) { } void func_8084140C(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084170C, 1); + Player_SetupAction(play, this, Player_Action_8084170C, 1); Player_AnimChangeOnceMorph(play, this, &gPlayerAnim_link_normal_back_brake); } @@ -7830,7 +7968,7 @@ s32 func_80841458(Player* this, f32* arg1, s16* arg2, PlayState* play) { if (*arg1 != 0.0f) { if (func_8083721C(this)) { *arg1 = 0.0f; - *arg2 = this->currentYaw; + *arg2 = this->yaw; } else { return 1; } @@ -7839,40 +7977,40 @@ s32 func_80841458(Player* this, f32* arg1, s16* arg2, PlayState* play) { return 0; } -void func_808414F8(Player* this, PlayState* play) { - f32 sp34; - s16 sp32; +void Player_Action_808414F8(Player* this, PlayState* play) { + f32 speedTarget; + s16 yawTarget; s32 sp2C; s16 sp2A; func_80841138(this, play); - if (!Player_TryActionChangeList(play, this, D_80854400, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) { if (!func_80833C04(this)) { - func_8083C8DC(this, play, this->currentYaw); + func_8083C8DC(this, play, this->yaw); return; } - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); - sp2C = func_8083FD78(this, &sp34, &sp32, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); + sp2C = func_8083FD78(this, &speedTarget, &yawTarget, play); if (sp2C >= 0) { - if (!func_80841458(this, &sp34, &sp32, play)) { + if (!func_80841458(this, &speedTarget, &yawTarget, play)) { if (sp2C != 0) { func_8083C858(this, play); - } else if (sp34 > 4.9f) { + } else if (speedTarget > 4.9f) { func_8083CC9C(this, play); } else { func_8083CB94(this, play); } } } else { - sp2A = sp32 - this->currentYaw; + sp2A = yawTarget - this->yaw; - Math_AsymStepToF(&this->linearVelocity, sp34 * 1.5f, 1.5f, 2.0f); - Math_ScaledStepToS(&this->currentYaw, sp32, sp2A * 0.1f); + Math_AsymStepToF(&this->linearVelocity, speedTarget * 1.5f, 1.5f, 2.0f); + Math_ScaledStepToS(&this->yaw, yawTarget, sp2A * 0.1f); - if ((sp34 == 0.0f) && (this->linearVelocity == 0.0f)) { + if ((speedTarget == 0.0f) && (this->linearVelocity == 0.0f)) { func_80839F30(this, play); } } @@ -7880,39 +8018,39 @@ void func_808414F8(Player* this, PlayState* play) { } void func_808416C0(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_808417FC, 1); + Player_SetupAction(play, this, Player_Action_808417FC, 1); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_back_brake_end); } -void func_8084170C(Player* this, PlayState* play) { +void Player_Action_8084170C(Player* this, PlayState* play) { s32 sp34; - f32 sp30; - s16 sp2E; + f32 speedTarget; + s16 yawTarget; sp34 = LinkAnimation_Update(play, &this->skelAnime); func_8083721C(this); - if (!Player_TryActionChangeList(play, this, D_80854400, 1)) { - Player_GetMovementSpeedAndYaw(this, &sp30, &sp2E, 0.0f, play); + if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) { + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); if (this->linearVelocity == 0.0f) { - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; - if (func_8083FD78(this, &sp30, &sp2E, play) > 0) { + if (func_8083FD78(this, &speedTarget, &yawTarget, play) > 0) { func_8083C858(this, play); - } else if ((sp30 != 0.0f) || (sp34 != 0)) { + } else if ((speedTarget != 0.0f) || (sp34 != 0)) { func_808416C0(this, play); } } } } -void func_808417FC(Player* this, PlayState* play) { +void Player_Action_808417FC(Player* this, PlayState* play) { s32 sp1C; sp1C = LinkAnimation_Update(play, &this->skelAnime); - if (!Player_TryActionChangeList(play, this, D_80854400, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList4, true)) { if (sp1C != 0) { func_80839F30(this, play); } @@ -7933,27 +8071,27 @@ void func_80841860(PlayState* play, Player* this) { LinkAnimation_BlendToJoint(play, &this->skelAnime, sp34, frame, sp38, frame, this->unk_870, this->blendTable); } -void func_8084193C(Player* this, PlayState* play) { - f32 sp3C; - s16 sp3A; +void Player_Action_8084193C(Player* this, PlayState* play) { + f32 speedTarget; + s16 yawTarget; s32 temp1; s16 temp2; s32 temp3; func_80841860(play, this); - if (!Player_TryActionChangeList(play, this, D_80854408, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList5, true)) { if (!func_80833C04(this)) { func_8083C858(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); if (func_80833B2C(this)) { - temp1 = func_8083FD78(this, &sp3C, &sp3A, play); + temp1 = func_8083FD78(this, &speedTarget, &yawTarget, play); } else { - temp1 = func_8083FC68(this, sp3C, sp3A); + temp1 = func_8083FC68(this, speedTarget, yawTarget); } if (temp1 > 0) { @@ -7963,14 +8101,14 @@ void func_8084193C(Player* this, PlayState* play) { if (temp1 < 0) { if (func_80833B2C(this)) { - func_8083CB2C(this, sp3A, play); + func_8083CB2C(this, yawTarget, play); } else { - func_8083CBF0(this, sp3A, play); + func_8083CBF0(this, yawTarget, play); } return; } - if ((this->linearVelocity < 3.6f) && (sp3C < 4.0f)) { + if ((this->linearVelocity < 3.6f) && (speedTarget < 4.0f)) { if (!func_8008E9C4(this) && func_80833B2C(this)) { func_8083CB94(this, play); } else { @@ -7979,25 +8117,25 @@ void func_8084193C(Player* this, PlayState* play) { return; } - func_80840138(this, sp3C, sp3A); + func_80840138(this, speedTarget, yawTarget); - temp2 = sp3A - this->currentYaw; + temp2 = yawTarget - this->yaw; temp3 = ABS(temp2); if (temp3 > 0x4000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 3.0f) != 0) { - this->currentYaw = sp3A; + this->yaw = yawTarget; } return; } - sp3C *= 0.9f; - Math_AsymStepToF(&this->linearVelocity, sp3C, 2.0f, 3.0f); - Math_ScaledStepToS(&this->currentYaw, sp3A, temp3 * 0.1f); + speedTarget *= 0.9f; + Math_AsymStepToF(&this->linearVelocity, speedTarget, 2.0f, 3.0f); + Math_ScaledStepToS(&this->yaw, yawTarget, temp3 * 0.1f); } } -void func_80841BA8(Player* this, PlayState* play) { +void Player_Action_80841BA8(Player* this, PlayState* play) { f32 sp34; s16 sp32; @@ -8010,9 +8148,9 @@ void func_80841BA8(Player* this, PlayState* play) { this->skelAnime.morphTable, sUpperBodyLimbCopyMap); } - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.018f, play); + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_CURVED, play); - if (!Player_TryActionChangeList(play, this, D_80854414, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList6, true)) { if (sp34 != 0.0f) { this->actor.shape.rot.y = sp32; func_8083C858(this, play); @@ -8020,7 +8158,7 @@ void func_80841BA8(Player* this, PlayState* play) { func_8083C0E8(this, play); } - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } } @@ -8122,20 +8260,20 @@ void func_80841EE4(Player* this, PlayState* play) { } } -void func_80842180(Player* this, PlayState* play) { +void Player_Action_80842180(Player* this, PlayState* play) { f32 sp2C; s16 sp2A; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; func_80841EE4(this, play); - if (!Player_TryActionChangeList(play, this, D_80854424, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList8, true)) { if (func_80833C04(this)) { func_8083C858(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.018f, play); + Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play); if (!func_8083C484(this, &sp2C, &sp2A)) { int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); @@ -8177,20 +8315,20 @@ void func_80842180(Player* this, PlayState* play) { } } -void func_8084227C(Player* this, PlayState* play) { +void Player_Action_8084227C(Player* this, PlayState* play) { f32 sp2C; s16 sp2A; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; func_80841EE4(this, play); - if (!Player_TryActionChangeList(play, this, D_80854430, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList9, true)) { if (!func_80833C04(this)) { func_8083C858(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play); if (!func_8083C484(this, &sp2C, &sp2A)) { if ((func_80833B2C(this) && (sp2C != 0.0f) && (func_8083FD78(this, &sp2C, &sp2A, play) <= 0)) || @@ -8209,20 +8347,20 @@ void func_8084227C(Player* this, PlayState* play) { } } -void func_808423EC(Player* this, PlayState* play) { +void Player_Action_808423EC(Player* this, PlayState* play) { s32 sp34; f32 sp30; s16 sp2E; sp34 = LinkAnimation_Update(play, &this->skelAnime); - if (!Player_TryActionChangeList(play, this, D_80854408, 1)) { + if (!Player_TryActionChangeList(play, this, sActionChangeList5, true)) { if (!func_80833C04(this)) { func_8083C858(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp30, &sp2E, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp30, &sp2E, SPEED_MODE_LINEAR, play); if ((this->skelAnime.morphWeight == 0.0f) && (this->skelAnime.curFrame > 5.0f)) { func_8083721C(this); @@ -8239,27 +8377,27 @@ void func_808423EC(Player* this, PlayState* play) { } } -void func_8084251C(Player* this, PlayState* play) { +void Player_Action_8084251C(Player* this, PlayState* play) { s32 sp34; - f32 sp30; - s16 sp2E; + f32 speedTarget; + s16 yawTarget; sp34 = LinkAnimation_Update(play, &this->skelAnime); func_8083721C(this); - if (!Player_TryActionChangeList(play, this, D_80854440, 1)) { - Player_GetMovementSpeedAndYaw(this, &sp30, &sp2E, 0.0f, play); + if (!Player_TryActionChangeList(play, this, sActionChangeList10, true)) { + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_LINEAR, play); if (this->linearVelocity == 0.0f) { - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; - if (func_8083FC68(this, sp30, sp2E) > 0) { + if (func_8083FC68(this, speedTarget, yawTarget) > 0) { func_8083C858(this, play); return; } - if ((sp30 != 0.0f) || (sp34 != 0)) { + if ((speedTarget != 0.0f) || (sp34 != 0)) { func_80839F90(this, play); } } @@ -8291,11 +8429,11 @@ s32 func_8084269C(PlayState* play, Player* this) { return 0; } -void func_8084279C(Player* this, PlayState* play) { +void Player_Action_8084279C(Player* this, PlayState* play) { func_80832CB0(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check_wait, this->modelAnimType)); - if (DECR(this->unk_850) == 0) { - if (!func_8083B040(this, play)) { + if (DECR(this->av2.actionVar2) == 0) { + if (!Player_ActionChange_13(this, play)) { func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_check_end, this->modelAnimType), play); } @@ -8320,9 +8458,9 @@ s32 func_808428D8(Player* this, PlayState* play) { } Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_defense_kiru); - this->unk_84F = 1; + this->av1.actionVar1 = 1; this->meleeWeaponAnimation = PLAYER_MWA_STAB_1H; - this->currentYaw = this->actor.shape.rot.y + this->unk_6BE; + this->yaw = this->actor.shape.rot.y + this->unk_6BE; if (!CVarGetInteger("gCrouchStabHammerFix", 0)) { return 1; @@ -8347,22 +8485,22 @@ s32 func_808428D8(Player* this, PlayState* play) { } s32 func_80842964(Player* this, PlayState* play) { - return func_8083B040(this, play) || func_8083B644(this, play) || func_8083E5A8(this, play); + return Player_ActionChange_13(this, play) || Player_ActionChange_4(this, play) || Player_ActionChange_2(this, play); } void Player_RequestQuake(PlayState* play, s32 speed, s32 y, s32 countdown) { - s32 quakeIdx = Quake_Add(Play_GetCamera(play, 0), 3); + s32 quakeIndex = Quake_Add(Play_GetCamera(play, 0), 3); - Quake_SetSpeed(quakeIdx, speed); - Quake_SetQuakeValues(quakeIdx, y, 0, 0, 0); - Quake_SetCountdown(quakeIdx, countdown); + Quake_SetSpeed(quakeIndex, speed); + Quake_SetQuakeValues(quakeIndex, y, 0, 0, 0); + Quake_SetCountdown(quakeIndex, countdown); } void func_80842A28(PlayState* play, Player* this) { Player_RequestQuake(play, 27767, 7, 20); play->actorCtx.unk_02 = 4; Player_RequestRumble(this, 255, 20, 150, 0); - Player_PlaySfx(&this->actor, NA_SE_IT_HAMMER_HIT); + Player_PlaySfx(this, NA_SE_IT_HAMMER_HIT); } void func_80842A88(PlayState* play, Player* this) { @@ -8379,7 +8517,7 @@ s32 func_80842AC4(PlayState* play, Player* this) { this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; func_80842A88(play, this); - Player_PlaySfx(&this->actor, NA_SE_IT_WOODSTICK_BROKEN); + Player_PlaySfx(this, NA_SE_IT_WOODSTICK_BROKEN); } return 1; @@ -8395,7 +8533,7 @@ s32 func_80842B7C(PlayState* play, Player* this) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); func_800849EC(play); - Player_PlaySfx(&this->actor, NA_SE_IT_MAJIN_SWORD_BROKEN); + Player_PlaySfx(this, NA_SE_IT_MAJIN_SWORD_BROKEN); } } @@ -8421,9 +8559,9 @@ void func_80842D20(PlayState* play, Player* this) { s32 pad; s32 sp28; - if (func_80843188 != this->actionFunc) { + if (Player_Action_80843188 != this->actionFunc) { func_80832440(play, this); - Player_SetupAction(play, this, func_808505DC, 0); + Player_SetupAction(play, this, Player_Action_808505DC, 0); if (func_8008E9C4(this)) { sp28 = 2; @@ -8484,9 +8622,9 @@ s32 func_80842DF4(PlayState* play, Player* this) { } else { CollisionCheck_SpawnShieldParticles(play, &sp5C); if (sp48 == 0xB) { - Player_PlaySfx(&this->actor, NA_SE_IT_WALL_HIT_SOFT); + Player_PlaySfx(this, NA_SE_IT_WALL_HIT_SOFT); } else { - Player_PlaySfx(&this->actor, NA_SE_IT_WALL_HIT_HARD); + Player_PlaySfx(this, NA_SE_IT_WALL_HIT_HARD); } } @@ -8529,7 +8667,7 @@ s32 func_80842DF4(PlayState* play, Player* this) { return 0; } -void func_80843188(Player* this, PlayState* play) { +void Player_Action_80843188(Player* this, PlayState* play) { f32 sp54; f32 sp50; s16 sp4E; @@ -8543,8 +8681,8 @@ void func_80843188(Player* this, PlayState* play) { if (!Player_IsChildWithHylianShield(this)) { Player_AnimPlayLoop(play, this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense_wait, this->modelAnimType)); } - this->unk_850 = 1; - this->unk_84F = 0; + this->av2.actionVar2 = 1; + this->av1.actionVar1 = 0; } if (!Player_IsChildWithHylianShield(this)) { @@ -8555,7 +8693,7 @@ void func_80843188(Player* this, PlayState* play) { func_8083721C(this); - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { sp54 = sControlInput->rel.stick_y * 100 * (CVarGetInteger("gInvertShieldAimingYAxis", 1) ? 1 : -1); sp50 = sControlInput->rel.stick_x * (CVarGetInteger("gMirroredWorld", 0) ? 120 : -120) * (CVarGetInteger("gInvertShieldAimingXAxis", 0) ? -1 : 1); sp4E = this->actor.shape.rot.y - Camera_GetInputDirYaw(GET_ACTIVE_CAM(play)); @@ -8583,17 +8721,17 @@ void func_80843188(Player* this, PlayState* play) { this->unk_6BC = this->actor.focus.rot.x; Math_ScaledStepToS(&this->unk_6BE, sp4A, sp46); - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { if (!func_80842DF4(play, this)) { if (this->skelAnime.curFrame < 2.0f) { func_80833A20(this, 1); } } else { - this->unk_850 = 1; - this->unk_84F = 0; + this->av2.actionVar2 = 1; + this->av1.actionVar1 = 0; } } else if (!func_80842964(this, play)) { - if (func_8083C2B0(this, play)) { + if (Player_ActionChange_11(this, play)) { func_808428D8(this, play); } else { this->stateFlags1 &= ~PLAYER_STATE1_SHIELDING; @@ -8612,7 +8750,7 @@ void func_80843188(Player* this, PlayState* play) { func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense_end, this->modelAnimType), play); } - Player_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REMOVE); + Player_PlaySfx(this, NA_SE_IT_SHIELD_REMOVE); return; } } else { @@ -8626,22 +8764,22 @@ void func_80843188(Player* this, PlayState* play) { this->unk_6AE |= 0xC1; } -void func_808435C4(Player* this, PlayState* play) { +void Player_Action_808435C4(Player* this, PlayState* play) { s32 temp; LinkAnimationHeader* anim; f32 frames; func_8083721C(this); - if (this->unk_84F == 0) { + if (this->av1.actionVar1 == 0) { D_808535E0 = Player_UpdateUpperBody(this, play); if ((func_80834B5C == this->upperActionFunc) || (func_808374A0(play, this, &this->upperSkelAnime, 4.0f) > 0)) { - Player_SetupAction(play, this, func_80840450, 1); + Player_SetupAction(play, this, Player_Action_80840450, 1); } } else { temp = func_808374A0(play, this, &this->skelAnime, 4.0f); if ((temp != 0) && ((temp > 0) || LinkAnimation_Update(play, &this->skelAnime))) { - Player_SetupAction(play, this, func_80843188, 1); + Player_SetupAction(play, this, Player_Action_80843188, 1); this->stateFlags1 |= PLAYER_STATE1_SHIELDING; Player_SetModelsForHoldingShield(this); anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_defense, this->modelAnimType); @@ -8651,7 +8789,7 @@ void func_808435C4(Player* this, PlayState* play) { } } -void func_8084370C(Player* this, PlayState* play) { +void Player_Action_8084370C(Player* this, PlayState* play) { s32 sp1C; func_8083721C(this); @@ -8662,15 +8800,15 @@ void func_8084370C(Player* this, PlayState* play) { } } -void func_8084377C(Player* this, PlayState* play) { +void Player_Action_8084377C(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; func_808382BC(this); - if (!(this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) && (this->unk_850 == 0) && (this->unk_8A1 != 0)) { + if (!(this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) && (this->av2.actionVar2 == 0) && (this->unk_8A1 != 0)) { s16 temp = this->actor.shape.rot.y - this->unk_8A2; - this->currentYaw = this->actor.shape.rot.y = this->unk_8A2; + this->yaw = this->actor.shape.rot.y = this->unk_8A2; this->linearVelocity = this->unk_8A4; if (ABS(temp) > 0x4000) { @@ -8684,22 +8822,22 @@ void func_8084377C(Player* this, PlayState* play) { } if (LinkAnimation_Update(play, &this->skelAnime) && (this->actor.bgCheckFlags & 1)) { - if (this->unk_850 != 0) { - this->unk_850--; - if (this->unk_850 == 0) { + if (this->av2.actionVar2 != 0) { + this->av2.actionVar2--; + if (this->av2.actionVar2 == 0) { func_80853080(this, play); } } else if ((this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) || (!(this->cylinder.base.acFlags & AC_HIT) && (this->unk_8A1 == 0))) { if (this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) { - this->unk_850++; + this->av2.actionVar2++; } else { - Player_SetupAction(play, this, func_80843954, 0); + Player_SetupAction(play, this, Player_Action_80843954, 0); this->stateFlags1 |= PLAYER_STATE1_DAMAGED; } Player_AnimPlayOnce(play, this, - (this->currentYaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_downB + (this->yaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_downB : &gPlayerAnim_link_normal_back_downB); func_80832698(this, NA_SE_VO_LI_FREEZE); } @@ -8710,7 +8848,7 @@ void func_8084377C(Player* this, PlayState* play) { } } -void func_80843954(Player* this, PlayState* play) { +void Player_Action_80843954(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; func_808382BC(this); @@ -8718,25 +8856,25 @@ void func_80843954(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime) && (this->linearVelocity == 0.0f)) { if (this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE) { - this->unk_850++; + this->av2.actionVar2++; } else { - Player_SetupAction(play, this, func_80843A38, 0); + Player_SetupAction(play, this, Player_Action_80843A38, 0); this->stateFlags1 |= PLAYER_STATE1_DAMAGED; } Player_AnimPlayOnceAdjusted(play, this, - (this->currentYaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_down_wake + (this->yaw != this->actor.shape.rot.y) ? &gPlayerAnim_link_normal_front_down_wake : &gPlayerAnim_link_normal_back_down_wake); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } } static AnimSfxEntry D_808545DC[] = { - { 0, 0x4014 }, - { 0, -0x401E }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 30) }, }; -void func_80843A38(Player* this, PlayState* play) { +void Player_Action_80843A38(Player* this, PlayState* play) { s32 sp24; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; @@ -8757,10 +8895,10 @@ void func_80843A38(Player* this, PlayState* play) { static Vec3f D_808545E4 = { 0.0f, 0.0f, 5.0f }; void func_80843AE8(PlayState* play, Player* this) { - if (this->unk_850 != 0) { - if (this->unk_850 > 0) { - this->unk_850--; - if (this->unk_850 == 0) { + if (this->av2.actionVar2 != 0) { + if (this->av2.actionVar2 > 0) { + this->av2.actionVar2--; + if (this->av2.actionVar2 == 0) { if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_swimer_swim_wait, 1.0f, 0.0f, Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_wait), ANIMMODE_ONCE, @@ -8779,7 +8917,7 @@ void func_80843AE8(PlayState* play, Player* this) { } else { gSaveContext.healthAccumulator = 0x140; } - this->unk_850 = -1; + this->av2.actionVar2 = -1; } } else if (gSaveContext.healthAccumulator == 0) { this->stateFlags1 &= ~PLAYER_STATE1_DEAD; @@ -8792,10 +8930,10 @@ void func_80843AE8(PlayState* play, Player* this) { func_80837AFC(this, -20); func_800F47FC(); } - } else if (this->unk_84F != 0) { - this->unk_850 = 60; + } else if (this->av1.actionVar1 != 0) { + this->av2.actionVar2 = 60; Player_SpawnFairy(play, this, &this->actor.world.pos, &D_808545E4, FAIRY_REVIVE_DEATH); - Player_PlaySfx(&this->actor, NA_SE_EV_FIATY_HEAL - SFX_FLAG); + Player_PlaySfx(this, NA_SE_EV_FIATY_HEAL - SFX_FLAG); OnePointCutscene_Init(play, 9908, 125, &this->actor, MAIN_CAM); } else if (play->gameOverCtx.state == GAMEOVER_DEATH_WAIT_GROUND) { play->gameOverCtx.state = GAMEOVER_DEATH_DELAY_MENU; @@ -8804,13 +8942,13 @@ void func_80843AE8(PlayState* play, Player* this) { } static AnimSfxEntry D_808545F0[] = { - { NA_SE_PL_BOUND, 0x103C }, - { 0, 0x408C }, - { 0, 0x40A4 }, - { 0, -0x40AA }, + { NA_SE_PL_BOUND, ANIMSFX_DATA(ANIMSFX_TYPE_2, 60) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 140) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 164) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 170) }, }; -void func_80843CEC(Player* this, PlayState* play) { +void Player_Action_80843CEC(Player* this, PlayState* play) { if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) { if ((play->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3) || (sFloorType == 9) || ((func_80838144(sFloorType) >= 0) && @@ -8882,8 +9020,8 @@ s32 func_80843E64(PlayState* play, Player* this) { func_80837AE0(this, 40); Player_RequestQuake(play, 32967, 2, 30); - Player_RequestRumble(this, impactInfo->unk_01, impactInfo->unk_02, impactInfo->unk_03, 0); - Player_PlaySfx(&this->actor, NA_SE_PL_BODY_HIT); + Player_RequestRumble(this, impactInfo->rumbleStrength, impactInfo->rumbleDuration, impactInfo->rumbleDecreaseRate, 0); + Player_PlaySfx(this, NA_SE_PL_BODY_HIT); func_80832698(this, impactInfo->sfxId); return impactIndex + 1; @@ -8916,12 +9054,12 @@ void func_8084409C(PlayState* play, Player* this, f32 speedXZ, f32 velocityY) { heldActor->speedXZ = speedXZ; heldActor->velocity.y = velocityY; func_80834644(play, this); - Player_PlaySfx(&this->actor, NA_SE_PL_THROW); + Player_PlaySfx(this, NA_SE_PL_THROW); func_80832698(this, NA_SE_VO_LI_SWORD_N); } } -void func_8084411C(Player* this, PlayState* play) { +void Player_Action_8084411C(Player* this, PlayState* play) { f32 sp4C; s16 sp4A; @@ -8931,7 +9069,7 @@ void func_8084411C(Player* this, PlayState* play) { this->actor.gravity = -1.2f; } - Player_GetMovementSpeedAndYaw(this, &sp4C, &sp4A, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp4C, &sp4A, SPEED_MODE_LINEAR, play); if (!(this->actor.bgCheckFlags & 1)) { if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { @@ -8955,10 +9093,10 @@ void func_8084411C(Player* this, PlayState* play) { Player_UpdateUpperBody(this, play); - if (((this->stateFlags2 & PLAYER_STATE2_HOPPING) && (this->unk_84F == 2)) || !func_8083BBA0(this, play)) { + if (((this->stateFlags2 & PLAYER_STATE2_HOPPING) && (this->av1.actionVar1 == 2)) || !func_8083BBA0(this, play)) { if (this->actor.velocity.y < 0.0f) { - if (this->unk_850 >= 0) { - if ((this->actor.bgCheckFlags & 8) || (this->unk_850 == 0) || (this->fallDistance > 0)) { + if (this->av2.actionVar2 >= 0) { + if ((this->actor.bgCheckFlags & 8) || (this->av2.actionVar2 == 0) || (this->fallDistance > 0)) { if ((sYDistToFloor > 800.0f) || (this->stateFlags1 & PLAYER_STATE1_HOOKSHOT_FALLING)) { func_80843E14(this, NA_SE_VO_LI_FALL_S); this->stateFlags1 &= ~PLAYER_STATE1_HOOKSHOT_FALLING; @@ -8966,11 +9104,11 @@ void func_8084411C(Player* this, PlayState* play) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_normal_landing, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, 8.0f); - this->unk_850 = -1; + this->av2.actionVar2 = -1; } } else { - if ((this->unk_850 == -1) && (this->fallDistance > 120.0f) && (sYDistToFloor > 280.0f)) { - this->unk_850 = -2; + if ((this->av2.actionVar2 == -1) && (this->fallDistance > 120.0f) && (sYDistToFloor > 280.0f)) { + this->av2.actionVar2 = -2; func_80843E14(this, NA_SE_VO_LI_FALL_L); } @@ -8979,7 +9117,7 @@ void func_8084411C(Player* this, PlayState* play) { !(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_WATER)) && (this->linearVelocity > 0.0f)) { if ((this->yDistToLedge >= 150.0f) && (this->unk_84B[this->unk_846] == 0)) { func_8083EC18(this, play, sTouchedWallFlags); - } else if ((this->unk_88C >= 2) && (this->yDistToLedge < 150.0f) && + } else if ((this->ledgeClimbType >= 2) && (this->yDistToLedge < 150.0f) && (((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) > (70.0f * this->ageProperties->unk_08))) { AnimationContext_DisableQueue(play); @@ -8991,7 +9129,7 @@ void func_8084411C(Player* this, PlayState* play) { this->actor.world.pos.y += this->yDistToLedge; func_8083A5C4(play, this, this->actor.wallPoly, this->distToInteractWall, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_hold, this->modelAnimType)); - this->actor.shape.rot.y = this->currentYaw += 0x8000; + this->actor.shape.rot.y = this->yaw += 0x8000; this->stateFlags1 |= PLAYER_STATE1_HANGING_OFF_LEDGE; } } @@ -9004,9 +9142,9 @@ void func_8084411C(Player* this, PlayState* play) { if (this->stateFlags2 & PLAYER_STATE2_HOPPING) { if (func_8008E9C4(this)) { - anim = D_80853D4C[this->unk_84F][2]; + anim = D_80853D4C[this->av1.actionVar1][2]; } else { - anim = D_80853D4C[this->unk_84F][1]; + anim = D_80853D4C[this->av1.actionVar1][1]; } } else if (this->skelAnime.animation == &gPlayerAnim_link_normal_run_jump) { anim = &gPlayerAnim_link_normal_run_jump_end; @@ -9027,9 +9165,9 @@ void func_8084411C(Player* this, PlayState* play) { func_8083A098(this, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing, this->modelAnimType), play); this->skelAnime.endFrame = 8.0f; if (sp3C == 1) { - this->unk_850 = 10; + this->av2.actionVar2 = 10; } else { - this->unk_850 = 20; + this->av2.actionVar2 = 20; } } else if (sp3C == 0) { func_8083A098(this, anim, play); @@ -9038,13 +9176,13 @@ void func_8084411C(Player* this, PlayState* play) { } static AnimSfxEntry D_8085460C[] = { - { NA_SE_VO_LI_SWORD_N, 0x2001 }, - { NA_SE_PL_WALK_GROUND, 0x1806 }, - { NA_SE_PL_ROLL, 0x806 }, - { 0, -0x2812 }, + { NA_SE_VO_LI_SWORD_N, ANIMSFX_DATA(ANIMSFX_TYPE_4, 1) }, + { NA_SE_PL_WALK_GROUND, ANIMSFX_DATA(ANIMSFX_TYPE_3, 6) }, + { NA_SE_PL_ROLL, ANIMSFX_DATA(ANIMSFX_TYPE_1, 6) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 18) }, }; -void func_80844708(Player* this, PlayState* play) { +void Player_Action_80844708(Player* this, PlayState* play) { Actor* cylinderOc; s32 temp; s32 sp44; @@ -9063,7 +9201,7 @@ void func_80844708(Player* this, PlayState* play) { } if (func_80842964(this, play) == 0) { - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { Math_StepToF(&this->linearVelocity, 0.0f, 2.0f); temp = func_808374A0(play, this, &this->skelAnime, 5.0f); @@ -9093,22 +9231,22 @@ void func_80844708(Player* this, PlayState* play) { this->linearVelocity = -this->linearVelocity; Player_RequestQuake(play, 33267, 3, 12); Player_RequestRumble(this, 255, 20, 150, 0); - Player_PlaySfx(&this->actor, NA_SE_PL_BODY_HIT); + Player_PlaySfx(this, NA_SE_PL_BODY_HIT); func_80832698(this, NA_SE_VO_LI_CLIMB_END); - this->unk_850 = 1; + this->av2.actionVar2 = 1; gSaveContext.sohStats.count[COUNT_BONKS]++; GameInteractor_ExecuteOnPlayerBonk(); return; } } - if ((this->skelAnime.curFrame < 15.0f) || !func_80850224(this, play)) { + if ((this->skelAnime.curFrame < 15.0f) || !Player_ActionChange_7(this, play)) { if (this->skelAnime.curFrame >= 20.0f) { func_8083A060(this, play); return; } - Player_GetMovementSpeedAndYaw(this, &sp38, &sp36, 0.018f, play); + Player_GetMovementSpeedAndYaw(this, &sp38, &sp36, SPEED_MODE_CURVED, play); sp38 *= 1.5f; if ((sp38 < 3.0f) || (this->unk_84B[this->unk_846] != 0)) { @@ -9127,7 +9265,7 @@ void func_80844708(Player* this, PlayState* play) { } } -void func_80844A44(Player* this, PlayState* play) { +void Player_Action_80844A44(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -9142,7 +9280,7 @@ void func_80844A44(Player* this, PlayState* play) { } } -void func_80844AF4(Player* this, PlayState* play) { +void Player_Action_80844AF4(Player* this, PlayState* play) { f32 sp2C; s16 sp2A; @@ -9155,8 +9293,8 @@ void func_80844AF4(Player* this, PlayState* play) { func_8084285C(this, 6.0f, 7.0f, 99.0f); if (!(this->actor.bgCheckFlags & 1)) { - Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); - func_8083DFE0(this, &sp2C, &this->currentYaw); + Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play); + func_8083DFE0(this, &sp2C, &this->yaw); return; } @@ -9198,32 +9336,32 @@ s32 func_80844BE4(Player* this, PlayState* play) { } void func_80844CF8(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80845000, 1); + Player_SetupAction(play, this, Player_Action_80845000, 1); } void func_80844D30(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80845308, 1); + Player_SetupAction(play, this, Player_Action_80845308, 1); } void func_80844D68(Player* this, PlayState* play) { func_80839FFC(this, play); func_80832318(this); Player_AnimChangeOnceMorph(play, this, D_80854368[Player_HoldsTwoHandedWeapon(this)]); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } void func_80844DC8(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80844E68, 1); + Player_SetupAction(play, this, Player_Action_80844E68, 1); this->unk_868 = 0.0f; Player_AnimPlayLoop(play, this, D_80854360[Player_HoldsTwoHandedWeapon(this)]); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } void func_80844E3C(Player* this) { Math_StepToF(&this->unk_858, 1.0f, 0.02f); } -void func_80844E68(Player* this, PlayState* play) { +void Player_Action_80844E68(Player* this, PlayState* play) { f32 sp34; s16 sp32; s32 temp; @@ -9235,23 +9373,23 @@ void func_80844E68(Player* this, PlayState* play) { func_808355DC(this); this->stateFlags1 &= ~PLAYER_STATE1_TARGET_NOTHING; Player_AnimPlayLoop(play, this, D_80854360[Player_HoldsTwoHandedWeapon(this)]); - this->unk_850 = -1; + this->av2.actionVar2 = -1; } func_8083721C(this); - if (!func_80842964(this, play) && (this->unk_850 != 0)) { + if (!func_80842964(this, play) && (this->av2.actionVar2 != 0)) { func_80844E3C(this); - if (this->unk_850 < 0) { + if (this->av2.actionVar2 < 0) { if (this->unk_858 >= 0.1f) { this->unk_845 = 0; - this->unk_850 = 1; + this->av2.actionVar2 = 1; } else if (!CHECK_BTN_ALL(sControlInput->cur.button, BTN_B)) { func_80844D68(this, play); } } else if (!func_80844BE4(this, play)) { - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play); temp = func_80840058(this, &sp34, &sp32, play); if (temp > 0) { @@ -9263,7 +9401,7 @@ void func_80844E68(Player* this, PlayState* play) { } } -void func_80845000(Player* this, PlayState* play) { +void Player_Action_80845000(Player* this, PlayState* play) { s16 temp1; s32 temp2; f32 sp5C; @@ -9274,7 +9412,7 @@ void func_80845000(Player* this, PlayState* play) { s16 temp5; s32 sp44; - temp1 = this->currentYaw - this->actor.shape.rot.y; + temp1 = this->yaw - this->actor.shape.rot.y; temp2 = ABS(temp1); sp5C = fabsf(this->linearVelocity); @@ -9298,7 +9436,7 @@ void func_80845000(Player* this, PlayState* play) { if (!func_80842964(this, play) && !func_80844BE4(this, play)) { func_80844E3C(this); - Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, SPEED_MODE_LINEAR, play); temp4 = func_80840058(this, &sp54, &sp52, play); @@ -9309,21 +9447,21 @@ void func_80845000(Player* this, PlayState* play) { if (temp4 == 0) { sp54 = 0.0f; - sp52 = this->currentYaw; + sp52 = this->yaw; } - temp5 = sp52 - this->currentYaw; + temp5 = sp52 - this->yaw; sp44 = ABS(temp5); if (sp44 > 0x4000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) { - this->currentYaw = sp52; + this->yaw = sp52; } return; } Math_AsymStepToF(&this->linearVelocity, sp54 * 0.2f, 1.0f, 0.5f); - Math_ScaledStepToS(&this->currentYaw, sp52, sp44 * 0.1f); + Math_ScaledStepToS(&this->yaw, sp52, sp44 * 0.1f); if ((sp54 == 0.0f) && (this->linearVelocity == 0.0f)) { func_80844DC8(this, play); @@ -9331,7 +9469,7 @@ void func_80845000(Player* this, PlayState* play) { } } -void func_80845308(Player* this, PlayState* play) { +void Player_Action_80845308(Player* this, PlayState* play) { f32 sp5C; f32 sp58; f32 sp54; @@ -9366,7 +9504,7 @@ void func_80845308(Player* this, PlayState* play) { if (!func_80842964(this, play) && !func_80844BE4(this, play)) { func_80844E3C(this); - Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp54, &sp52, SPEED_MODE_LINEAR, play); temp4 = func_80840058(this, &sp54, &sp52, play); @@ -9377,21 +9515,21 @@ void func_80845308(Player* this, PlayState* play) { if (temp4 == 0) { sp54 = 0.0f; - sp52 = this->currentYaw; + sp52 = this->yaw; } - temp5 = sp52 - this->currentYaw; + temp5 = sp52 - this->yaw; sp44 = ABS(temp5); if (sp44 > 0x4000) { if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) { - this->currentYaw = sp52; + this->yaw = sp52; } return; } Math_AsymStepToF(&this->linearVelocity, sp54 * 0.2f, 1.0f, 0.5f); - Math_ScaledStepToS(&this->currentYaw, sp52, sp44 * 0.1f); + Math_ScaledStepToS(&this->yaw, sp52, sp44 * 0.1f); if ((sp54 == 0.0f) && (this->linearVelocity == 0.0f) && (sp5C == 0.0f)) { func_80844DC8(this, play); @@ -9399,7 +9537,7 @@ void func_80845308(Player* this, PlayState* play) { } } -void func_80845668(Player* this, PlayState* play) { +void Player_Action_80845668(Player* this, PlayState* play) { s32 sp3C; f32 temp1; s32 temp2; @@ -9429,7 +9567,7 @@ void func_80845668(Player* this, PlayState* play) { } func_80838940(this, NULL, temp1, play, NA_SE_VO_LI_AUTO_JUMP); - this->unk_850 = -1; + this->av2.actionVar2 = -1; return; } } else { @@ -9465,16 +9603,16 @@ void func_80845668(Player* this, PlayState* play) { } if ((this->skelAnime.animation == &gPlayerAnim_link_normal_100step_up) || (this->skelAnime.curFrame > 5.0f)) { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { func_80832854(this); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } Math_StepToF(&this->actor.shape.yOffset, 0.0f, 150.0f); } } } -void func_808458D0(Player* this, PlayState* play) { +void Player_Action_808458D0(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; LinkAnimation_Update(play, &this->skelAnime); @@ -9551,26 +9689,26 @@ s32 func_80845C68(PlayState* play, s32 arg1) { return arg1; } -void func_80845CA4(Player* this, PlayState* play) { +void Player_Action_80845CA4(Player* this, PlayState* play) { f32 sp3C; s32 temp; f32 sp34; s32 sp30; s32 pad; - if (!func_8083B040(this, play)) { - if (this->unk_850 == 0) { + if (!Player_ActionChange_13(this, play)) { + if (this->av2.actionVar2 == 0) { LinkAnimation_Update(play, &this->skelAnime); if (DECR(this->doorTimer) == 0) { this->linearVelocity = 0.1f; - this->unk_850 = 1; + this->av2.actionVar2 = 1; } - } else if (this->unk_84F == 0) { + } else if (this->av1.actionVar1 == 0) { sp3C = 5.0f * D_808535E8; if (func_80845BA0(play, this, &sp3C, -1) < 30) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->unk_450.x = this->unk_45C.x; @@ -9587,8 +9725,8 @@ void func_80845CA4(Player* this, PlayState* play) { this->unk_450.x = (Math_SinS(sConveyorYaw) * 400.0f) + this->actor.world.pos.x; this->unk_450.z = (Math_CosS(sConveyorYaw) * 400.0f) + this->actor.world.pos.z; } - } else if (this->unk_850 < 0) { - this->unk_850++; + } else if (this->av2.actionVar2 < 0) { + this->av2.actionVar2++; sp34 = gSaveContext.entranceSpeed; sp30 = -1; @@ -9596,13 +9734,13 @@ void func_80845CA4(Player* this, PlayState* play) { temp = func_80845BA0(play, this, &sp34, sp30); - if ((this->unk_850 == 0) || + if ((this->av2.actionVar2 == 0) || ((temp == 0) && (this->linearVelocity == 0.0f) && (Play_GetCamera(play, 0)->unk_14C & 0x10))) { func_8005B1A4(Play_GetCamera(play, 0)); func_80845C68(play, gSaveContext.respawn[RESPAWN_MODE_DOWN].data); - if (!func_8083B644(this, play)) { + if (!Player_ActionChange_4(this, play)) { func_8083CF5C(this, play); } } @@ -9614,7 +9752,7 @@ void func_80845CA4(Player* this, PlayState* play) { } } -void func_80845EF8(Player* this, PlayState* play) { +void Player_Action_80845EF8(Player* this, PlayState* play) { s32 sp2C; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; @@ -9623,9 +9761,9 @@ void func_80845EF8(Player* this, PlayState* play) { Player_UpdateUpperBody(this, play); if (sp2C) { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (DECR(this->doorTimer) == 0) { - this->unk_850 = 1; + this->av2.actionVar2 = 1; this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; } } else { @@ -9644,7 +9782,7 @@ void func_80845EF8(Player* this, PlayState* play) { } } -void func_80846050(Player* this, PlayState* play) { +void Player_Action_80846050(Player* this, PlayState* play) { func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -9670,13 +9808,13 @@ void func_80846050(Player* this, PlayState* play) { } static AnimSfxEntry D_8085461C[] = { - { NA_SE_VO_LI_SWORD_L, 0x2031 }, - { NA_SE_VO_LI_SWORD_N, -0x20E6 }, + { NA_SE_VO_LI_SWORD_L, ANIMSFX_DATA(ANIMSFX_TYPE_4, 49) }, + { NA_SE_VO_LI_SWORD_N, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 230) }, }; -void func_80846120(Player* this, PlayState* play) { - if (LinkAnimation_Update(play, &this->skelAnime) && (this->unk_850++ > 20)) { - if (!func_8083B040(this, play)) { +void Player_Action_80846120(Player* this, PlayState* play) { + if (LinkAnimation_Update(play, &this->skelAnime) && (this->av2.actionVar2++ > 20)) { + if (!Player_ActionChange_13(this, play)) { func_8083A098(this, &gPlayerAnim_link_normal_heavy_carry_end, play); } return; @@ -9710,12 +9848,12 @@ void func_80846120(Player* this, PlayState* play) { Player_ProcessAnimSfxList(this, D_8085461C); } -void func_80846260(Player* this, PlayState* play) { +void Player_Action_80846260(Player* this, PlayState* play) { func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoop(play, this, &gPlayerAnim_link_silver_wait); - this->unk_850 = 1; + this->av2.actionVar2 = 1; return; } @@ -9723,7 +9861,7 @@ void func_80846260(Player* this, PlayState* play) { if (CVarGetInteger("gDpadEquips", 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (LinkAnimation_OnFrame(&this->skelAnime, 27.0f)) { Actor* interactRangeActor = this->interactRangeActor; @@ -9739,12 +9877,12 @@ void func_80846260(Player* this, PlayState* play) { } } else if (CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) { - Player_SetupAction(play, this, func_80846358, 1); + Player_SetupAction(play, this, Player_Action_80846358, 1); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_silver_throw); } } -void func_80846358(Player* this, PlayState* play) { +void Player_Action_80846358(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80839F90(this, play); return; @@ -9757,21 +9895,21 @@ void func_80846358(Player* this, PlayState* play) { heldActor->speedXZ = 10.0f; heldActor->velocity.y = 20.0f; func_80834644(play, this); - Player_PlaySfx(&this->actor, NA_SE_PL_THROW); + Player_PlaySfx(this, NA_SE_PL_THROW); func_80832698(this, NA_SE_VO_LI_SWORD_N); } } -void func_80846408(Player* this, PlayState* play) { +void Player_Action_80846408(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoop(play, this, &gPlayerAnim_link_normal_nocarry_free_wait); - this->unk_850 = 15; + this->av2.actionVar2 = 15; return; } - if (this->unk_850 != 0) { - this->unk_850--; - if (this->unk_850 == 0) { + if (this->av2.actionVar2 != 0) { + this->av2.actionVar2--; + if (this->av2.actionVar2 == 0) { func_8083A098(this, &gPlayerAnim_link_normal_nocarry_free_end, play); this->stateFlags1 &= ~PLAYER_STATE1_ITEM_OVER_HEAD; func_80832698(this, NA_SE_VO_LI_DAMAGE_S); @@ -9779,7 +9917,7 @@ void func_80846408(Player* this, PlayState* play) { } } -void func_808464B0(Player* this, PlayState* play) { +void Player_Action_808464B0(Player* this, PlayState* play) { func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -9801,14 +9939,14 @@ void func_808464B0(Player* this, PlayState* play) { } } -void func_80846578(Player* this, PlayState* play) { +void Player_Action_80846578(Player* this, PlayState* play) { f32 sp34; s16 sp32; func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime) || - ((this->skelAnime.curFrame >= 8.0f) && Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.018f, play))) { + ((this->skelAnime.curFrame >= 8.0f) && Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_CURVED, play))) { func_80839F90(this, play); return; } @@ -9887,9 +10025,9 @@ void func_80846648(PlayState* play, Player* this) { } void func_80846660(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084F710, 0); + Player_SetupAction(play, this, Player_Action_8084F710, 0); if ((play->sceneNum == SCENE_LAKE_HYLIA) && (gSaveContext.sceneSetupIndex >= 4)) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; } this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_okarina_warp_goal, 2.0f / 3.0f, 0.0f, 24.0f, @@ -9913,34 +10051,34 @@ void func_80846720(PlayState* play, Player* this, s32 arg2) { func_80834644(play, this); if (arg2 != 0) { - Player_PlaySfx(&this->actor, NA_SE_IT_SWORD_PICKOUT); + Player_PlaySfx(this, NA_SE_IT_SWORD_PICKOUT); } } static Vec3f D_808546F4 = { -1.0f, 69.0f, 20.0f }; void func_808467D4(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084E9AC, 0); + Player_SetupAction(play, this, Player_Action_8084E9AC, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; Math_Vec3f_Copy(&this->actor.world.pos, &D_808546F4); - this->currentYaw = this->actor.shape.rot.y = -0x8000; + this->yaw = this->actor.shape.rot.y = -0x8000; LinkAnimation_Change(play, &this->skelAnime, this->ageProperties->unk_A0, 2.0f / 3.0f, 0.0f, 0.0f, ANIMMODE_ONCE, 0.0f); Player_AnimReplaceApplyFlags(play, this, 0x28F); if (LINK_IS_ADULT) { func_80846720(play, this, 0); } - this->unk_850 = 20; + this->av2.actionVar2 = 20; } void func_808468A8(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084F9A0, 0); + Player_SetupAction(play, this, Player_Action_8084F9A0, 0); Player_AnimReplaceApplyFlags(play, this, 0x9B); } void func_808468E8(PlayState* play, Player* this) { func_808389E8(this, &gPlayerAnim_link_normal_jump, 12.0f, play); - Player_SetupAction(play, this, func_8084F9C0, 0); + Player_SetupAction(play, this, Player_Action_8084F9C0, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->fallStartHeight = this->actor.world.pos.y; OnePointCutscene_Init(play, 5110, 40, &this->actor, MAIN_CAM); @@ -9951,7 +10089,7 @@ void func_80846978(PlayState* play, Player* this) { } void func_808469BC(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084F698, 0); + Player_SetupAction(play, this, Player_Action_8084F698, 0); this->actor.draw = NULL; this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; } @@ -9965,7 +10103,7 @@ Actor* func_80846A00(PlayState* play, Player* this, s32 arg2) { void func_80846A68(PlayState* play, Player* this) { this->actor.draw = NULL; - Player_SetupAction(play, this, func_8085076C, 0); + Player_SetupAction(play, this, Player_Action_8085076C, 0); this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; } @@ -9985,7 +10123,7 @@ void Player_InitCommon(Player* this, PlayState* play, FlexSkeletonHeader* skelHe this->ageProperties = &sAgeProperties[gSaveContext.linkAge]; Actor_ProcessInitChain(&this->actor, sInitChain); this->meleeWeaponEffectIndex = TOTAL_EFFECT_COUNT; - this->currentYaw = this->actor.world.rot.y; + this->yaw = this->actor.world.rot.y; func_80834644(play, this); SkelAnime_InitLink(play, &this->skelAnime, skelHeader, GET_PLAYER_ANIM(PLAYER_ANIMGROUP_wait, this->modelAnimType), 9, @@ -10079,7 +10217,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { Math_Vec3f_Copy(&thisx->home.pos, &thisx->world.pos); Math_Vec3f_Copy(&thisx->prevPos, &thisx->world.pos); this->fallStartHeight = thisx->world.pos.y; - this->currentYaw = thisx->shape.rot.y = gSaveContext.respawn[sp4C].yaw; + this->yaw = thisx->shape.rot.y = gSaveContext.respawn[sp4C].yaw; thisx->params = gSaveContext.respawn[sp4C].playerParams; } @@ -10224,7 +10362,7 @@ void func_808473D4(PlayState* play, Player* this) { if (this->unk_860 == 2) { doAction = DO_ACTION_REEL; } - } else if ((func_8084E3C4 != this->actionFunc) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) { + } else if ((Player_Action_8084E3C4 != this->actionFunc) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) { if ((this->doorType != PLAYER_DOORTYPE_NONE) && (!(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) || ((heldActor != NULL) && (heldActor->id == ACTOR_EN_RU1)))) { @@ -10246,7 +10384,7 @@ void func_808473D4(PlayState* play, Player* this) { (!(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->rideActor != NULL))) { doAction = DO_ACTION_CLIMB; } else if ((this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && !EN_HORSE_CHECK_4((EnHorse*)this->rideActor) && - (func_8084D3E4 != this->actionFunc)) { + (Player_Action_8084D3E4 != this->actionFunc)) { if ((this->stateFlags2 & PLAYER_STATE2_SPEAK_OR_CHECK) && (this->targetActor != NULL)) { if (this->targetActor->category == ACTORCAT_NPC) { doAction = DO_ACTION_SPEAK; @@ -10397,16 +10535,16 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { f32 ceilingCheckHeight; u32 flags; - sPrevFloorProperty = this->unk_A7A; + sPrevFloorProperty = this->floorProperty; if (this->stateFlags2 & PLAYER_STATE2_CRAWLING) { spB0 = 10.0f; spAC = 15.0f; ceilingCheckHeight = 30.0f; } else { - spB0 = this->ageProperties->unk_38; + spB0 = this->ageProperties->wallCheckRadius; spAC = 26.0f; - ceilingCheckHeight = this->ageProperties->unk_00; + ceilingCheckHeight = this->ageProperties->ceilingCheckHeight; } if (this->stateFlags1 & (PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_FLOOR_DISABLED)) { @@ -10416,7 +10554,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { } else if ((this->stateFlags1 & PLAYER_STATE1_LOADING) && ((this->unk_A84 - (s32)this->actor.world.pos.y) >= 100)) { flags = 0x39; } else if (!(this->stateFlags1 & PLAYER_STATE1_LOADING) && - ((func_80845EF8 == this->actionFunc) || (func_80845CA4 == this->actionFunc))) { + ((Player_Action_80845EF8 == this->actionFunc) || (Player_Action_80845CA4 == this->actionFunc))) { this->actor.bgCheckFlags &= ~0x208; flags = 0x3C; } else { @@ -10447,8 +10585,8 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { floorPoly = this->actor.floorPoly; if (floorPoly != NULL) { - this->unk_A7A = func_80041EA4(&play->colCtx, floorPoly, this->actor.floorBgId); - this->unk_A82 = this->floorSfxOffset; + this->floorProperty = func_80041EA4(&play->colCtx, floorPoly, this->actor.floorBgId); + this->prevFloorSfxOffset = this->floorSfxOffset; if (this->actor.bgCheckFlags & 0x20) { if (this->actor.yDistToWater < 20.0f) { @@ -10499,7 +10637,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { s32 pad; sInteractWallCheckOffset.y = 18.0f; - sInteractWallCheckOffset.z = this->ageProperties->unk_38 + 10.0f; + sInteractWallCheckOffset.z = this->ageProperties->wallCheckRadius + 10.0f; if (!(this->stateFlags2 & PLAYER_STATE2_CRAWLING) && Player_PosVsWallLineTest(play, this, &sInteractWallCheckOffset, &wallPoly, &wallBgId, &sInteractWallCheckResult)) { @@ -10567,7 +10705,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { sShapeYawToTouchedWall = ABS(yawDiff); - yawDiff = this->currentYaw - (s16)(this->actor.wallYaw + 0x8000); + yawDiff = this->yaw - (s16)(this->actor.wallYaw + 0x8000); sWorldYawToTouchedWall = ABS(yawDiff); @@ -10641,17 +10779,17 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { } } else { this->unk_880 = R_RUN_SPEED_LIMIT / 100.0f; - this->unk_88D = 0; + this->ledgeClimbDelayTimer = 0; this->yDistToLedge = 0.0f; } - if (nextLedgeClimbType == this->unk_88C) { - if ((this->linearVelocity != 0.0f) && (this->unk_88D < 100)) { - this->unk_88D++; + if (nextLedgeClimbType == this->ledgeClimbType) { + if ((this->linearVelocity != 0.0f) && (this->ledgeClimbDelayTimer < 100)) { + this->ledgeClimbDelayTimer++; } } else { - this->unk_88C = nextLedgeClimbType; - this->unk_88D = 0; + this->ledgeClimbType = nextLedgeClimbType; + this->ledgeClimbDelayTimer = 0; } if (this->actor.bgCheckFlags & 1) { @@ -10674,8 +10812,8 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { sp54 = 1.0f / COLPOLY_GET_NORMAL(floorPoly->normal.y); sp50 = COLPOLY_GET_NORMAL(floorPoly->normal.z); - sp4C = Math_SinS(this->currentYaw); - sp44 = Math_CosS(this->currentYaw); + sp4C = Math_SinS(this->yaw); + sp44 = Math_CosS(this->yaw); this->floorPitch = Math_Atan2S(1.0f, (-(sp58 * sp4C) - (sp50 * sp44)) * sp54); this->floorPitchAlt = Math_Atan2S(1.0f, (-(sp58 * sp44) - (sp50 * sp4C)) * sp54); @@ -10691,11 +10829,11 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { Player_UpdateHoverBoots(this); } - if (this->unk_A7B == sFloorType) { - this->unk_A79++; + if (this->prevFloorType == sFloorType) { + this->floorTypeTimer++; } else { - this->unk_A7B = sFloorType; - this->unk_A79 = 0; + this->prevFloorType = sFloorType; + this->floorTypeTimer = 0; } } @@ -10714,7 +10852,7 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { if ((this->actor.parent != NULL) && (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING)) { camMode = CAM_MODE_HOOKSHOT; Camera_SetParam(Play_GetCamera(play, 0), 8, this->actor.parent); - } else if (func_8084377C == this->actionFunc) { + } else if (Player_Action_8084377C == this->actionFunc) { camMode = CAM_MODE_STILL; } else if (this->stateFlags2 & PLAYER_STATE2_GRABBING_DYNAPOLY) { camMode = CAM_MODE_PUSHPULL; @@ -10751,7 +10889,7 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { camMode = CAM_MODE_TARGET; } } else if (this->stateFlags1 & (PLAYER_STATE1_JUMPING | PLAYER_STATE1_CLIMBING_LADDER)) { - if ((func_80845668 == this->actionFunc) || (this->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER)) { + if ((Player_Action_80845668 == this->actionFunc) || (this->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER)) { camMode = CAM_MODE_CLIMB; } else { camMode = CAM_MODE_JUMP; @@ -10826,16 +10964,16 @@ void func_80848A04(PlayState* play, Player* this) { 0, 8); } -void func_80848B44(PlayState* play, Player* this) { +void Player_UpdateBodyShock(PlayState* play, Player* this) { Vec3f shockPos; Vec3f* randBodyPart; s32 shockScale; - this->shockTimer--; - this->unk_892 += this->shockTimer; + this->bodyShockTimer--; + this->unk_892 += this->bodyShockTimer; if (this->unk_892 > 20) { - shockScale = this->shockTimer * 2; + shockScale = this->bodyShockTimer * 2; this->unk_892 -= 20; if (shockScale > 40) { @@ -10852,7 +10990,7 @@ void func_80848B44(PlayState* play, Player* this) { } } -void func_80848C74(PlayState* play, Player* this) { +void Player_UpdateBodyBurn(PlayState* play, Player* this) { s32 spawnedFlame; u8* timerPtr; s32 timerStep; @@ -10870,7 +11008,7 @@ void func_80848C74(PlayState* play, Player* this) { } spawnedFlame = false; - timerPtr = this->flameTimers; + timerPtr = this->bodyFlameTimers; if (this->stateFlags2 & PLAYER_STATE2_FOOTSTEP) { sp58 = 100; @@ -10903,7 +11041,7 @@ void func_80848C74(PlayState* play, Player* this) { } if (spawnedFlame) { - Player_PlaySfx(&this->actor, NA_SE_EV_TORCH - SFX_FLAG); + Player_PlaySfx(this, NA_SE_EV_TORCH - SFX_FLAG); if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { dmgCooldown = 0; @@ -10915,7 +11053,7 @@ void func_80848C74(PlayState* play, Player* this) { Player_InflictDamage(play, -1); } } else { - this->isBurning = false; + this->bodyIsBurning = false; } } @@ -11124,12 +11262,12 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { this->unk_860++; } - if (this->shockTimer != 0) { - func_80848B44(play, this); + if (this->bodyShockTimer != 0) { + Player_UpdateBodyShock(play, this); } - if (this->isBurning) { - func_80848C74(play, this); + if (this->bodyIsBurning) { + Player_UpdateBodyBurn(play, this); } if ((this->stateFlags3 & PLAYER_STATE3_RESTORE_NAYRUS_LOVE) && (gSaveContext.nayrusLoveTimer != 0) && (gSaveContext.magicState == MAGIC_STATE_IDLE)) { @@ -11175,7 +11313,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { this->stateFlags1 |= PLAYER_STATE1_ON_HORSE; Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_1); Player_AnimReplaceApplyFlags(play, this, 0x9B); - this->unk_850 = 99; + this->av2.actionVar2 = 99; } if (this->unk_844 == 0) { @@ -11204,7 +11342,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { ((this->currentBoots == PLAYER_BOOTS_HOVER || GameInteractor_GetSlipperyFloorActive()) && !(this->stateFlags1 & (PLAYER_STATE1_IN_WATER | PLAYER_STATE1_IN_CUTSCENE)))) { f32 sp70 = this->linearVelocity; - s16 sp6E = this->currentYaw; + s16 sp6E = this->yaw; s16 yawDiff = this->actor.world.rot.y - sp6E; s32 pad; @@ -11214,7 +11352,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { } if (Math_StepToF(&this->actor.speedXZ, sp70, 0.35f) && (sp70 == 0.0f)) { - this->actor.world.rot.y = this->currentYaw; + this->actor.world.rot.y = this->yaw; } if (this->linearVelocity != 0.0f) { @@ -11231,14 +11369,14 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { } } else { this->actor.speedXZ = this->linearVelocity; - this->actor.world.rot.y = this->currentYaw; + this->actor.world.rot.y = this->yaw; } func_8002D868(&this->actor); if ((this->pushedSpeed != 0.0f) && !Player_InCsMode(play) && !(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER)) && - (func_80845668 != this->actionFunc) && (func_808507F4 != this->actionFunc)) { + (Player_Action_80845668 != this->actionFunc) && (Player_Action_808507F4 != this->actionFunc)) { this->actor.velocity.x += this->pushedSpeed * Math_SinS(this->pushedYaw); this->actor.velocity.z += this->pushedSpeed * Math_CosS(this->pushedYaw); } @@ -11247,7 +11385,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Player_ProcessSceneCollision(play, this); } else { sFloorType = 0; - this->unk_A7A = 0; + this->floorProperty = 0; if (!(this->stateFlags1 & PLAYER_STATE1_LOADING) && (this->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { EnHorse* rideActor = (EnHorse*)this->rideActor; @@ -11308,7 +11446,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { } else if ((this->actor.bgCheckFlags & 1) || (this->stateFlags1 & PLAYER_STATE1_IN_WATER)) { func_80836448(play, this, func_808332B8(this) ? &gPlayerAnim_link_swimer_swim_down - : (this->shockTimer != 0) ? &gPlayerAnim_link_normal_electric_shock_end + : (this->bodyShockTimer != 0) ? &gPlayerAnim_link_normal_electric_shock_end : &gPlayerAnim_link_derth_rebirth); } } else { @@ -11341,7 +11479,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { if ((this->csAction != 7) || !(this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER | PLAYER_STATE1_DAMAGED))) { this->unk_6AD = 3; - } else if (func_80852E14 != this->actionFunc) { + } else if (Player_Action_CsAction != this->actionFunc) { func_80852944(play, this, NULL); } } else { @@ -11815,7 +11953,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) { } if (this->stateFlags2 & PLAYER_STATE2_FROZEN) { - f32 scale = (this->unk_84F >> 1) * 22.0f; + f32 scale = (this->av1.actionVar1 >> 1) * 22.0f; gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (0 - play->gameplayFrames) % 128, 32, 32, 1, @@ -12000,7 +12138,7 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { } Math_AsymStepToF(arg1, arg2 * 0.8f * swimMod, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); - Math_ScaledStepToS(&this->currentYaw, arg3, 1600); + Math_ScaledStepToS(&this->yaw, arg3, 1600); // #endregion } else { @@ -12019,7 +12157,7 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { } Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); - Math_ScaledStepToS(&this->currentYaw, arg3, 1600); + Math_ScaledStepToS(&this->yaw, arg3, 1600); } } @@ -12045,7 +12183,7 @@ void SurfaceWithoutSwimMod(Player* this, f32* arg1, f32 arg2, s16 arg3) { } Math_AsymStepToF(arg1, arg2 * 0.8f, temp1, (fabsf(*arg1) * 0.02f) + 0.05f); - Math_ScaledStepToS(&this->currentYaw, arg3, 1600); + Math_ScaledStepToS(&this->yaw, arg3, 1600); } // #endregion @@ -12117,7 +12255,7 @@ void func_8084B158(PlayState* play, Player* this, Input* input, f32 arg3) { LinkAnimation_Update(play, &this->skelAnime); } -void func_8084B1D8(Player* this, PlayState* play) { +void Player_Action_8084B1D8(Player* this, PlayState* play) { if (this->stateFlags1 & PLAYER_STATE1_IN_WATER) { func_8084B000(this); func_8084AEEC(this, &this->linearVelocity, 0, this->actor.shape.rot.y); @@ -12140,7 +12278,7 @@ void func_8084B1D8(Player* this, PlayState* play) { ((this->unk_6AD == 1) && CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)))) { func_8083C148(this, play); func_80078884(NA_SE_SY_CAMERA_ZOOM_UP); - } else if ((DECR(this->unk_850) == 0) || (this->unk_6AD != 2)) { + } else if ((DECR(this->av2.actionVar2) == 0) || (this->unk_6AD != 2)) { if (func_8008F128(this)) { this->unk_6AE |= 0x43; } else { @@ -12148,13 +12286,13 @@ void func_8084B1D8(Player* this, PlayState* play) { } } - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } s32 func_8084B3CC(PlayState* play, Player* this) { if (play->shootingGalleryStatus != 0) { func_80832564(play, this); - Player_SetupAction(play, this, func_8084FA54, 0); + Player_SetupAction(play, this, Player_Action_8084FA54, 0); if (!func_8002DD6C(this) || Player_HoldsHookshot(this)) { s32 projectileItemToUse = ITEM_BOW; @@ -12185,14 +12323,14 @@ s32 func_8084B4D4(PlayState* play, Player* this) { this->stateFlags3 &= ~PLAYER_STATE3_FORCE_PULL_OCARINA; func_8084B498(this); this->unk_6AD = 4; - func_8083B040(this, play); + Player_ActionChange_13(this, play); return 1; } return 0; } -void func_8084B530(Player* this, PlayState* play) { +void Player_Action_8084B530(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; Player_UpdateUpperBody(this, play); @@ -12206,11 +12344,11 @@ void func_8084B530(Player* this, PlayState* play) { func_8005B1A4(Play_GetCamera(play, 0)); if (!func_8084B4D4(play, this) && !func_8084B3CC(play, this) && !Player_StartCsAction(play, this)) { - if ((this->targetActor != this->interactRangeActor) || !func_8083E5A8(this, play)) { + if ((this->targetActor != this->interactRangeActor) || !Player_ActionChange_2(this, play)) { if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) { - s32 sp24 = this->unk_850; + s32 sp24 = this->av2.actionVar2; func_8083A360(play, this); - this->unk_850 = sp24; + this->av2.actionVar2 = sp24; } else if (func_808332B8(this)) { func_80838F18(play, this); } else { @@ -12224,9 +12362,9 @@ void func_8084B530(Player* this, PlayState* play) { } if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) { - func_8084CC98(this, play); + Player_Action_8084CC98(this, play); } else if (func_808332B8(this)) { - func_8084D610(this, play); + Player_Action_8084D610(this, play); } else if (!func_8008E9C4(this) && LinkAnimation_Update(play, &this->skelAnime)) { if (this->skelAnime.moveFlags != 0) { func_80832DBC(this); @@ -12242,11 +12380,11 @@ void func_8084B530(Player* this, PlayState* play) { } if (this->unk_664 != NULL) { - this->currentYaw = this->actor.shape.rot.y = func_8083DB98(this, 0); + this->yaw = this->actor.shape.rot.y = func_8083DB98(this, 0); } } -void func_8084B78C(Player* this, PlayState* play) { +void Player_Action_8084B78C(Player* this, PlayState* play) { f32 sp34; s16 sp32; s32 temp; @@ -12256,7 +12394,7 @@ void func_8084B78C(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { if (!func_8083F9D0(play, this)) { - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play); temp = func_8083FFB8(this, &sp34, &sp32); if (temp > 0) { func_8083FAB8(this, play); @@ -12278,11 +12416,11 @@ void func_8084B840(PlayState* play, Player* this, f32 arg2) { } static AnimSfxEntry D_80854870[] = { - { NA_SE_PL_SLIP, 0x1003 }, - { NA_SE_PL_SLIP, -0x1015 }, + { NA_SE_PL_SLIP, ANIMSFX_DATA(ANIMSFX_TYPE_2, 3) }, + { NA_SE_PL_SLIP, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 21) }, }; -void func_8084B898(Player* this, PlayState* play) { +void Player_Action_8084B898(Player* this, PlayState* play) { f32 sp34; s16 sp32; s32 temp; @@ -12290,8 +12428,8 @@ void func_8084B898(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY; if (func_80832CB0(play, this, &gPlayerAnim_link_normal_pushing)) { - this->unk_850 = 1; - } else if (this->unk_850 == 0) { + this->av2.actionVar2 = 1; + } else if (this->av2.actionVar2 == 0) { if (LinkAnimation_OnFrame(&this->skelAnime, 11.0f)) { func_80832698(this, NA_SE_VO_LI_PUSH); } @@ -12301,7 +12439,7 @@ void func_8084B898(Player* this, PlayState* play) { func_8083F524(play, this); if (!func_8083F9D0(play, this)) { - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play); temp = func_8083FFB8(this, &sp34, &sp32); if (temp < 0) { func_8083FB14(this, play); @@ -12319,13 +12457,13 @@ void func_8084B898(Player* this, PlayState* play) { } static AnimSfxEntry D_80854878[] = { - { NA_SE_PL_SLIP, 0x1004 }, - { NA_SE_PL_SLIP, -0x1018 }, + { NA_SE_PL_SLIP, ANIMSFX_DATA(ANIMSFX_TYPE_2, 4) }, + { NA_SE_PL_SLIP, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 24) }, }; static Vec3f D_80854880 = { 0.0f, 26.0f, -40.0f }; -void func_8084B9E4(Player* this, PlayState* play) { +void Player_Action_8084B9E4(Player* this, PlayState* play) { LinkAnimationHeader* anim; f32 sp70; s16 sp6E; @@ -12341,9 +12479,9 @@ void func_8084B9E4(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_GRAB | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS | PLAYER_STATE2_GRABBING_DYNAPOLY; if (func_80832CB0(play, this, anim)) { - this->unk_850 = 1; + this->av2.actionVar2 = 1; } else { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (LinkAnimation_OnFrame(&this->skelAnime, 11.0f)) { func_80832698(this, NA_SE_VO_LI_PUSH); } @@ -12355,7 +12493,7 @@ void func_8084B9E4(Player* this, PlayState* play) { func_8083F524(play, this); if (!func_8083F9D0(play, this)) { - Player_GetMovementSpeedAndYaw(this, &sp70, &sp6E, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp70, &sp6E, SPEED_MODE_LINEAR, play); temp1 = func_8083FFB8(this, &sp70, &sp6E); if (temp1 > 0) { func_8083FAB8(this, play); @@ -12382,7 +12520,7 @@ void func_8084B9E4(Player* this, PlayState* play) { } } -void func_8084BBE4(Player* this, PlayState* play) { +void Player_Action_8084BBE4(Player* this, PlayState* play) { f32 sp3C; s16 sp3A; LinkAnimationHeader* anim; @@ -12392,9 +12530,9 @@ void func_8084BBE4(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { // clang-format off - anim = (this->unk_84F > 0) ? &gPlayerAnim_link_normal_fall_wait : GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_wait, this->modelAnimType); Player_AnimPlayLoop(play, this, anim); + anim = (this->av1.actionVar1 > 0) ? &gPlayerAnim_link_normal_fall_wait : GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_wait, this->modelAnimType); Player_AnimPlayLoop(play, this, anim); // clang-format on - } else if (this->unk_84F == 0) { + } else if (this->av1.actionVar1 == 0) { if (this->skelAnime.animation == &gPlayerAnim_link_normal_fall) { temp = 11.0f; } else { @@ -12404,19 +12542,19 @@ void func_8084BBE4(Player* this, PlayState* play) { if (LinkAnimation_OnFrame(&this->skelAnime, temp)) { func_80832770(this, NA_SE_PL_WALK_GROUND); if (this->skelAnime.animation == &gPlayerAnim_link_normal_fall) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; } else { - this->unk_84F = -1; + this->av1.actionVar1 = -1; } } } - Math_ScaledStepToS(&this->actor.shape.rot.y, this->currentYaw, 0x800); + Math_ScaledStepToS(&this->actor.shape.rot.y, this->yaw, 0x800); - if (this->unk_84F != 0) { - Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, 0.0f, play); + if (this->av1.actionVar1 != 0) { + Player_GetMovementSpeedAndYaw(this, &sp3C, &sp3A, SPEED_MODE_LINEAR, play); if (this->unk_847[this->unk_846] >= 0) { - if (this->unk_84F > 0) { + if (this->av1.actionVar1 > 0) { anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_fall_up, this->modelAnimType); } else { anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_jump_climb_up, this->modelAnimType); @@ -12427,7 +12565,7 @@ void func_8084BBE4(Player* this, PlayState* play) { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A) || (this->actor.shape.feetFloorFlags != 0)) { func_80837B60(this); - if (this->unk_84F < 0) { + if (this->av1.actionVar1 < 0) { this->linearVelocity = -0.8f; } else { this->linearVelocity = 0.8f; @@ -12438,7 +12576,7 @@ void func_8084BBE4(Player* this, PlayState* play) { } } -void func_8084BDFC(Player* this, PlayState* play) { +void Player_Action_8084BDFC(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -12451,16 +12589,16 @@ void func_8084BDFC(Player* this, PlayState* play) { func_808328A0(this); } else if (LinkAnimation_OnFrame(&this->skelAnime, this->skelAnime.endFrame - 34.0f)) { this->stateFlags1 &= ~(PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE); - Player_PlaySfx(&this->actor, NA_SE_PL_CLIMB_CLIFF); + Player_PlaySfx(this, NA_SE_PL_CLIMB_CLIFF); func_80832698(this, NA_SE_VO_LI_CLIMB_END); } } void func_8084BEE4(Player* this) { - Player_PlaySfx(&this->actor, (this->unk_84F != 0) ? NA_SE_PL_WALK_WALL : NA_SE_PL_WALK_LADDER); + Player_PlaySfx(this, (this->av1.actionVar1 != 0) ? NA_SE_PL_WALK_WALL : NA_SE_PL_WALK_LADDER); } -void func_8084BF1C(Player* this, PlayState* play) { +void Player_Action_8084BF1C(Player* this, PlayState* play) { static Vec3f D_8085488C = { 0.0f, 0.0f, 26.0f }; s32 sp84; s32 sp80; @@ -12479,7 +12617,7 @@ void func_8084BF1C(Player* this, PlayState* play) { this->fallStartHeight = this->actor.world.pos.y; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; - if ((this->unk_84F != 0) && (ABS(sp84) < ABS(sp80))) { + if ((this->av1.actionVar1 != 0) && (ABS(sp84) < ABS(sp80))) { phi_f0 = ABS(sp80) * 0.0325f; sp84 = 0; } else { @@ -12501,7 +12639,7 @@ void func_8084BF1C(Player* this, PlayState* play) { this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVarGetInteger("gClimbSpeed", 0); - if (this->unk_850 >= 0) { + if (this->av2.actionVar2 >= 0) { if ((this->actor.wallPoly != NULL) && (this->actor.wallBgId != BGCHECK_SCENE)) { DynaPolyActor* wallPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId); if (wallPolyActor != NULL) { @@ -12510,36 +12648,36 @@ void func_8084BF1C(Player* this, PlayState* play) { } } - Actor_UpdateBgCheckInfo(play, &this->actor, 26.0f, 6.0f, this->ageProperties->unk_00, 7); + Actor_UpdateBgCheckInfo(play, &this->actor, 26.0f, 6.0f, this->ageProperties->ceilingCheckHeight, 7); func_8083F360(play, this, 26.0f, this->ageProperties->unk_3C, 50.0f, -20.0f); } - if ((this->unk_850 < 0) || !func_8083FBC0(this, play)) { + if ((this->av2.actionVar2 < 0) || !func_8083FBC0(this, play)) { if (LinkAnimation_Update(play, &this->skelAnime) != 0) { - if (this->unk_850 < 0) { - this->unk_850 = ABS(this->unk_850) & 1; + if (this->av2.actionVar2 < 0) { + this->av2.actionVar2 = ABS(this->av2.actionVar2) & 1; return; } if (sp84 != 0) { - sp68 = this->unk_84F + this->unk_850; + sp68 = this->av1.actionVar1 + this->av2.actionVar2; if (sp84 > 0) { D_8085488C.y = this->ageProperties->unk_40; temp_f0 = func_8083973C(play, this, &D_8085488C, &sp5C); if (this->actor.world.pos.y < temp_f0) { - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { this->actor.world.pos.y = temp_f0; this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER; func_8083A5C4(play, this, this->actor.wallPoly, this->ageProperties->unk_3C, &gPlayerAnim_link_normal_jump_climb_up_free); - this->currentYaw += 0x8000; - this->actor.shape.rot.y = this->currentYaw; + this->yaw += 0x8000; + this->actor.shape.rot.y = this->yaw; func_8083A9B8(this, &gPlayerAnim_link_normal_jump_climb_up_free, play); this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LEDGE; } else { - func_8083F070(this, this->ageProperties->unk_CC[this->unk_850], play); + func_8083F070(this, this->ageProperties->unk_CC[this->av2.actionVar2], play); } } else { this->skelAnime.prevTransl = this->ageProperties->unk_4A[sp68]; @@ -12547,14 +12685,14 @@ void func_8084BF1C(Player* this, PlayState* play) { } } else { if ((this->actor.world.pos.y - this->actor.floorHeight) < 15.0f) { - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { func_8083FB7C(this, play); } else { - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { this->skelAnime.prevTransl = this->ageProperties->unk_44; } - func_8083F070(this, this->ageProperties->unk_C4[this->unk_850], play); - this->unk_850 = 1; + func_8083F070(this, this->ageProperties->unk_C4[this->av2.actionVar2], play); + this->av2.actionVar2 = 1; } } else { sp68 ^= 1; @@ -12564,16 +12702,16 @@ void func_8084BF1C(Player* this, PlayState* play) { 0.0f, ANIMMODE_ONCE, 0.0f); } } - this->unk_850 ^= 1; + this->av2.actionVar2 ^= 1; } else { - if ((this->unk_84F != 0) && (sp80 != 0)) { - anim2 = this->ageProperties->unk_BC[this->unk_850]; + if ((this->av1.actionVar1 != 0) && (sp80 != 0)) { + anim2 = this->ageProperties->unk_BC[this->av2.actionVar2]; if (CVarGetInteger("gMirroredWorld", 0) ? (sp80 < 0) : (sp80 > 0)) { - this->skelAnime.prevTransl = this->ageProperties->unk_7A[this->unk_850]; + this->skelAnime.prevTransl = this->ageProperties->unk_7A[this->av2.actionVar2]; Player_AnimPlayOnce(play, this, anim2); } else { - this->skelAnime.prevTransl = this->ageProperties->unk_86[this->unk_850]; + this->skelAnime.prevTransl = this->ageProperties->unk_86[this->av2.actionVar2]; LinkAnimation_Change(play, &this->skelAnime, anim2, -1.0f, Animation_GetLastFrame(anim2), 0.0f, ANIMMODE_ONCE, 0.0f); } @@ -12586,10 +12724,10 @@ void func_8084BF1C(Player* this, PlayState* play) { } } - if (this->unk_850 < 0) { - if (((this->unk_850 == -2) && + if (this->av2.actionVar2 < 0) { + if (((this->av2.actionVar2 == -2) && (LinkAnimation_OnFrame(&this->skelAnime, 14.0f) || LinkAnimation_OnFrame(&this->skelAnime, 29.0f))) || - ((this->unk_850 == -4) && + ((this->av2.actionVar2 == -4) && (LinkAnimation_OnFrame(&this->skelAnime, 22.0f) || LinkAnimation_OnFrame(&this->skelAnime, 35.0f) || LinkAnimation_OnFrame(&this->skelAnime, 49.0f) || LinkAnimation_OnFrame(&this->skelAnime, 55.0f)))) { func_8084BEE4(this); @@ -12606,12 +12744,12 @@ static f32 D_80854898[] = { 10.0f, 20.0f }; static f32 D_808548A0[] = { 40.0f, 50.0f }; static AnimSfxEntry D_808548A8[] = { - { NA_SE_PL_WALK_LADDER, 0x80A }, - { NA_SE_PL_WALK_LADDER, 0x814 }, - { NA_SE_PL_WALK_LADDER, -0x81E }, + { NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) }, + { NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) }, + { NA_SE_PL_WALK_LADDER, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 30) }, }; -void func_8084C5F8(Player* this, PlayState* play) { +void Player_Action_8084C5F8(Player* this, PlayState* play) { s32 temp; f32* sp38; CollisionPoly* sp34; @@ -12635,7 +12773,7 @@ void func_8084C5F8(Player* this, PlayState* play) { sp38 = D_80854898; - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { Player_ProcessAnimSfxList(this, D_808548A8); sp38 = D_808548A0; } @@ -12652,11 +12790,14 @@ void func_8084C5F8(Player* this, PlayState* play) { } static AnimSfxEntry D_808548B4[] = { - { 0, 0x3028 }, { 0, 0x3030 }, { 0, 0x3038 }, { 0, 0x3040 }, { 0, 0x3048 }, - { 0, 0x3050 }, { 0, 0x3058 }, { 0, 0x3060 }, { 0, -0x3068 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 40) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 48) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 56) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 64) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 72) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 80) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 88) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 96) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 104) }, }; -void func_8084C760(Player* this, PlayState* play) { +void Player_Action_8084C760(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -12684,11 +12825,14 @@ void func_8084C760(Player* this, PlayState* play) { } static AnimSfxEntry D_808548D8[] = { - { 0, 0x300A }, { 0, 0x3012 }, { 0, 0x301A }, { 0, 0x3022 }, { 0, 0x3034 }, - { 0, 0x303C }, { 0, 0x3044 }, { 0, 0x304C }, { 0, -0x3054 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 18) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 26) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 34) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 52) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 60) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 68) }, { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 76) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 84) }, }; -void func_8084C81C(Player* this, PlayState* play) { +void Player_Action_8084C81C(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -12739,8 +12883,8 @@ s32 func_8084C9BC(Player* this, PlayState* play) { s32 sp38; f32 sp34; - if (this->unk_850 < 0) { - this->unk_850 = 99; + if (this->av2.actionVar2 < 0) { + this->av2.actionVar2 = 99; } else { sp38 = (this->mountSide < 0) ? 0 : 1; if (!func_8084C89C(play, this, sp38, &sp34)) { @@ -12759,7 +12903,7 @@ s32 func_8084C9BC(Player* this, PlayState* play) { if (EN_HORSE_CHECK_1(rideActor) || (EN_HORSE_CHECK_4(rideActor) && CHECK_BTN_ALL(sControlInput->press.button, BTN_A))) { rideActor->actor.child = NULL; - func_80835DAC(play, this, func_8084D3E4, 0); + func_80835DAC(play, this, Player_Action_8084D3E4, 0); this->unk_878 = sp34 - rideActor->actor.world.pos.y; Player_AnimPlayOnce(play, this, (this->mountSide < 0) ? &gPlayerAnim_link_uma_left_down @@ -12830,12 +12974,13 @@ static u8 D_80854998[2][2] = { static Vec3s D_8085499C = { -69, 7146, -266 }; static AnimSfxEntry D_808549A4[] = { - { NA_SE_PL_CALM_HIT, 0x830 }, { NA_SE_PL_CALM_HIT, 0x83A }, { NA_SE_PL_CALM_HIT, 0x844 }, - { NA_SE_PL_CALM_PAT, 0x85C }, { NA_SE_PL_CALM_PAT, 0x86E }, { NA_SE_PL_CALM_PAT, 0x87E }, - { NA_SE_PL_CALM_PAT, 0x884 }, { NA_SE_PL_CALM_PAT, -0x888 }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 48) }, { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 58) }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 68) }, { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 92) }, + { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 110) }, { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 126) }, + { NA_SE_PL_CALM_PAT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 132) }, { NA_SE_PL_CALM_PAT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 136) }, }; -void func_8084CC98(Player* this, PlayState* play) { +void Player_Action_8084CC98(Player* this, PlayState* play) { EnHorse* rideActor = (EnHorse*)this->rideActor; u8* arr; @@ -12843,23 +12988,23 @@ void func_8084CC98(Player* this, PlayState* play) { func_8084CBF4(this, 1.0f, 10.0f); - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (LinkAnimation_Update(play, &this->skelAnime)) { this->skelAnime.animation = &gPlayerAnim_link_uma_wait_1; - this->unk_850 = 99; + this->av2.actionVar2 = 99; return; } arr = D_80854998[(this->mountSide < 0) ? 0 : 1]; if (LinkAnimation_OnFrame(&this->skelAnime, arr[0])) { - Player_PlaySfx(&this->actor, NA_SE_PL_CLIMB_CLIFF); + Player_PlaySfx(this, NA_SE_PL_CLIMB_CLIFF); return; } if (LinkAnimation_OnFrame(&this->skelAnime, arr[1])) { func_8002DE74(play, this); - Player_PlaySfx(&this->actor, NA_SE_PL_SIT_ON_HORSE); + Player_PlaySfx(this, NA_SE_PL_SIT_ON_HORSE); return; } @@ -12869,12 +13014,12 @@ void func_8084CC98(Player* this, PlayState* play) { func_8002DE74(play, this); this->skelAnime.prevTransl = D_8085499C; - if ((rideActor->animationIdx != this->unk_850) && ((rideActor->animationIdx >= 2) || (this->unk_850 >= 2))) { - if ((this->unk_850 = rideActor->animationIdx) < 2) { + if ((rideActor->animationIdx != this->av2.actionVar2) && ((rideActor->animationIdx >= 2) || (this->av2.actionVar2 >= 2))) { + if ((this->av2.actionVar2 = rideActor->animationIdx) < 2) { f32 rand = Rand_ZeroOne(); s32 temp = 0; - this->unk_850 = 1; + this->av2.actionVar2 = 1; if (rand < 0.1f) { temp = 2; @@ -12883,20 +13028,20 @@ void func_8084CC98(Player* this, PlayState* play) { } Player_AnimPlayOnce(play, this, D_8085498C[temp]); } else { - this->skelAnime.animation = D_80854944[this->unk_850 - 2]; + this->skelAnime.animation = D_80854944[this->av2.actionVar2 - 2]; Animation_SetMorph(play, &this->skelAnime, 8.0f); - if (this->unk_850 < 4) { + if (this->av2.actionVar2 < 4) { func_80834644(play, this); - this->unk_84F = 0; + this->av1.actionVar1 = 0; } } } - if (this->unk_850 == 1) { + if (this->av2.actionVar2 == 1) { if ((D_808535E0 != 0) || func_8083224C(play)) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_3); } else if (LinkAnimation_Update(play, &this->skelAnime)) { - this->unk_850 = 99; + this->av2.actionVar2 = 99; } else if (this->skelAnime.animation == &gPlayerAnim_link_uma_wait_1) { Player_ProcessAnimSfxList(this, D_808549A4); } @@ -12913,11 +13058,11 @@ void func_8084CC98(Player* this, PlayState* play) { this->csAction = 0; } this->unk_6AD = 0; - this->unk_84F = 0; - } else if ((this->unk_850 < 2) || (this->unk_850 >= 4)) { + this->av1.actionVar1 = 0; + } else if ((this->av2.actionVar2 < 2) || (this->av2.actionVar2 >= 4)) { D_808535E0 = Player_UpdateUpperBody(this, play); if (D_808535E0 != 0) { - this->unk_84F = 0; + this->av1.actionVar1 = 0; } } @@ -12925,21 +13070,21 @@ void func_8084CC98(Player* this, PlayState* play) { this->actor.world.pos.y = (rideActor->actor.world.pos.y + rideActor->riderPos.y) - 27.0f; this->actor.world.pos.z = rideActor->actor.world.pos.z + rideActor->riderPos.z; - this->currentYaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y = rideActor->actor.shape.rot.y; if ((this->csAction != 0) || - (!func_8083224C(play) && ((rideActor->actor.speedXZ != 0.0f) || !func_8083B644(this, play)) && - !func_8083C1DC(this, play))) { + (!func_8083224C(play) && ((rideActor->actor.speedXZ != 0.0f) || !Player_ActionChange_4(this, play)) && + !Player_ActionChange_6(this, play))) { if (D_808535E0 == 0) { - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { if (LinkAnimation_Update(play, &this->upperSkelAnime)) { rideActor->stateFlags &= ~ENHORSE_FLAG_8; - this->unk_84F = 0; + this->av1.actionVar1 = 0; } if (this->upperSkelAnime.animation == &gPlayerAnim_link_uma_stop_muti) { if (LinkAnimation_OnFrame(&this->upperSkelAnime, 23.0f)) { - Player_PlaySfx(&this->actor, NA_SE_IT_LASH); + Player_PlaySfx(this, NA_SE_IT_LASH); func_80832698(this, NA_SE_VO_LI_LASH); } @@ -12947,7 +13092,7 @@ void func_8084CC98(Player* this, PlayState* play) { this->upperSkelAnime.jointTable); } else { if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) { - Player_PlaySfx(&this->actor, NA_SE_IT_LASH); + Player_PlaySfx(this, NA_SE_IT_LASH); func_80832698(this, NA_SE_VO_LI_LASH); } @@ -12960,14 +13105,14 @@ void func_8084CC98(Player* this, PlayState* play) { if (EN_HORSE_CHECK_3(rideActor)) { anim = &gPlayerAnim_link_uma_stop_muti; } else if (EN_HORSE_CHECK_2(rideActor)) { - if ((this->unk_850 >= 2) && (this->unk_850 != 99)) { - anim = D_80854968[this->unk_850 - 2]; + if ((this->av2.actionVar2 >= 2) && (this->av2.actionVar2 != 99)) { + anim = D_80854968[this->av2.actionVar2 - 2]; } } if (anim != NULL) { LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim); - this->unk_84F = 1; + this->av1.actionVar1 = 1; } } } @@ -12985,7 +13130,7 @@ void func_8084CC98(Player* this, PlayState* play) { return; } - if ((this->csAction != 0) || (!func_8084C9BC(this, play) && !func_8083B040(this, play))) { + if ((this->csAction != 0) || (!func_8084C9BC(this, play) && !Player_ActionChange_13(this, play))) { if (this->unk_664 != NULL) { if (func_8002DD78(this) != 0) { this->unk_6BE = func_8083DB98(this, 1) - this->actor.shape.rot.y; @@ -13008,12 +13153,12 @@ void func_8084CC98(Player* this, PlayState* play) { } static AnimSfxEntry D_808549C4[] = { - { 0, 0x2800 }, - { NA_SE_PL_GET_OFF_HORSE, 0x80A }, - { NA_SE_PL_SLIPDOWN, -0x819 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_5, 0) }, + { NA_SE_PL_GET_OFF_HORSE, ANIMSFX_DATA(ANIMSFX_TYPE_1, 10) }, + { NA_SE_PL_SLIPDOWN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 25) }, }; -void func_8084D3E4(Player* this, PlayState* play) { +void Player_Action_8084D3E4(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; func_8084CBF4(this, 1.0f, 10.0f); @@ -13035,16 +13180,16 @@ void func_8084D3E4(Player* this, PlayState* play) { Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_NORMAL0); if (this->mountSide < 0) { - D_808549C4[0].field = 0x2828; + D_808549C4[0].data = ANIMSFX_DATA(ANIMSFX_TYPE_5, 40); } else { - D_808549C4[0].field = 0x281D; + D_808549C4[0].data = ANIMSFX_DATA(ANIMSFX_TYPE_5, 29); } Player_ProcessAnimSfxList(this, D_808549C4); } } static AnimSfxEntry D_808549D0[] = { - { NA_SE_PL_SWIM, -0x800 }, + { NA_SE_PL_SWIM, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 0) }, }; void func_8084D530(Player* this, f32* arg1, f32 arg2, s16 arg3) { @@ -13053,24 +13198,24 @@ void func_8084D530(Player* this, f32* arg1, f32 arg2, s16 arg3) { } void func_8084D574(PlayState* play, Player* this, s16 arg2) { - Player_SetupAction(play, this, func_8084D84C, 0); - this->actor.shape.rot.y = this->currentYaw = arg2; + Player_SetupAction(play, this, Player_Action_8084D84C, 0); + this->actor.shape.rot.y = this->yaw = arg2; Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim); } void func_8084D5CC(PlayState* play, Player* this) { - Player_SetupAction(play, this, func_8084DAB4, 0); + Player_SetupAction(play, this, Player_Action_8084DAB4, 0); Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim); } -void func_8084D610(Player* this, PlayState* play) { +void Player_Action_8084D610(Player* this, PlayState* play) { f32 sp34; s16 sp32; func_80832CB0(play, this, &gPlayerAnim_link_swimer_swim_wait); func_8084B000(this); - if (!func_8083224C(play) && !Player_TryActionChangeList(play, this, D_80854444, 1) && + if (!func_8083224C(play) && !Player_TryActionChangeList(play, this, sActionChangeList11, true) && !func_8083D12C(play, this, sControlInput)) { if (this->unk_6AD != 1) { this->unk_6AD = 0; @@ -13085,7 +13230,7 @@ void func_8084D610(Player* this, PlayState* play) { func_808328A0(this); } } else { - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play); if (sp34 != 0.0f) { s16 temp = this->actor.shape.rot.y - sp32; @@ -13106,20 +13251,20 @@ void func_8084D610(Player* this, PlayState* play) { } } -void func_8084D7C4(Player* this, PlayState* play) { - if (!func_8083B040(this, play)) { +void Player_Action_8084D7C4(Player* this, PlayState* play) { + if (!Player_ActionChange_13(this, play)) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; func_8084B158(play, this, NULL, this->linearVelocity); func_8084B000(this); - if (DECR(this->unk_850) == 0) { + if (DECR(this->av2.actionVar2) == 0) { func_80838F18(play, this); } } } -void func_8084D84C(Player* this, PlayState* play) { +void Player_Action_8084D84C(Player* this, PlayState* play) { f32 sp34; s16 sp32; s16 temp; @@ -13129,8 +13274,8 @@ void func_8084D84C(Player* this, PlayState* play) { func_8084B158(play, this, sControlInput, this->linearVelocity); func_8084B000(this); - if (!Player_TryActionChangeList(play, this, D_80854444, 1) && !func_8083D12C(play, this, sControlInput)) { - Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, 0.0f, play); + if (!Player_TryActionChangeList(play, this, sActionChangeList11, true) && !func_8083D12C(play, this, sControlInput)) { + Player_GetMovementSpeedAndYaw(this, &sp34, &sp32, SPEED_MODE_LINEAR, play); temp = this->actor.shape.rot.y - sp32; if ((sp34 == 0.0f) || (ABS(temp) > 0x6000) || (this->currentBoots == PLAYER_BOOTS_IRON)) { @@ -13148,16 +13293,16 @@ s32 func_8084D980(PlayState* play, Player* this, f32* arg2, s16* arg3) { s16 temp1; s32 temp2; - temp1 = this->currentYaw - *arg3; + temp1 = this->yaw - *arg3; if (ABS(temp1) > 0x6000) { anim = &gPlayerAnim_link_swimer_swim_wait; if (Math_StepToF(&this->linearVelocity, 0.0f, 1.0f)) { - this->currentYaw = *arg3; + this->yaw = *arg3; } else { *arg2 = 0.0f; - *arg3 = this->currentYaw; + *arg3 = this->yaw; } } else { temp2 = func_8083FD78(this, arg2, arg3, play); @@ -13181,15 +13326,15 @@ s32 func_8084D980(PlayState* play, Player* this, f32* arg2, s16* arg3) { return 0; } -void func_8084DAB4(Player* this, PlayState* play) { +void Player_Action_8084DAB4(Player* this, PlayState* play) { f32 sp2C; s16 sp2A; func_8084B158(play, this, sControlInput, this->linearVelocity); func_8084B000(this); - if (!Player_TryActionChangeList(play, this, D_80854444, 1) && !func_8083D12C(play, this, sControlInput)) { - Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); + if (!Player_TryActionChangeList(play, this, sActionChangeList11, true) && !func_8083D12C(play, this, sControlInput)) { + Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play); if (sp2C == 0.0f) { func_80838F18(play, this); @@ -13207,33 +13352,33 @@ void func_8084DBC4(PlayState* play, Player* this, f32 arg2) { f32 sp2C; s16 sp2A; - Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, 0.0f, play); + Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_LINEAR, play); func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A); // Original implementation of func_8084AEEC (SurfaceWithoutSwimMod) to prevent velocity increases via swim mod which push Link into the air // #region SOH [Enhancement] if (CVarGetInteger("gEnableWalkModify", 0)) { - SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->currentYaw); + SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->yaw); // #endregion } else { - func_8084AEEC(this, &this->actor.velocity.y, arg2, this->currentYaw); + func_8084AEEC(this, &this->actor.velocity.y, arg2, this->yaw); } } -void func_8084DC48(Player* this, PlayState* play) { +void Player_Action_8084DC48(Player* this, PlayState* play) { f32 sp2C; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; this->actor.gravity = 0.0f; Player_UpdateUpperBody(this, play); - if (!func_8083B040(this, play)) { + if (!Player_ActionChange_13(this, play)) { if (this->currentBoots == PLAYER_BOOTS_IRON) { func_80838F18(play, this); return; } - if (this->unk_84F == 0) { - if (this->unk_850 == 0) { + if (this->av1.actionVar1 == 0) { + if (this->av2.actionVar2 == 0) { if (LinkAnimation_Update(play, &this->skelAnime) || ((this->skelAnime.curFrame >= 22.0f) && !CHECK_BTN_ALL(sControlInput->cur.button, BTN_A))) { func_8083D330(play, this); @@ -13248,24 +13393,24 @@ void func_8084DC48(Player* this, PlayState* play) { func_8084B158(play, this, sControlInput, this->actor.velocity.y); this->unk_6C2 = 16000; - if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A) && !func_8083E5A8(this, play) && + if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_A) && !Player_ActionChange_2(this, play) && !(this->actor.bgCheckFlags & 1) && (this->actor.yDistToWater < D_80854784[CUR_UPG_VALUE(UPG_SCALE)])) { func_8084DBC4(play, this, -2.0f); } else { - this->unk_84F++; + this->av1.actionVar1++; Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait); } - } else if (this->unk_84F == 1) { + } else if (this->av1.actionVar1 == 1) { LinkAnimation_Update(play, &this->skelAnime); func_8084B000(this); if (this->unk_6C2 < 10000) { - this->unk_84F++; - this->unk_850 = this->actor.yDistToWater; + this->av1.actionVar1++; + this->av2.actionVar2 = this->actor.yDistToWater; Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim); } } else if (!func_8083D12C(play, this, sControlInput)) { - sp2C = (this->unk_850 * 0.018f) + 4.0f; + sp2C = (this->av2.actionVar2 * 0.018f) + 4.0f; if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { sControlInput = NULL; @@ -13295,7 +13440,7 @@ void func_8084DFAC(PlayState* play, Player* this) { func_8084DF6C(play, this); func_808322FC(this); func_8083C0E8(this, play); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } s32 func_8084DFF4(PlayState* play, Player* this) { @@ -13309,13 +13454,13 @@ s32 func_8084DFF4(PlayState* play, Player* this) { return 1; } - if (this->unk_84F == 0) { + if (this->av1.actionVar1 == 0) { if (this->getItemEntry.objectId == OBJECT_INVALID || (this->getItemId != this->getItemEntry.getItemId)) { giEntry = ItemTable_Retrieve(this->getItemId); } else { giEntry = this->getItemEntry; } - this->unk_84F = 1; + this->av1.actionVar1 = 1; equipItem = giEntry.itemId; equipNow = CVarGetInteger("gAskToEquip", 0) && giEntry.modIndex == MOD_NONE && equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_TUNIC_ZORA && @@ -13426,7 +13571,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { return 0; } -void func_8084E1EC(Player* this, PlayState* play) { +void Player_Action_8084E1EC(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -13449,7 +13594,7 @@ void func_8084E1EC(Player* this, PlayState* play) { func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y); } -void func_8084E30C(Player* this, PlayState* play) { +void Player_Action_8084E30C(Player* this, PlayState* play) { func_8084B000(this); if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -13459,7 +13604,7 @@ void func_8084E30C(Player* this, PlayState* play) { func_8084AEEC(this, &this->linearVelocity, 0.0f, this->actor.shape.rot.y); } -void func_8084E368(Player* this, PlayState* play) { +void Player_Action_8084E368(Player* this, PlayState* play) { func_8084B000(this); if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -13478,10 +13623,10 @@ static s16 sWarpSongEntrances[] = { ENTR_TEMPLE_OF_TIME_7, }; -void func_8084E3C4(Player* this, PlayState* play) { +void Player_Action_8084E3C4(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_normal_okarina_swing); - this->unk_850 = 1; + this->av2.actionVar2 = 1; if (this->stateFlags2 & (PLAYER_STATE2_NEAR_OCARINA_ACTOR | PLAYER_STATE2_PLAY_FOR_ACTOR)) { this->stateFlags2 |= PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR; } else { @@ -13490,7 +13635,7 @@ void func_8084E3C4(Player* this, PlayState* play) { return; } - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { return; } @@ -13503,7 +13648,7 @@ void func_8084E3C4(Player* this, PlayState* play) { this->targetActor = this->naviActor; this->naviActor->textId = -this->naviTextId; Player_StartTalking(play, this->targetActor); - } else if (!func_8083B040(this, play)) { + } else if (!Player_ActionChange_13(this, play)) { func_8083A098(this, &gPlayerAnim_link_normal_okarina_end, play); } @@ -13532,7 +13677,7 @@ void func_8084E3C4(Player* this, PlayState* play) { } } -void func_8084E604(Player* this, PlayState* play) { +void Player_Action_8084E604(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_8083A098(this, &gPlayerAnim_link_normal_light_bom_end, play); } else if (LinkAnimation_OnFrame(&this->skelAnime, 3.0f)) { @@ -13547,22 +13692,22 @@ void func_8084E604(Player* this, PlayState* play) { } static AnimSfxEntry D_808549E0[] = { - { 0, 0x3857 }, - { NA_SE_VO_LI_CLIMB_END, 0x2057 }, - { NA_SE_VO_LI_AUTO_JUMP, 0x2045 }, - { 0, -0x287B }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_7, 87) }, + { NA_SE_VO_LI_CLIMB_END, ANIMSFX_DATA(ANIMSFX_TYPE_4, 87) }, + { NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 69) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 123) }, }; -void func_8084E6D4(Player* this, PlayState* play) { +void Player_Action_8084E6D4(Player* this, PlayState* play) { s32 cond; if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_850 != 0) { - if (this->unk_850 >= 2) { - this->unk_850--; + if (this->av2.actionVar2 != 0) { + if (this->av2.actionVar2 >= 2) { + this->av2.actionVar2--; } - if (func_8084DFF4(play, this) && (this->unk_850 == 1)) { + if (func_8084DFF4(play, this) && (this->av2.actionVar2 == 1)) { cond = ((this->targetActor != NULL) && (this->exchangeItemId < 0)) || (this->stateFlags3 & PLAYER_STATE3_FORCE_PULL_OCARINA); @@ -13607,11 +13752,11 @@ void func_8084E6D4(Player* this, PlayState* play) { Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_demo_get_itemA); } - this->unk_850 = 2; + this->av2.actionVar2 = 2; func_80835EA4(play, 9); } } else { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (!LINK_IS_ADULT) { Player_ProcessAnimSfxList(this, D_808549E0); } @@ -13629,7 +13774,7 @@ void func_8084E6D4(Player* this, PlayState* play) { } static AnimSfxEntry D_808549F0[] = { - { NA_SE_IT_MASTER_SWORD_SWING, -0x83C }, + { NA_SE_IT_MASTER_SWORD_SWING, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 60) }, }; void func_8084E988(Player* this) { @@ -13637,15 +13782,15 @@ void func_8084E988(Player* this) { } static AnimSfxEntry D_808549F4[] = { - { NA_SE_VO_LI_AUTO_JUMP, 0x2005 }, - { 0, -0x280F }, + { NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 5) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 15) }, }; -void func_8084E9AC(Player* this, PlayState* play) { +void Player_Action_8084E9AC(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_84F == 0) { - if (DECR(this->unk_850) == 0) { - this->unk_84F = 1; + if (this->av1.actionVar1 == 0) { + if (DECR(this->av2.actionVar2) == 0) { + this->av1.actionVar1 = 1; this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; } } else { @@ -13669,9 +13814,9 @@ static u8 D_808549FC[] = { 0x01, 0x03, 0x02, 0x04, 0x04, }; -void func_8084EAC0(Player* this, PlayState* play) { +void Player_Action_8084EAC0(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (this->itemAction == PLAYER_IA_BOTTLE_POE) { s32 rand = Rand_S16Offset(-1, 3); @@ -13777,20 +13922,20 @@ void func_8084EAC0(Player* this, PlayState* play) { } Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_wait); - this->unk_850 = 1; + this->av2.actionVar2 = 1; return; } func_8083C0E8(this, play); func_8005B1A4(Play_GetCamera(play, 0)); - } else if (this->unk_850 == 1) { + } else if (this->av2.actionVar2 == 1) { if ((gSaveContext.healthAccumulator == 0) && (gSaveContext.magicState != MAGIC_STATE_FILL)) { Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_end); - this->unk_850 = 2; + this->av2.actionVar2 = 2; Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE); } func_80832698(this, NA_SE_VO_LI_DRINK - SFX_FLAG); - } else if ((this->unk_850 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 29.0f)) { + } else if ((this->av2.actionVar2 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 29.0f)) { func_80832698(this, NA_SE_VO_LI_BREATH_DRINK); } } @@ -13802,41 +13947,41 @@ static BottleCatchInfo D_80854A04[] = { { ACTOR_EN_INSECT, ITEM_BUG, 0x21, 0x7A }, }; -void func_8084ECA4(Player* this, PlayState* play) { +void Player_Action_8084ECA4(Player* this, PlayState* play) { struct_80854554* sp24; BottleCatchInfo* catchInfo; s32 temp; s32 i; - sp24 = &D_80854554[this->unk_850]; + sp24 = &D_80854554[this->av2.actionVar2]; func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_84F != 0) { - if (this->unk_850 == 0) { + if (this->av1.actionVar1 != 0) { + if (this->av2.actionVar2 == 0) { if (CVarGetInteger("gFastDrops", 0)) { - this->unk_84F = 0; + this->av1.actionVar1 = 0; } else { - Message_StartTextbox(play, D_80854A04[this->unk_84F - 1].textId, &this->actor); + Message_StartTextbox(play, D_80854A04[this->av1.actionVar1 - 1].textId, &this->actor); } Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } else if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { - this->unk_84F = 0; + this->av1.actionVar1 = 0; func_8005B1A4(Play_GetCamera(play, 0)); } } else { func_8083C0E8(this, play); } } else { - if (this->unk_84F == 0) { + if (this->av1.actionVar1 == 0) { temp = this->skelAnime.curFrame - sp24->unk_08; if (temp >= 0) { if (sp24->unk_09 >= temp) { - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { if (temp == 0) { - Player_PlaySfx(&this->actor, NA_SE_IT_SCOOP_UP_WATER); + Player_PlaySfx(this, NA_SE_IT_SCOOP_UP_WATER); } } @@ -13849,8 +13994,8 @@ void func_8084ECA4(Player* this, PlayState* play) { } if (i < 4) { - this->unk_84F = i + 1; - this->unk_850 = 0; + this->av1.actionVar1 = i + 1; + this->av2.actionVar2 = 0; this->interactRangeActor->parent = &this->actor; Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction)); if (!CVarGetInteger("gFastDrops", 0)) { @@ -13875,7 +14020,7 @@ void func_8084ECA4(Player* this, PlayState* play) { static Vec3f D_80854A1C = { 0.0f, 0.0f, 5.0f }; -void func_8084EED8(Player* this, PlayState* play) { +void Player_Action_8084EED8(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_8083C0E8(this, play); func_8005B1A4(Play_GetCamera(play, 0)); @@ -13885,8 +14030,8 @@ void func_8084EED8(Player* this, PlayState* play) { if (LinkAnimation_OnFrame(&this->skelAnime, 37.0f)) { Player_SpawnFairy(play, this, &this->leftHandPos, &D_80854A1C, FAIRY_REVIVE_BOTTLE); Player_UpdateBottleHeld(play, this, ITEM_BOTTLE, PLAYER_IA_BOTTLE); - Player_PlaySfx(&this->actor, NA_SE_EV_BOTTLE_CAP_OPEN); - Player_PlaySfx(&this->actor, NA_SE_EV_FIATY_HEAL - SFX_FLAG); + Player_PlaySfx(this, NA_SE_EV_BOTTLE_CAP_OPEN); + Player_PlaySfx(this, NA_SE_EV_FIATY_HEAL - SFX_FLAG); } else if (LinkAnimation_OnFrame(&this->skelAnime, 47.0f)) { if (CVarGetInteger("gFairyEffect", 0)) { if (CVarGetInteger("gFairyPercentRestore", 0)) { @@ -13908,11 +14053,11 @@ static BottleDropInfo D_80854A28[] = { }; static AnimSfxEntry D_80854A34[] = { - { NA_SE_VO_LI_AUTO_JUMP, 0x2026 }, - { NA_SE_EV_BOTTLE_CAP_OPEN, -0x828 }, + { NA_SE_VO_LI_AUTO_JUMP, ANIMSFX_DATA(ANIMSFX_TYPE_4, 38) }, + { NA_SE_EV_BOTTLE_CAP_OPEN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 40) }, }; -void func_8084EFC0(Player* this, PlayState* play) { +void Player_Action_8084EFC0(Player* this, PlayState* play) { func_8083721C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { @@ -13937,14 +14082,14 @@ void func_8084EFC0(Player* this, PlayState* play) { } static AnimSfxEntry D_80854A3C[] = { - { NA_SE_PL_PUT_OUT_ITEM, -0x81E }, + { NA_SE_PL_PUT_OUT_ITEM, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 30) }, }; -void func_8084F104(Player* this, PlayState* play) { +void Player_Action_8084F104(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_850 < 0) { + if (this->av2.actionVar2 < 0) { func_8083C0E8(this, play); } else if (this->exchangeItemId == EXCH_ITEM_NONE) { Actor* targetActor = this->targetActor; @@ -13966,21 +14111,21 @@ void func_8084F104(Player* this, PlayState* play) { } } - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { Message_StartTextbox(play, this->actor.textId, &this->actor); if ((this->itemAction == PLAYER_IA_CHICKEN) || (this->itemAction == PLAYER_IA_POCKET_CUCCO)) { - Player_PlaySfx(&this->actor, NA_SE_EV_CHICKEN_CRY_M); + Player_PlaySfx(this, NA_SE_EV_CHICKEN_CRY_M); } - this->unk_850 = 1; + this->av2.actionVar2 = 1; } else if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO; this->unk_862 = 0; - if (this->unk_84F == 1) { + if (this->av1.actionVar1 == 1) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_bottle_read_end); - this->unk_850 = -1; + this->av2.actionVar2 = -1; } else { func_8083C0E8(this, play); } @@ -13988,12 +14133,12 @@ void func_8084F104(Player* this, PlayState* play) { func_8005B1A4(Play_GetCamera(play, 0)); } } - } else if (this->unk_850 >= 0) { + } else if (this->av2.actionVar2 >= 0) { Player_ProcessAnimSfxList(this, D_80854A3C); } - if ((this->unk_84F == 0) && (this->unk_664 != NULL)) { - this->currentYaw = this->actor.shape.rot.y = func_8083DB98(this, 0); + if ((this->av1.actionVar1 == 0) && (this->unk_664 != NULL)) { + this->yaw = this->actor.shape.rot.y = func_8083DB98(this, 0); } } @@ -14010,7 +14155,7 @@ void func_8084F308(Player* this, PlayState* play) { } } -void func_8084F390(Player* this, PlayState* play) { +void Player_Action_8084F390(Player* this, PlayState* play) { CollisionPoly* floorPoly; f32 sp50; f32 sp4C; @@ -14024,7 +14169,7 @@ void func_8084F390(Player* this, PlayState* play) { func_8084269C(play, this); func_800F4138(&this->actor.projectedPos, NA_SE_PL_SLIP_LEVEL - SFX_FLAG, this->actor.speedXZ); - if (func_8083B040(this, play) == 0) { + if (Player_ActionChange_13(this, play) == 0) { floorPoly = this->actor.floorPoly; if (floorPoly == NULL) { @@ -14035,7 +14180,7 @@ void func_8084F390(Player* this, PlayState* play) { Player_GetSlopeDirection(floorPoly, &sp38, &sp46); sp44 = sp46; - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { sp44 = sp46 + 0x8000; } @@ -14059,7 +14204,7 @@ void func_8084F390(Player* this, PlayState* play) { if (Math_AsymStepToF(&this->linearVelocity, sp50, sp4C, sp48) && (sp50 == 0)) { LinkAnimationHeader* anim; - if (this->unk_84F == 0) { + if (this->av1.actionVar1 == 0) { anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_down_slope_slip_end, this->modelAnimType); } else { anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_up_slope_slip_end, this->modelAnimType); @@ -14067,38 +14212,38 @@ void func_8084F390(Player* this, PlayState* play) { func_8083A098(this, anim, play); } - Math_SmoothStepToS(&this->currentYaw, sp46, 10, 4000, 800); + Math_SmoothStepToS(&this->yaw, sp46, 10, 4000, 800); Math_ScaledStepToS(&this->actor.shape.rot.y, sp44, 2000); } } -void func_8084F608(Player* this, PlayState* play) { - if ((DECR(this->unk_850) == 0) && Player_StartCsAction(play, this)) { +void Player_Action_8084F608(Player* this, PlayState* play) { + if ((DECR(this->av2.actionVar2) == 0) && Player_StartCsAction(play, this)) { func_80852280(play, this, NULL); - Player_SetupAction(play, this, func_80852E14, 0); - func_80852E14(this, play); + Player_SetupAction(play, this, Player_Action_CsAction, 0); + Player_Action_CsAction(this, play); } } -void func_8084F698(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_8084F608, 0); - this->unk_850 = 40; +void Player_Action_8084F698(Player* this, PlayState* play) { + Player_SetupAction(play, this, Player_Action_8084F608, 0); + this->av2.actionVar2 = 40; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_KANKYO, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0x10, true); } -void func_8084F710(Player* this, PlayState* play) { +void Player_Action_8084F710(Player* this, PlayState* play) { s32 pad; - if ((this->unk_84F != 0) && (play->csCtx.frames < 0x131)) { + if ((this->av1.actionVar1 != 0) && (play->csCtx.frames < 0x131)) { this->actor.gravity = 0.0f; this->actor.velocity.y = 0.0f; } else if (sYDistToFloor < 150.0f) { if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (this->actor.bgCheckFlags & 1) { this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; func_808328A0(this); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } } else { if ((play->sceneNum == SCENE_KOKIRI_FOREST) && Player_StartCsAction(play, this)) { @@ -14121,16 +14266,16 @@ void func_8084F710(Player* this, PlayState* play) { } } -void func_8084F88C(Player* this, PlayState* play) { +void Player_Action_8084F88C(Player* this, PlayState* play) { LinkAnimation_Update(play, &this->skelAnime); - if ((this->unk_850++ > 8) && (play->transitionTrigger == TRANS_TRIGGER_OFF)) { + if ((this->av2.actionVar2++ > 8) && (play->transitionTrigger == TRANS_TRIGGER_OFF)) { - if (this->unk_84F != 0) { + if (this->av1.actionVar1 != 0) { if (play->sceneNum == SCENE_ICE_CAVERN) { Play_TriggerRespawn(play); play->nextEntranceIndex = ENTR_ICE_CAVERN_0; - } else if (this->unk_84F < 0) { + } else if (this->av1.actionVar1 < 0) { Play_TriggerRespawn(play); // In ER, handle DMT and other special void outs to respawn from last entrance from grotto if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { @@ -14153,11 +14298,11 @@ void func_8084F88C(Player* this, PlayState* play) { } } -void func_8084F9A0(Player* this, PlayState* play) { - func_80839800(this, play); +void Player_Action_8084F9A0(Player* this, PlayState* play) { + Player_ActionChange_1(this, play); } -void func_8084F9C0(Player* this, PlayState* play) { +void Player_Action_8084F9C0(Player* this, PlayState* play) { this->actor.gravity = -1.0f; LinkAnimation_Update(play, &this->skelAnime); @@ -14169,7 +14314,7 @@ void func_8084F9C0(Player* this, PlayState* play) { } } -void func_8084FA54(Player* this, PlayState* play) { +void Player_Action_8084FA54(Player* this, PlayState* play) { this->unk_6AD = 2; func_8083AD4C(play, this); @@ -14187,16 +14332,16 @@ void func_8084FA54(Player* this, PlayState* play) { } } -void func_8084FB10(Player* this, PlayState* play) { - if (this->unk_84F >= 0) { - if (this->unk_84F < 6) { - this->unk_84F++; +void Player_Action_8084FB10(Player* this, PlayState* play) { + if (this->av1.actionVar1 >= 0) { + if (this->av1.actionVar1 < 6) { + this->av1.actionVar1++; } if (func_80832594(this, 1, 100)) { - this->unk_84F = -1; + this->av1.actionVar1 = -1; EffectSsIcePiece_SpawnBurst(play, &this->actor.world.pos, this->actor.scale.x); - Player_PlaySfx(&this->actor, NA_SE_PL_ICE_BROKEN); + Player_PlaySfx(this, NA_SE_PL_ICE_BROKEN); } else { this->stateFlags2 |= PLAYER_STATE2_FROZEN; } @@ -14212,17 +14357,17 @@ void func_8084FB10(Player* this, PlayState* play) { } } -void func_8084FBF4(Player* this, PlayState* play) { +void Player_Action_8084FBF4(Player* this, PlayState* play) { LinkAnimation_Update(play, &this->skelAnime); func_808382BC(this); - if (((this->unk_850 % 25) != 0) || func_80837B18(play, this, -1)) { - if (DECR(this->unk_850) == 0) { + if (((this->av2.actionVar2 % 25) != 0) || func_80837B18(play, this, -1)) { + if (DECR(this->av2.actionVar2) == 0) { func_80839F90(this, play); } } - this->shockTimer = 40; + this->bodyShockTimer = 40; func_8002F8F0(&this->actor, NA_SE_VO_LI_TAKEN_AWAY - SFX_FLAG + this->ageProperties->unk_92); } @@ -14357,7 +14502,7 @@ void Player_UpdateBunnyEars(Player* this) { } } -s32 func_80850224(Player* this, PlayState* play) { +s32 Player_ActionChange_7(Player* this, PlayState* play) { if (func_8083C6B8(play, this) == 0) { if (func_8083BB20(this) != 0) { s32 sp24 = func_80837818(this); @@ -14379,7 +14524,7 @@ s32 func_80850224(Player* this, PlayState* play) { static Vec3f D_80854A40 = { 0.0f, 40.0f, 45.0f }; -void func_808502D0(Player* this, PlayState* play) { +void Player_Action_808502D0(Player* this, PlayState* play) { struct_80854190* sp44 = &D_80854190[this->meleeWeaponAnimation]; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; @@ -14401,7 +14546,7 @@ void func_808502D0(Player* this, PlayState* play) { func_8083C50C(this); if (LinkAnimation_Update(play, &this->skelAnime)) { - if (!func_80850224(this, play)) { + if (!Player_ActionChange_7(this, play)) { u8 sp43 = this->skelAnime.moveFlags; LinkAnimationHeader* sp3C; @@ -14448,7 +14593,7 @@ void func_808502D0(Player* this, PlayState* play) { } } -void func_808505DC(Player* this, PlayState* play) { +void Player_Action_808505DC(Player* this, PlayState* play) { LinkAnimation_Update(play, &this->skelAnime); func_8083721C(this); @@ -14457,15 +14602,15 @@ void func_808505DC(Player* this, PlayState* play) { } } -void func_8085063C(Player* this, PlayState* play) { +void Player_Action_8085063C(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; LinkAnimation_Update(play, &this->skelAnime); Player_UpdateUpperBody(this, play); - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { Message_StartTextbox(play, 0x3B, &this->actor); - this->unk_850 = 1; + this->av2.actionVar2 = 1; return; } @@ -14492,17 +14637,17 @@ void func_8085063C(Player* this, PlayState* play) { } } -void func_8085076C(Player* this, PlayState* play) { +void Player_Action_8085076C(Player* this, PlayState* play) { s32 respawnData = gSaveContext.respawn[RESPAWN_MODE_TOP].data; - if (this->unk_850 > 20) { + if (this->av2.actionVar2 > 20) { this->actor.draw = Player_Draw; this->actor.world.pos.y += 60.0f; func_80837B9C(this, play); return; } - if (this->unk_850++ == 20) { + if (this->av2.actionVar2++ == 20) { gSaveContext.respawn[RESPAWN_MODE_TOP].data = respawnData + 1; func_80078914(&gSaveContext.respawn[RESPAWN_MODE_TOP].pos, NA_SE_PL_MAGIC_WIND_WARP); } @@ -14529,61 +14674,61 @@ static LinkAnimationHeader* D_80854A70[] = { static u8 D_80854A7C[] = { 70, 10, 10 }; static AnimSfxEntry D_80854A80[] = { - { NA_SE_PL_SKIP, 0x814 }, - { NA_SE_VO_LI_SWORD_N, 0x2014 }, - { 0, -0x301A }, + { NA_SE_PL_SKIP, ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) }, + { NA_SE_VO_LI_SWORD_N, ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 26) }, }; static AnimSfxEntry D_80854A8C[][2] = { { - { 0, 0x4014 }, - { NA_SE_VO_LI_MAGIC_FROL, -0x201E }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) }, + { NA_SE_VO_LI_MAGIC_FROL, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 30) }, }, { - { 0, 0x4014 }, - { NA_SE_VO_LI_MAGIC_NALE, -0x202C }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 20) }, + { NA_SE_VO_LI_MAGIC_NALE, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 44) }, }, { - { NA_SE_VO_LI_MAGIC_ATTACK, 0x2014 }, - { NA_SE_IT_SWORD_SWING_HARD, -0x814 }, + { NA_SE_VO_LI_MAGIC_ATTACK, ANIMSFX_DATA(ANIMSFX_TYPE_4, 20) }, + { NA_SE_IT_SWORD_SWING_HARD, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 20) }, }, }; -void func_808507F4(Player* this, PlayState* play) { +void Player_Action_808507F4(Player* this, PlayState* play) { u8 isFastFarores = CVarGetInteger("gFastFarores", 0) && this->itemAction == PLAYER_IA_FARORES_WIND; if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_84F < 0) { + if (this->av1.actionVar1 < 0) { if ((this->itemAction == PLAYER_IA_NAYRUS_LOVE) || isFastFarores || (gSaveContext.magicState == MAGIC_STATE_IDLE)) { func_80839FFC(this, play); func_8005B1A4(Play_GetCamera(play, 0)); } } else { - if (this->unk_850 == 0) { - LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A58[this->unk_84F], 0.83f * (isFastFarores ? 2 : 1)); + if (this->av2.actionVar2 == 0) { + LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A58[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1)); - if (func_80846A00(play, this, this->unk_84F) != NULL) { + if (func_80846A00(play, this, this->av1.actionVar1) != NULL) { this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE; - if ((this->unk_84F != 0) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) { + if ((this->av1.actionVar1 != 0) || (gSaveContext.respawn[RESPAWN_MODE_TOP].data <= 0)) { gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP; } } else { Magic_Reset(play); } } else { - LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, D_80854A64[this->unk_84F], 0.83f * (isFastFarores ? 2 : 1)); + LinkAnimation_PlayLoopSetSpeed(play, &this->skelAnime, D_80854A64[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1)); - if (this->unk_84F == 0) { - this->unk_850 = -10; + if (this->av1.actionVar1 == 0) { + this->av2.actionVar2 = -10; } } - this->unk_850++; + this->av2.actionVar2++; } } else { - if (this->unk_850 < 0) { - this->unk_850++; + if (this->av2.actionVar2 < 0) { + this->av2.actionVar2++; - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { gSaveContext.respawn[RESPAWN_MODE_TOP].data = 1; Play_SetupRespawnPoint(play, RESPAWN_MODE_TOP, 0x6FF); gSaveContext.fw.set = 1; @@ -14596,20 +14741,20 @@ void func_808507F4(Player* this, PlayState* play) { gSaveContext.fw.roomIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex; gSaveContext.fw.tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags; gSaveContext.fw.tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags; - this->unk_850 = 2; + this->av2.actionVar2 = 2; } - } else if (this->unk_84F >= 0) { - if (this->unk_850 == 0) { + } else if (this->av1.actionVar1 >= 0) { + if (this->av2.actionVar2 == 0) { Player_ProcessAnimSfxList(this, D_80854A80); - } else if (this->unk_850 == 1) { - Player_ProcessAnimSfxList(this, D_80854A8C[this->unk_84F]); - if ((this->unk_84F == 2) && LinkAnimation_OnFrame(&this->skelAnime, 30.0f)) { + } else if (this->av2.actionVar2 == 1) { + Player_ProcessAnimSfxList(this, D_80854A8C[this->av1.actionVar1]); + if ((this->av1.actionVar1 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 30.0f)) { this->stateFlags1 &= ~(PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE); } - } else if ((isFastFarores ? 10 : D_80854A7C[this->unk_84F]) < this->unk_850++) { - LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A70[this->unk_84F], 0.83f * (isFastFarores ? 2 : 1)); - this->currentYaw = this->actor.shape.rot.y; - this->unk_84F = -1; + } else if ((isFastFarores ? 10 : D_80854A7C[this->av1.actionVar1]) < this->av2.actionVar2++) { + LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80854A70[this->av1.actionVar1], 0.83f * (isFastFarores ? 2 : 1)); + this->yaw = this->actor.shape.rot.y; + this->av1.actionVar1 = -1; } } } @@ -14617,7 +14762,7 @@ void func_808507F4(Player* this, PlayState* play) { func_8083721C(this); } -void func_80850AEC(Player* this, PlayState* play) { +void Player_Action_80850AEC(Player* this, PlayState* play) { f32 temp; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET; @@ -14655,8 +14800,8 @@ void func_80850AEC(Player* this, PlayState* play) { } } -void func_80850C68(Player* this, PlayState* play) { - if ((this->unk_850 != 0) && ((this->unk_858 != 0.0f) || (this->unk_85C != 0.0f))) { +void Player_Action_80850C68(Player* this, PlayState* play) { + if ((this->av2.actionVar2 != 0) && ((this->unk_858 != 0.0f) || (this->unk_85C != 0.0f))) { f32 updateScale = R_UPDATE_RATE * 0.5f; this->skelAnime.curFrame += this->skelAnime.playSpeed * updateScale; @@ -14676,7 +14821,7 @@ void func_80850C68(Player* this, PlayState* play) { } else if (LinkAnimation_Update(play, &this->skelAnime)) { this->unk_860 = 2; Player_AnimPlayLoop(play, this, &gPlayerAnim_link_fishing_wait); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } func_8083721C(this); @@ -14684,12 +14829,12 @@ void func_80850C68(Player* this, PlayState* play) { if (this->unk_860 == 0) { func_80853080(this, play); } else if (this->unk_860 == 3) { - Player_SetupAction(play, this, func_80850E84, 0); + Player_SetupAction(play, this, Player_Action_80850E84, 0); Player_AnimChangeOnceMorph(play, this, &gPlayerAnim_link_fishing_fish_catch); } } -void func_80850E84(Player* this, PlayState* play) { +void Player_Action_80850E84(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime) && (this->unk_860 == 0)) { func_8083A098(this, &gPlayerAnim_link_fishing_fish_catch_end, play); } @@ -14702,18 +14847,22 @@ static void (*D_80854AA4[])(PlayState*, Player*, void*) = { }; static AnimSfxEntry D_80854AF0[] = { - { 0, 0x2822 }, - { NA_SE_PL_CALM_HIT, 0x82D }, - { NA_SE_PL_CALM_HIT, 0x833 }, - { NA_SE_PL_CALM_HIT, -0x840 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_5, 34) }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 45) }, + { NA_SE_PL_CALM_HIT, ANIMSFX_DATA(ANIMSFX_TYPE_1, 51) }, + { NA_SE_PL_CALM_HIT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 64) }, }; static AnimSfxEntry D_80854B00[] = { - { NA_SE_VO_LI_SURPRISE, 0x2003 }, { 0, 0x300F }, { 0, 0x3018 }, { 0, 0x301E }, { NA_SE_VO_LI_FALL_L, -0x201F }, + { NA_SE_VO_LI_SURPRISE, ANIMSFX_DATA(ANIMSFX_TYPE_4, 3) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 15) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 24) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 30) }, + { NA_SE_VO_LI_FALL_L, -ANIMSFX_DATA(ANIMSFX_TYPE_4, 31) }, }; static AnimSfxEntry D_80854B14[] = { - { 0, -0x300A }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) }, }; static struct_80854B18 D_80854B18[] = { @@ -15008,7 +15157,7 @@ void func_808511D4(PlayState* play, Player* this, void* anim) { void func_808511FC(PlayState* play, Player* this, void* anim) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimChangeLoopMorphAdjustedZeroRootYawSpeed(play, this, anim); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } } @@ -15022,7 +15171,7 @@ void func_80851248(PlayState* play, Player* this, void* anim) { void func_80851294(PlayState* play, Player* this, void* anim) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplaceNormalPlayLoopAdjusted(play, this, anim); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } } @@ -15054,19 +15203,19 @@ void func_80851368(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_808513BC(PlayState* play, Player* this, CsCmdActorAction* arg2) { this->actor.gravity = 0.0f; - if (this->unk_84F == 0) { + if (this->av1.actionVar1 == 0) { if (func_8083D12C(play, this, NULL)) { - this->unk_84F = 1; + this->av1.actionVar1 = 1; } else { func_8084B158(play, this, NULL, fabsf(this->actor.velocity.y)); Math_ScaledStepToS(&this->unk_6C2, -10000, 800); - func_8084AEEC(this, &this->actor.velocity.y, 4.0f, this->currentYaw); + func_8084AEEC(this, &this->actor.velocity.y, 4.0f, this->yaw); } return; } if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->unk_84F == 1) { + if (this->av1.actionVar1 == 1) { Player_AnimChangeLoopSlowMorph(play, this, &gPlayerAnim_link_swimer_swim_wait); } else { Player_AnimPlayLoop(play, this, &gPlayerAnim_link_swimer_swim_wait); @@ -15093,7 +15242,7 @@ void func_808514C0(PlayState* play, Player* this, CsCmdActorAction* arg2) { } if ((this->interactRangeActor != NULL) && (this->interactRangeActor->textId == 0xFFFF)) { - func_8083E5A8(this, play); + Player_ActionChange_2(this, play); } } @@ -15143,8 +15292,8 @@ void func_80851688(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_80855188[] = { - { 0, 0x302A }, - { 0, -0x3030 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 42) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 48) }, }; void func_80851750(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15155,7 +15304,7 @@ void func_80851750(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80851788(PlayState* play, Player* this, CsCmdActorAction* arg2) { this->stateFlags1 &= ~PLAYER_STATE1_THREW_BOOMERANG; - this->currentYaw = this->actor.shape.rot.y = this->actor.world.rot.y = + this->yaw = this->actor.shape.rot.y = this->actor.world.rot.y = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_450); if (this->linearVelocity <= 0.0f) { @@ -15171,7 +15320,7 @@ void func_80851828(PlayState* play, Player* this, CsCmdActorAction* arg2) { func_80845BA0(play, this, &sp1C, 10); if (play->sceneNum == SCENE_JABU_JABU_BOSS) { - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) { return; } @@ -15182,8 +15331,8 @@ void func_80851828(PlayState* play, Player* this, CsCmdActorAction* arg2) { } } - this->unk_850++; - if (this->unk_850 > 20) { + this->av2.actionVar2++; + if (this->av2.actionVar2 > 20) { this->csAction = 0xB; } } @@ -15195,10 +15344,10 @@ void func_808518DC(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_8085190C(PlayState* play, Player* this, CsCmdActorAction* arg2) { func_80851314(this); - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoop(play, this, func_808334E4(this)); - this->unk_850 = 0; + this->av2.actionVar2 = 0; } func_80833C3C(this); @@ -15236,8 +15385,8 @@ static struct_808551A4 D_808551A4[] = { }; static AnimSfxEntry D_808551AC[] = { - { 0, 0x401D }, - { 0, -0x4027 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 29) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 39) }, }; void func_80851A50(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15258,7 +15407,7 @@ void func_80851A50(PlayState* play, Player* this, CsCmdActorAction* arg2) { } this->leftHandDLists = &dLists[gSaveContext.linkAge]; - Player_PlaySfx(&this->actor, sp2C->unk_00); + Player_PlaySfx(this, sp2C->unk_00); if (!LINK_IS_ADULT) { func_80832698(this, sp2C->unk_02); } @@ -15277,16 +15426,16 @@ void func_80851B90(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551B4[] = { - { 0, -0x281E }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_5, 30) }, }; void func_80851BE8(PlayState* play, Player* this, CsCmdActorAction* arg2) { LinkAnimation_Update(play, &this->skelAnime); - this->unk_850++; + this->av2.actionVar2++; - if (this->unk_850 >= 180) { - if (this->unk_850 == 180) { + if (this->av2.actionVar2 >= 180) { + if (this->av2.actionVar2 == 180) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_okarina_warp_goal, (2.0f / 3.0f), 10.0f, Animation_GetLastFrame(&gPlayerAnim_link_okarina_warp_goal), ANIMMODE_ONCE, -8.0f); } @@ -15295,12 +15444,12 @@ void func_80851BE8(PlayState* play, Player* this, CsCmdActorAction* arg2) { } void func_80851CA4(PlayState* play, Player* this, CsCmdActorAction* arg2) { - if (LinkAnimation_Update(play, &this->skelAnime) && (this->unk_850 == 0) && (this->actor.bgCheckFlags & 1)) { + if (LinkAnimation_Update(play, &this->skelAnime) && (this->av2.actionVar2 == 0) && (this->actor.bgCheckFlags & 1)) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_back_downB); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } - if (this->unk_850 != 0) { + if (this->av2.actionVar2 != 0) { func_8083721C(this); } } @@ -15312,7 +15461,7 @@ void func_80851D2C(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551B8[] = { - { NA_SE_IT_SWORD_PICKOUT, -0x80C }, + { NA_SE_IT_SWORD_PICKOUT, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 12) }, }; void func_80851D80(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15353,8 +15502,8 @@ void func_80851ECC(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80851F14(PlayState* play, Player* this, LinkAnimationHeader* anim, AnimSfxEntry* arg3) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoopAdjusted(play, this, anim); - this->unk_850 = 1; - } else if (this->unk_850 == 0) { + this->av2.actionVar2 = 1; + } else if (this->av2.actionVar2 == 0) { Player_ProcessAnimSfxList(this, arg3); } } @@ -15365,16 +15514,16 @@ void func_80851F84(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551BC[] = { - { NA_SE_VO_LI_RELAX, 0x2023 }, - { NA_SE_PL_SLIPDOWN, 0x8EC }, - { NA_SE_PL_SLIPDOWN, -0x900 }, + { NA_SE_VO_LI_RELAX, ANIMSFX_DATA(ANIMSFX_TYPE_4, 35) }, + { NA_SE_PL_SLIPDOWN, ANIMSFX_DATA(ANIMSFX_TYPE_1, 236) }, + { NA_SE_PL_SLIPDOWN, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 256) }, }; void func_80851FB0(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplacePlayLoop(play, this, &gPlayerAnim_clink_op3_wait3, 0x9C); - this->unk_850 = 1; - } else if (this->unk_850 == 0) { + this->av2.actionVar2 = 1; + } else if (this->av2.actionVar2 == 0) { Player_ProcessAnimSfxList(this, D_808551BC); if (LinkAnimation_OnFrame(&this->skelAnime, 240.0f)) { this->actor.shape.shadowDraw = ActorShadow_DrawFeet; @@ -15383,10 +15532,10 @@ void func_80851FB0(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551C8[] = { - { NA_SE_PL_LAND_LADDER, 0x843 }, - { 0, 0x4854 }, - { 0, 0x485A }, - { 0, -0x4860 }, + { NA_SE_PL_LAND_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_1, 67) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_9, 84) }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_9, 90) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_9, 96) }, }; void func_80852048(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15414,8 +15563,8 @@ void func_808520BC(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551D8[] = { - { NA_SE_PL_BOUND, 0x1014 }, - { NA_SE_PL_BOUND, -0x101E }, + { NA_SE_PL_BOUND, ANIMSFX_DATA(ANIMSFX_TYPE_2, 20) }, + { NA_SE_PL_BOUND, -ANIMSFX_DATA(ANIMSFX_TYPE_2, 30) }, }; void func_80852174(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15451,8 +15600,8 @@ void func_80852280(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80852298(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimReplaceNormalPlayLoopAdjusted(play, this, &gPlayerAnim_clink_demo_koutai_wait); - this->unk_850 = 1; - } else if (this->unk_850 == 0) { + this->av2.actionVar2 = 1; + } else if (this->av2.actionVar2 == 0) { if (LinkAnimation_OnFrame(&this->skelAnime, 10.0f)) { func_80846720(play, this, 1); } @@ -15460,8 +15609,8 @@ void func_80852298(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551E0[] = { - { 0, 0x300A }, - { 0, -0x3018 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 10) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 24) }, }; void func_80852328(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15469,8 +15618,8 @@ void func_80852328(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551E8[] = { - { 0, 0x400F }, - { 0, -0x4023 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_8, 15) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_8, 35) }, }; void func_80852358(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15480,10 +15629,10 @@ void func_80852358(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80852388(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_demo_link_twait); - this->unk_850 = 1; + this->av2.actionVar2 = 1; } - if ((this->unk_850 != 0) && (play->csCtx.frames >= 900)) { + if ((this->av2.actionVar2 != 0) && (play->csCtx.frames >= 900)) { this->rightHandType = PLAYER_MODELTYPE_LH_OPEN; } else { this->rightHandType = PLAYER_MODELTYPE_RH_FF; @@ -15492,14 +15641,14 @@ void func_80852388(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80852414(PlayState* play, Player* this, LinkAnimationHeader* anim, AnimSfxEntry* arg3) { func_80851294(play, this, anim); - if (this->unk_850 == 0) { + if (this->av2.actionVar2 == 0) { Player_ProcessAnimSfxList(this, arg3); } } static AnimSfxEntry D_808551F0[] = { - { 0, 0x300F }, - { 0, -0x3021 }, + { 0, ANIMSFX_DATA(ANIMSFX_TYPE_6, 15) }, + { 0, -ANIMSFX_DATA(ANIMSFX_TYPE_6, 33) }, }; void func_80852450(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15507,7 +15656,7 @@ void func_80852450(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static AnimSfxEntry D_808551F8[] = { - { NA_SE_PL_KNOCK, -0x84E }, + { NA_SE_PL_KNOCK, -ANIMSFX_DATA(ANIMSFX_TYPE_1, 78) }, }; void func_80852480(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15521,11 +15670,11 @@ void func_808524B0(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_808524D0(PlayState* play, Player* this, CsCmdActorAction* arg2) { sControlInput->press.button |= BTN_B; - func_80844E68(this, play); + Player_Action_80844E68(this, play); } void func_80852514(PlayState* play, Player* this, CsCmdActorAction* arg2) { - func_80844E68(this, play); + Player_Action_80844E68(this, play); } void func_80852544(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15544,13 +15693,13 @@ void func_80852564(PlayState* play, Player* this, CsCmdActorAction* arg2) { } static void (*D_808551FC[])(Player* this, PlayState* play) = { - func_8084377C, - func_80843954, - func_80843A38, + Player_Action_8084377C, + Player_Action_80843954, + Player_Action_80843A38, }; void func_808525C0(PlayState* play, Player* this, CsCmdActorAction* arg2) { - D_808551FC[this->unk_850](this, play); + D_808551FC[this->av2.actionVar2](this, play); } void func_80852608(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15622,7 +15771,7 @@ void func_808526EC(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80852944(play, this, arg2); - } else if (this->unk_850 == 0) { + } else if (this->av2.actionVar2 == 0) { Item_Give(play, ITEM_SWORD_MASTER); func_80846720(play, this, 0); } else { @@ -15646,8 +15795,8 @@ void func_80852944(PlayState* play, Player* this, CsCmdActorAction* arg2) { func_80832340(play, this); } else { func_8083C148(this, play); - if (!func_8083B644(this, play)) { - func_8083E5A8(this, play); + if (!Player_ActionChange_4(this, play)) { + Player_ActionChange_2(this, play); } } @@ -15662,7 +15811,7 @@ void func_808529D0(PlayState* play, Player* this, CsCmdActorAction* arg2) { this->actor.world.pos.y -= 1.0f; } this->actor.world.pos.z = arg2->startPos.z; - this->currentYaw = this->actor.shape.rot.y = arg2->rot.y; + this->yaw = this->actor.shape.rot.y = arg2->rot.y; } void func_80852A54(PlayState* play, Player* this, CsCmdActorAction* arg2) { @@ -15733,8 +15882,8 @@ void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) { func_80852C0C(play, this, ABS(sp24)); func_80852B4C(play, this, linkCsAction, &D_80854B18[ABS(sp24)]); - this->unk_850 = 0; - this->unk_84F = 0; + this->av2.actionVar2 = 0; + this->av1.actionVar1 = 0; this->cueId = linkCsAction->action; } @@ -15746,7 +15895,7 @@ void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) { } } -void func_80852E14(Player* this, PlayState* play) { +void Player_Action_CsAction(Player* this, PlayState* play) { if (this->csAction != this->prevCsAction) { D_80858AA0 = this->skelAnime.moveFlags; @@ -15760,10 +15909,10 @@ void func_80852E14(Player* this, PlayState* play) { func_80852B4C(play, this, NULL, &D_80854E50[this->csAction]); } -s32 Player_IsDroppingFish(PlayState* play) { +int Player_IsDroppingFish(PlayState* play) { Player* this = GET_PLAYER(play); - return (func_8084EFC0 == this->actionFunc) && (this->itemAction == PLAYER_IA_BOTTLE_FISH); + return (Player_Action_8084EFC0 == this->actionFunc) && (this->itemAction == PLAYER_IA_BOTTLE_FISH); } s32 Player_StartFishing(PlayState* play) { @@ -15802,20 +15951,20 @@ s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction) { if (!Player_InBlockingCsMode(play, this)) { func_80832564(play, this); - Player_SetupAction(play, this, func_80852E14, 0); + Player_SetupAction(play, this, Player_Action_CsAction, 0); this->csAction = csAction; this->csActor = actor; func_80832224(this); - return 1; + return true; } - return 0; + return false; } void func_80853080(Player* this, PlayState* play) { - Player_SetupAction(play, this, func_80840BC8, 1); + Player_SetupAction(play, this, Player_Action_80840BC8, 1); Player_AnimChangeOnceMorph(play, this, func_80833338(this)); - this->currentYaw = this->actor.shape.rot.y; + this->yaw = this->actor.shape.rot.y; } s32 Player_InflictDamage(PlayState* play, s32 damage) { @@ -15859,12 +16008,12 @@ void Player_StartTalking(PlayState* play, Actor* actor) { } if (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) { - s32 sp24 = this->unk_850; + s32 sp24 = this->av2.actionVar2; func_80832528(play, this); func_8083A2F8(play, this); - this->unk_850 = sp24; + this->av2.actionVar2 = sp24; } else { if (func_808332B8(this)) { func_80836898(play, this, func_8083A2F8); From a7726653e5fb0d2c25487ddc78ad041719734ee0 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 16 Feb 2024 02:49:45 +0000 Subject: [PATCH 088/300] Add Big Skulltula logic to adult kokiri forest and fix a small bug in forest temple logic (#3938) * Add Big Skulltula logic to adult kokiri forest and fix a small bug in forest temple logic * fix spelling --- .../location_access/locacc_forest_temple.cpp | 2 +- .../location_access/locacc_lost_woods.cpp | 4 ++-- soh/soh/Enhancements/randomizer/logic.cpp | 20 +++++++++++++++++++ soh/soh/Enhancements/randomizer/logic.h | 2 ++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index 1e464357f..5f79f53cd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -170,7 +170,7 @@ void AreaTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}), Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return logic->CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslash && logic->GoronBracelet);}}), Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return logic->IsAdult && logic->GoronBracelet && logic->SmallKeys(RR_FOREST_TEMPLE, 2);}}), - Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) && logic->GoronBracelet && logic->SmallKeys(RR_FOREST_TEMPLE, 2);}}), + Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) && logic->GoronBracelet && logic->SmallKeys(RR_FOREST_TEMPLE, 2);}}), }); areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp index 69911b049..6dc417727 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp @@ -24,7 +24,7 @@ void AreaTable_Init_LostWoods() { Entrance(RR_KF_HOUSE_OF_TWINS, {[]{return true;}}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}), Entrance(RR_KF_KOKIRI_SHOP, {[]{return true;}}), - Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return logic->IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), + Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return (logic->IsAdult && (logic->CanPassEnemy("Big Skulltula") || logic->ForestTempleClear)) || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), Entrance(RR_THE_LOST_WOODS, {[]{return true;}}), Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return logic->IsAdult || randoCtx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || logic->DekuTreeClear;}}), Entrance(RR_KF_STORMS_GROTTO, {[]{return logic->CanOpenStormGrotto;}}), @@ -42,7 +42,7 @@ void AreaTable_Init_LostWoods() { }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return logic->IsChild || (randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield));}}), - Entrance(RR_KOKIRI_FOREST, {[]{return logic->IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), + Entrance(RR_KOKIRI_FOREST, {[]{return (logic->IsAdult && (logic->CanPassEnemy("Big Skulltula") || logic->ForestTempleClear)) || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), }); areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 31b8e7bdc..56ed191c0 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -230,6 +230,26 @@ namespace Rando { return false; } + bool Logic::CanKillEnemy(std::string enemy) { + //switch(enemy) {} RANDOTODO implement enemies enum + if (enemy == "Big Skulltula"){ + return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanJumpslash || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives; + } + //Shouldn't be reached + return false; + } + + bool Logic::CanPassEnemy(std::string enemy) { + //switch(enemy) {} RANDOTODO implement enemies enum + if (CanKillEnemy(enemy)){ + return true; + } + if (enemy == "Big Skulltula"){ + return Nuts || CanUse(RG_BOOMERANG); + } + return false; + } + Logic::Logic() { } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 8cccdbbf8..5475d4d92 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -422,6 +422,8 @@ class Logic { bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); bool CanDoGlitch(GlitchType glitch); bool CanEquipSwap(RandomizerGet itemName); + bool CanKillEnemy(std::string enemy); + bool CanPassEnemy(std::string enemy); bool EventsUpdated(); void Reset(); From 8525f71c57c205712ce12c2fbe5d3b0090d7e5be Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 16 Feb 2024 03:50:17 +0100 Subject: [PATCH 089/300] Colored Compasses (#3883) * Colored Compasses * Rename cvar & add explicit rando check --- soh/soh/Enhancements/mods.cpp | 22 ++++++++++ soh/soh/Enhancements/mods.h | 1 + soh/soh/Enhancements/randomizer/draw.cpp | 44 +++++++++++++++++++ soh/soh/Enhancements/randomizer/draw.h | 1 + soh/soh/Enhancements/randomizer/item_list.cpp | 10 +++++ soh/soh/SohMenuBar.cpp | 22 +++++++++- 6 files changed, 98 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 26adf611d..9b8e7076e 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -10,6 +10,7 @@ #include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include #include "soh/Enhancements/nametag.h" +#include "objects/object_gi_compass/object_gi_compass.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" #include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h" @@ -1595,6 +1596,26 @@ void RegisterFishsanity() { }); } +extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); + +void PatchCompasses() { + s8 compassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); + s8 isColoredCompassesEnabled = compassesCanBeOutsideDungeon && CVarGetInteger("gRandoEnhancement.MatchCompassColors", 1); + if (isColoredCompassesEnabled) { + ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_PrimColor", 5, gsDPNoOp()); + ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_EnvColor", 6, gsDPNoOp()); + } else { + ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_PrimColor"); + ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_EnvColor"); + } +} + +void RegisterRandomizerCompasses() { + GameInteractor::Instance->RegisterGameHook([](int32_t _unused) { + PatchCompasses(); + }); +} + void InitMods() { RegisterTTS(); RegisterInfiniteMoney(); @@ -1632,6 +1653,7 @@ void InitMods() { RegisterNoSwim(); RegisterNoWallet(); RegisterFishsanity(); + RegisterRandomizerCompasses(); NameTag_RegisterHooks(); RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index 57ebedfd9..9289594dc 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -11,6 +11,7 @@ void UpdateDirtPathFixState(int32_t sceneNum); void UpdateMirrorModeState(int32_t sceneNum); void UpdateHurtContainerModeState(bool newState); void PatchToTMedallions(); +void PatchCompasses(); void UpdatePermanentHeartLossState(); void InitMods(); void UpdatePatchHand(); diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 646d99456..4ee80d919 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -9,6 +9,7 @@ #include #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" +#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_hearts/object_gi_hearts.h" #include "objects/object_gi_scale/object_gi_scale.h" #include "objects/object_gi_fire/object_gi_fire.h" @@ -63,6 +64,49 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn CLOSE_DISPS(play->state.gfxCtx); } +extern "C" { + void GetItem_DrawCompass(PlayState* play, s16 drawId); + void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); + void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); +} + +extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry) { + + s16 color_slot = getItemEntry->getItemId - RG_DEKU_TREE_COMPASS; + s16 colors[12][3] = { + { 4, 100, 46 }, // Deku Tree + { 140, 30, 30 }, // Dodongo's Cavern + { 30, 60, 255 }, // Jabu Jabu's Belly + { 4, 195, 46 }, // Forest Temple + { 237, 95, 95 }, // Fire Temple + { 85, 180, 223 }, // Water Temple + { 222, 158, 47 }, // Spirit Temple + { 126, 16, 177 }, // Shadow Temple + { 227, 110, 255 }, // Bottom of the Well + { 221, 212, 60 }, // Gerudo Training Grounds + { 255, 255, 255 }, // Thieves' Hideout + { 80, 80, 80 } // Ganon's Castle + }; + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); + gDPSetEnvColor(POLY_OPA_DISP++, colors[color_slot][0] / 2, colors[color_slot][1] / 2, colors[color_slot][2] / 2, 255); + + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiCompassDL); + + POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 5); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiCompassGlassDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry) { s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GANONS_CASTLE_BOSS_KEY ? DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY) : diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 0e8a3e3b5..51300f3a6 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -10,6 +10,7 @@ typedef struct PlayState PlayState; extern "C" { #endif void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index a64d62d40..343f680b1 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -107,15 +107,25 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &logic->noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &logic->noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &logic->noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &logic->noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &logic->noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &logic->noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &logic->noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &logic->noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &logic->noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &logic->noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, &logic->BossKeyForestTemple, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 56e12e53e..c2b560296 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -10,6 +10,7 @@ #include "include/z64audio.h" #include "OTRGlobals.h" #include "z64.h" +#include "macros.h" #include "Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/presets.h" #include "soh/Enhancements/mods.h" @@ -1826,6 +1827,7 @@ extern std::shared_ptr mItemTrackerSettingsWindow; extern std::shared_ptr mEntranceTrackerWindow; extern std::shared_ptr mCheckTrackerWindow; extern std::shared_ptr mCheckTrackerSettingsWindow; +extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void DrawRandomizerMenu() { if (ImGui::BeginMenu("Randomizer")) { @@ -1916,7 +1918,7 @@ void DrawRandomizerMenu() { disableKeyColors = false; } - static const char* disableKeyColorsText = + static const char* disableKeyColorsText = "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; @@ -1925,7 +1927,23 @@ void DrawRandomizerMenu() { UIWidgets::Tooltip( "Matches the color of small keys and boss keys to the dungeon they belong to. " "This helps identify keys from afar and adds a little bit of flair.\n\nThis only " - "applies to seeds with keys and boss keys shuffled to Any Dungeon, Overworld, or Anywhere."); + "applies to seeds with keys and boss keys shuffled to \"Any Dungeon\", \"Overworld\", or \"Anywhere\"."); + + bool disableCompassColors = !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); + + static const char* disableCompassColorsText = + "This setting is disabled because a savefile is loaded without the compass\n" + "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; + + if (UIWidgets::PaddedEnhancementCheckbox("Compass Colors Match Dungeon", "gRandoEnhancement.MatchCompassColors", true, false, + disableCompassColors, disableCompassColorsText, UIWidgets::CheckboxGraphics::Cross, true)) { + PatchCompasses(); + } + UIWidgets::Tooltip( + "Matches the color of compasses to the dungeon they belong to. " + "This helps identify compasses from afar and adds a little bit of flair.\n\nThis only " + "applies to seeds with compasses shuffled to \"Any Dungeon\", \"Overworld\", or \"Anywhere\"."); + UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares", true, false); UIWidgets::Tooltip( "Play unique fanfares when obtaining quest items " From db57581d6f003083714be5030b3264be6c553d10 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:51:23 -0500 Subject: [PATCH 090/300] [Cosmetics] Add Vanilla GS DL for Cosmetics Editor (#3937) * Add Vanilla DL * Fixed egregious spacing error --- .../Enhancements/cosmetics/CosmeticsEditor.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 2166f43bc..c6b6a5e74 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1065,12 +1065,16 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { if (manualChange || CVarGetInteger(npcGoldenSkulltula.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {npcGoldenSkulltula.defaultColor.x, npcGoldenSkulltula.defaultColor.y, npcGoldenSkulltula.defaultColor.z, npcGoldenSkulltula.defaultColor.w}; Color_RGBA8 color = CVarGetColor(npcGoldenSkulltula.cvar, defaultColor); - PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula1", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula2", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); - PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula3", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula4", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); - PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula5", npcGoldenSkulltula.changedCvar, 118, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula6", npcGoldenSkulltula.changedCvar, 119, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255)); + PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula1", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula2", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); + PATCH_GFX(gSkulltulaTokenFlameDL, "NPC_GoldenSkulltula3", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gSkulltulaTokenFlameDL, "NPC_GoldenSkulltula4", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); + PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula5", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiSkulltulaTokenDL, "NPC_GoldenSkulltula6", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); + PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula7", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiSkulltulaTokenFlameDL, "NPC_GoldenSkulltula8", npcGoldenSkulltula.changedCvar, 33, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); + PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula9", npcGoldenSkulltula.changedCvar, 118, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula10", npcGoldenSkulltula.changedCvar, 119, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255)); } static CosmeticOption& npcGerudo = cosmeticOptions.at("NPC_Gerudo"); From 7f4fc8dc4a650abe5a11a440b1df5acf61a2a790 Mon Sep 17 00:00:00 2001 From: Miles Acquaviva Date: Thu, 15 Feb 2024 22:03:19 -0500 Subject: [PATCH 091/300] Abstracted repeated code into functions (#3116) * Abstracted repeated code into functions * Apply suggestions from code review * Update soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: Archez --- .../cosmetics/CosmeticsEditor.cpp | 372 ++++-------------- 1 file changed, 85 insertions(+), 287 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index c6b6a5e74..72ad74e19 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1185,6 +1185,43 @@ void DrawScaleSlider(const std::string CvarName,float DefaultValue){ //Disabled for now. feature not done and several fixes needed to be merged. //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true); } +void Draw_Table_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, int MinY, int MaxY, int MinX, int MaxX, float Default_Value) { + if (ImGui::CollapsingHeader(Header_Title)) { + if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) { + ImGui::TableSetupColumn(Column_Title, FlagsCell, TablesCellsWidth); + Table_InitHeader(false); + DrawUseMarginsSlider(Slider_Title, Slider_ID); + DrawPositionsRadioBoxes(Slider_ID); + DrawPositionSlider(Slider_ID, MinY, MaxY, MinX, MaxX); + DrawScaleSlider(Slider_ID, Default_Value); + ImGui::NewLine(); + ImGui::EndTable(); + } + } +} +void C_Button_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, const char* Int_Type, float Slider_Scale_Value) { + if (ImGui::CollapsingHeader(Header_Title)) { + if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) { + ImGui::TableSetupColumn(Column_Title, FlagsCell, TablesCellsWidth); + Table_InitHeader(false); + DrawUseMarginsSlider(Slider_Title, Slider_ID); + DrawPositionsRadioBoxes(Slider_ID); + s16 Min_X_CU = 0; + s16 Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; + if(CVarGetInteger(Int_Type,0) == 2){ + Max_X_CU = 294; + } else if(CVarGetInteger(Int_Type,0) == 3){ + Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; + } else if(CVarGetInteger(Int_Type,0) == 4){ + Min_X_CU = (ImGui::GetWindowViewport()->Size.x/2)*-1; + } + DrawPositionSlider(Slider_ID, 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CU, Max_X_CU); + DrawScaleSlider(Slider_ID, Slider_Scale_Value); + ImGui::NewLine(); + ImGui::EndTable(); + } + } +} void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); @@ -1251,126 +1288,13 @@ void Draw_Placements(){ ImGui::EndTable(); } } - if (ImGui::CollapsingHeader("B Button position")) { - if (ImGui::BeginTable("tablebbtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("B Button settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("B Button", "gBBtn"); - DrawPositionsRadioBoxes("gBBtn"); - DrawPositionSlider("gBBtn", 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50); - DrawScaleSlider("gBBtn",0.95f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("A Button position")) { - if (ImGui::BeginTable("tableabtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("A Button settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("A Button", "gABtn"); - DrawPositionsRadioBoxes("gABtn"); - DrawPositionSlider("gABtn", -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50); - DrawScaleSlider("gABtn",0.95f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Start Button position")) { - if (ImGui::BeginTable("tablestartbtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("Start Button settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Start Button", "gStartBtn"); - DrawPositionsRadioBoxes("gStartBtn"); - DrawPositionSlider("gStartBtn", 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70); - DrawScaleSlider("gStartBtn",0.75f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("C Button Up position")) { - if (ImGui::BeginTable("tablecubtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("C Button Up settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("C Button Up", "gCBtnU"); - DrawPositionsRadioBoxes("gCBtnU"); - s16 Min_X_CU = 0; - s16 Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gCBtnUPosType",0) == 2){ - Max_X_CU = 294; - } else if(CVarGetInteger("gCBtnUPosType",0) == 3){ - Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; - } else if(CVarGetInteger("gCBtnUPosType",0) == 4){ - Min_X_CU = (ImGui::GetWindowViewport()->Size.x/2)*-1; - } - DrawPositionSlider("gCBtnU", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CU, Max_X_CU); - DrawScaleSlider("gCBtnU",0.5f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("C Button Down position")) { - if (ImGui::BeginTable("tablecdbtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("C Button Down settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("C Button Down", "gCBtnD"); - DrawPositionsRadioBoxes("gCBtnD"); - s16 Min_X_CD = 0; - s16 Max_X_CD = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gCBtnDPosType",0) == 2){ - Max_X_CD = 294; - } else if(CVarGetInteger("gCBtnDPosType",0) == 3){ - Max_X_CD = ImGui::GetWindowViewport()->Size.x/2; - } else if(CVarGetInteger("gCBtnDPosType",0) == 4){ - Min_X_CD = (ImGui::GetWindowViewport()->Size.x/2)*-1; - } - DrawPositionSlider("gCBtnD", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CD, Max_X_CD); - DrawScaleSlider("gCBtnD",0.87f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("C Button Left position")) { - if (ImGui::BeginTable("tableclbtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("C Button Left settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("C Button Left", "gCBtnL"); - DrawPositionsRadioBoxes("gCBtnL"); - s16 Min_X_CL = 0; - s16 Max_X_CL = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gCBtnLPosType",0) == 2){ - Max_X_CL = 294; - } else if(CVarGetInteger("gCBtnLPosType",0) == 3){ - Max_X_CL = ImGui::GetWindowViewport()->Size.x/2; - } else if(CVarGetInteger("gCBtnLPosType",0) == 4){ - Min_X_CL = (ImGui::GetWindowViewport()->Size.x/2)*-1; - } - DrawPositionSlider("gCBtnL", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CL, Max_X_CL); - DrawScaleSlider("gCBtnL",0.87f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("C Button Right position")) { - if (ImGui::BeginTable("tablecrnbtn", 1, FlagsTable)) { - ImGui::TableSetupColumn("C Button Right settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("C Button Right", "gCBtnR"); - DrawPositionsRadioBoxes("gCBtnR"); - s16 Min_X_CR = 0; - s16 Max_X_CR = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gCBtnRPosType",0) == 2){ - Max_X_CR = 294; - } else if(CVarGetInteger("gCBtnRPosType",0) == 3){ - Max_X_CR = ImGui::GetWindowViewport()->Size.x/2; - } else if(CVarGetInteger("gCBtnRPosType",0) == 4){ - Min_X_CR = (ImGui::GetWindowViewport()->Size.x/2)*-1; - } - DrawPositionSlider("gCBtnR", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CR, Max_X_CR); - DrawScaleSlider("gCBtnR",0.87f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } + Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", "gBBtn", 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", "gABtn", -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", "gStartBtn", 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); + C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", "gCBtnU", "gCBtnUPosType", 0.5f); + C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", "gCBtnD", "gCBtnDPosType", 0.87f); + C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", "gCBtnL", "gCBtnLPosType", 0.87f); + C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", "gCBtnR", "gCBtnRPosType", 0.87f); if (CVarGetInteger("gDpadEquips",0) && ImGui::CollapsingHeader("DPad items position")) { if (ImGui::BeginTable("tabledpaditems", 1, FlagsTable)) { ImGui::TableSetupColumn("DPad items settings", FlagsCell, TablesCellsWidth); @@ -1390,115 +1314,15 @@ void Draw_Placements(){ ImGui::EndTable(); } } - if (ImGui::CollapsingHeader("Minimaps position")) { - if (ImGui::BeginTable("tableminimapspos", 1, FlagsTable)) { - ImGui::TableSetupColumn("minimaps settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Minimap", "gMinimap"); - DrawPositionsRadioBoxes("gMinimap", false); - DrawPositionSlider("gMinimap", (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider("gMinimap",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Small Keys counter position")) { - if (ImGui::BeginTable("tablesmolekeys", 1, FlagsTable)) { - ImGui::TableSetupColumn("Small Keys counter settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Small Keys counter", "gSKC"); - DrawPositionsRadioBoxes("gSKC"); - DrawPositionSlider("gSKC", 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider("gSKC",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Rupee counter position")) { - if (ImGui::BeginTable("tablerupeecount", 1, FlagsTable)) { - ImGui::TableSetupColumn("Rupee counter settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Rupee counter", "gRC"); - DrawPositionsRadioBoxes("gRC"); - DrawPositionSlider("gRC", -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider("gRC",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Carrots position")) { - if (ImGui::BeginTable("tableCarrots", 1, FlagsTable)) { - ImGui::TableSetupColumn("Carrots settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Carrots", "gCarrots"); - DrawPositionsRadioBoxes("gCarrots"); - DrawPositionSlider("gCarrots", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25); - DrawScaleSlider("gCarrots",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Timers position")) { - if (ImGui::BeginTable("tabletimers", 1, FlagsTable)) { - ImGui::TableSetupColumn("Timers settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Timers", "gTimers"); - DrawPositionsRadioBoxes("gTimers"); - DrawPositionSlider("gTimers", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50); - DrawScaleSlider("gTimers",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Archery Scores position")) { - if (ImGui::BeginTable("tablearchery", 1, FlagsTable)) { - ImGui::TableSetupColumn("Archery Scores settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Archery scores", "gAS"); - DrawPositionsRadioBoxes("gAS", false); - DrawPositionSlider("gAS", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50); - DrawScaleSlider("gAS",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Title cards (Maps) position")) { - if (ImGui::BeginTable("tabletcmaps", 1, FlagsTable)) { - ImGui::TableSetupColumn("Titlecard maps settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Title cards (overworld)", "gTCM"); - DrawPositionsRadioBoxes("gTCM"); - DrawPositionSlider("gTCM", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10); - DrawScaleSlider("gTCM",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("Title cards (Bosses) position")) { - if (ImGui::BeginTable("tabletcbosses", 1, FlagsTable)) { - ImGui::TableSetupColumn("Title cards (Bosses) settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("Title cards (Bosses)", "gTCB"); - DrawPositionsRadioBoxes("gTCB"); - DrawPositionSlider("gTCB", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10); - DrawScaleSlider("gTCB",1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } - if (ImGui::CollapsingHeader("In-game Gameplay Timer position")) { - if (ImGui::BeginTable("tablegameplaytimer", 1, FlagsTable)) { - ImGui::TableSetupColumn("In-game Gameplay Timer settings", FlagsCell, TablesCellsWidth); - Table_InitHeader(false); - DrawUseMarginsSlider("In-game Gameplay Timer", "gIGT"); - DrawPositionsRadioBoxes("gIGT"); - DrawPositionSlider("gIGT", 0, ImGui::GetWindowViewport()->Size.y / 2, -50, - ImGui::GetWindowViewport()->Size.x / 2 + 10); - DrawScaleSlider("gIGT", 1.0f); - ImGui::NewLine(); - ImGui::EndTable(); - } - } + Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", "gMinimap", (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", "gSKC", 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", "gRC", -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", "gCarrots", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); + Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", "gTimers", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", "gAS", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", "gTCM", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", "gTCB", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", "gIGT", 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); if (ImGui::CollapsingHeader("Enemy Health Bar position")) { if (ImGui::BeginTable("enemyhealthbar", 1, FlagsTable)) { ImGui::TableSetupColumn("Enemy Health Bar settings", FlagsCell, TablesCellsWidth); @@ -1526,7 +1350,21 @@ void Draw_Placements(){ } } } - +void Reset_Option_Single(const char* Button_Title, const char* name) { + ImGui::SameLine(); + if (ImGui::Button(Button_Title)) { + CVarClear(name); + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } +} +void Reset_Option_Double(const char* Button_Title, const char* name) { + ImGui::SameLine(); + if (ImGui::Button(Button_Title)) { + CVarClear((std::string(name) + ".Value").c_str()); + CVarClear((std::string(name) + ".Changed").c_str()); + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } +} void DrawSillyTab() { ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); if (CVarGetInteger("gLetItSnow", 0)) { @@ -1552,68 +1390,28 @@ void DrawSillyTab() { if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", "gCosmetics.Link_HeadScale.Value", 0.4f, 4.0f, "", 1.0f, false)) { CVarSetInteger("gCosmetics.Link_HeadScale.Changed", 1); } - ImGui::SameLine(); - if (ImGui::Button("Reset##Link_HeadScale")) { - CVarClear("gCosmetics.Link_HeadScale.Value"); - CVarClear("gCosmetics.Link_HeadScale.Changed"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %.3fx", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) { + Reset_Option_Double("Reset##Link_HeadScale", "gCosmetics.Link_HeadScale"); + if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) { CVarSetInteger("gCosmetics.Link_SwordScale.Changed", 1); } - ImGui::SameLine(); - if (ImGui::Button("Reset##Link_SwordScale")) { - CVarClear("gCosmetics.Link_SwordScale.Value"); - CVarClear("gCosmetics.Link_SwordScale.Changed"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %.0f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false); - ImGui::SameLine(); - if (ImGui::Button("Reset##BunnyHood_EarLength")) { - CVarClear("gCosmetics.BunnyHood_EarLength"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %.0f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false); - ImGui::SameLine(); - if (ImGui::Button("Reset##BunnyHood_EarSpread")) { - CVarClear("gCosmetics.BunnyHood_EarSpread"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - UIWidgets::EnhancementSliderFloat("Goron Neck Length: %.0f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 5000.0f, "", 0.0f, false); - ImGui::SameLine(); - if (ImGui::Button("Reset##Goron_NeckLength")) { - CVarClear("gCosmetics.Goron_NeckLength"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } + Reset_Option_Double("Reset##Link_SwordScale", "gCosmetics.Link_SwordScale"); + UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false); + Reset_Option_Single("Reset##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength"); + UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false); + Reset_Option_Single("Reset##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread"); + UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 1000.0f, "", 0.0f, false); + Reset_Option_Single("Reset##Goron_NeckLength", "gCosmetics.Goron_NeckLength"); UIWidgets::EnhancementCheckbox("Unfix Goron Spin", "gUnfixGoronSpin"); - UIWidgets::EnhancementSliderFloat("Fairies Size: %.2fx", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false); - ImGui::SameLine(); - if (ImGui::Button("Reset##Fairies_Size")) { - CVarClear("gCosmetics.Fairies_Size"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %.2fx", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false); - ImGui::SameLine(); - if (ImGui::Button("Reset##N64Logo_SpinSpeed")) { - CVarClear("gCosmetics.N64Logo_SpinSpeed"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - UIWidgets::EnhancementSliderFloat("Moon Size: %.1f %%", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, true); - ImGui::SameLine(); - if (ImGui::Button("Reset##Moon_Size")) { - CVarClear("gCosmetics.Moon_Size"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %.0f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) { + UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false); + Reset_Option_Single("Reset##Fairies_Size", "gCosmetics.Fairies_Size"); + UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false); + Reset_Option_Single("Reset##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed"); + UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, false); + Reset_Option_Single("Reset##Moon_Size", "gCosmetics.Moon_Size"); + if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) { CVarSetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 1); } - ImGui::SameLine(); - if (ImGui::Button("Reset##Kak_Windmill_Speed")) { - CVarClear("gCosmetics.Kak_Windmill_Speed.Value"); - CVarClear("gCosmetics.Kak_Windmill_Speed.Changed"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - } - ImGui::EndDisabled(); + Reset_Option_Double("Reset##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed"); } // Copies the RGB values from one cosmetic option to another, multiplied by the passed in amount, this From e0d502b696179e2cbae6b284015cfe8d4c251834 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 15 Feb 2024 22:06:52 -0500 Subject: [PATCH 092/300] resource refactory (#3926) * animation * playeranimation * stop putting things in the LUS namespace from SoH * get all the factories out of the namespace * LUS:: * start on scene command stuff * i think that's the rest of scene * reduce copypasta * collision header * skeleton * skeletonlimb * fix * path * cutscene * text * audio sample * sound font * audiosequence * background * Revert "stop putting things in the LUS namespace from SoH" This reverts commit 0ead6056e66287f515a3bb0f9117ad93bc32d543. * namespace shanans * wrap all factories in namespace soh * it's trying to link now * lus * scene command override etc * fix audio loading * slightly less logspam * get past the cutscene problem * in game! * exporter cleanup * more exporter cleanup * clang formatted lus * msvc * itny lus change * variant * formatty * fix of some sort i guess? * use latest lus main * fix name to enum/factory mapping * otrexporter --- OTRExporter | 2 +- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 44 ++--- .../resource/importer/AnimationFactory.cpp | 32 +--- soh/soh/resource/importer/AnimationFactory.h | 16 +- .../resource/importer/AudioSampleFactory.cpp | 36 +--- .../resource/importer/AudioSampleFactory.h | 18 +- .../importer/AudioSequenceFactory.cpp | 33 +--- .../resource/importer/AudioSequenceFactory.h | 18 +- .../importer/AudioSoundFontFactory.cpp | 33 +--- .../resource/importer/AudioSoundFontFactory.h | 18 +- .../resource/importer/BackgroundFactory.cpp | 31 +--- soh/soh/resource/importer/BackgroundFactory.h | 16 +- .../importer/CollisionHeaderFactory.cpp | 69 +++----- .../importer/CollisionHeaderFactory.h | 19 +-- soh/soh/resource/importer/CutsceneFactory.cpp | 49 ++---- soh/soh/resource/importer/CutsceneFactory.h | 18 +- soh/soh/resource/importer/PathFactory.cpp | 34 +--- soh/soh/resource/importer/PathFactory.h | 18 +- .../importer/PlayerAnimationFactory.cpp | 38 ++--- .../importer/PlayerAnimationFactory.h | 16 +- soh/soh/resource/importer/SceneFactory.cpp | 114 ++++++------- soh/soh/resource/importer/SceneFactory.h | 24 ++- soh/soh/resource/importer/SkeletonFactory.cpp | 85 +++------- soh/soh/resource/importer/SkeletonFactory.h | 22 +-- .../resource/importer/SkeletonLimbFactory.cpp | 86 +++------- .../resource/importer/SkeletonLimbFactory.h | 22 +-- soh/soh/resource/importer/TextFactory.cpp | 83 +++------- soh/soh/resource/importer/TextFactory.h | 22 +-- .../scenecommand/EndMarkerFactory.cpp | 38 +---- .../importer/scenecommand/EndMarkerFactory.h | 14 +- .../scenecommand/SceneCommandFactory.cpp | 7 +- .../scenecommand/SceneCommandFactory.h | 13 +- .../scenecommand/SetActorListFactory.cpp | 54 ++---- .../scenecommand/SetActorListFactory.h | 15 +- .../SetAlternateHeadersFactory.cpp | 49 ++---- .../scenecommand/SetAlternateHeadersFactory.h | 15 +- .../scenecommand/SetCameraSettingsFactory.cpp | 36 +--- .../scenecommand/SetCameraSettingsFactory.h | 15 +- .../SetCollisionHeaderFactory.cpp | 35 +--- .../scenecommand/SetCollisionHeaderFactory.h | 15 +- .../scenecommand/SetCsCameraFactory.cpp | 35 +--- .../scenecommand/SetCsCameraFactory.h | 15 +- .../scenecommand/SetCutscenesFactory.cpp | 36 +--- .../scenecommand/SetCutscenesFactory.h | 15 +- .../scenecommand/SetEchoSettingsFactory.cpp | 36 +--- .../scenecommand/SetEchoSettingsFactory.h | 15 +- .../scenecommand/SetEntranceListFactory.cpp | 35 +--- .../scenecommand/SetEntranceListFactory.h | 15 +- .../scenecommand/SetExitListFactory.cpp | 35 +--- .../scenecommand/SetExitListFactory.h | 15 +- .../scenecommand/SetLightListFactory.cpp | 41 +---- .../scenecommand/SetLightListFactory.h | 15 +- .../SetLightingSettingsFactory.cpp | 36 +--- .../scenecommand/SetLightingSettingsFactory.h | 15 +- .../importer/scenecommand/SetMeshFactory.cpp | 45 ++--- .../importer/scenecommand/SetMeshFactory.h | 15 +- .../scenecommand/SetObjectListFactory.cpp | 36 +--- .../scenecommand/SetObjectListFactory.h | 15 +- .../scenecommand/SetPathwaysFactory.cpp | 35 +--- .../scenecommand/SetPathwaysFactory.h | 15 +- .../scenecommand/SetRoomBehaviorFactory.cpp | 35 +--- .../scenecommand/SetRoomBehaviorFactory.h | 15 +- .../scenecommand/SetRoomListFactory.cpp | 46 ++---- .../scenecommand/SetRoomListFactory.h | 15 +- .../scenecommand/SetSkyboxModifierFactory.cpp | 35 +--- .../scenecommand/SetSkyboxModifierFactory.h | 15 +- .../scenecommand/SetSkyboxSettingsFactory.cpp | 35 +--- .../scenecommand/SetSkyboxSettingsFactory.h | 15 +- .../scenecommand/SetSoundSettingsFactory.cpp | 35 +--- .../scenecommand/SetSoundSettingsFactory.h | 15 +- .../scenecommand/SetSpecialObjectsFactory.cpp | 35 +--- .../scenecommand/SetSpecialObjectsFactory.h | 15 +- .../SetStartPositionListFactory.cpp | 56 ++----- .../SetStartPositionListFactory.h | 15 +- .../scenecommand/SetTimeSettingsFactory.cpp | 35 +--- .../scenecommand/SetTimeSettingsFactory.h | 15 +- .../SetTransitionActorListFactory.cpp | 37 +---- .../SetTransitionActorListFactory.h | 15 +- .../scenecommand/SetWindSettingsFactory.cpp | 35 +--- .../scenecommand/SetWindSettingsFactory.h | 15 +- soh/soh/resource/type/Animation.cpp | 4 +- soh/soh/resource/type/Animation.h | 134 +++++++-------- soh/soh/resource/type/AudioSample.cpp | 4 +- soh/soh/resource/type/AudioSample.h | 6 +- soh/soh/resource/type/AudioSequence.cpp | 4 +- soh/soh/resource/type/AudioSequence.h | 6 +- soh/soh/resource/type/AudioSoundFont.cpp | 4 +- soh/soh/resource/type/AudioSoundFont.h | 6 +- soh/soh/resource/type/Background.cpp | 4 +- soh/soh/resource/type/Background.h | 6 +- soh/soh/resource/type/CollisionHeader.cpp | 4 +- soh/soh/resource/type/CollisionHeader.h | 6 +- soh/soh/resource/type/Cutscene.cpp | 4 +- soh/soh/resource/type/Cutscene.h | 8 +- soh/soh/resource/type/Path.cpp | 4 +- soh/soh/resource/type/Path.h | 6 +- soh/soh/resource/type/PlayerAnimation.cpp | 4 +- soh/soh/resource/type/PlayerAnimation.h | 9 +- soh/soh/resource/type/Scene.cpp | 4 +- soh/soh/resource/type/Scene.h | 6 +- soh/soh/resource/type/Skeleton.cpp | 4 +- soh/soh/resource/type/Skeleton.h | 8 +- soh/soh/resource/type/SkeletonLimb.cpp | 4 +- soh/soh/resource/type/SkeletonLimb.h | 8 +- soh/soh/resource/type/SohResourceType.h | 21 +++ soh/soh/resource/type/Text.cpp | 4 +- soh/soh/resource/type/Text.h | 6 +- .../resource/type/scenecommand/EndMarker.cpp | 4 +- .../resource/type/scenecommand/EndMarker.h | 2 +- soh/soh/resource/type/scenecommand/RomFile.h | 2 +- .../resource/type/scenecommand/SceneCommand.h | 6 +- .../type/scenecommand/SetActorList.cpp | 4 +- .../resource/type/scenecommand/SetActorList.h | 2 +- .../type/scenecommand/SetAlternateHeaders.cpp | 4 +- .../type/scenecommand/SetAlternateHeaders.h | 2 +- .../type/scenecommand/SetCameraSettings.cpp | 4 +- .../type/scenecommand/SetCameraSettings.h | 2 +- .../type/scenecommand/SetCollisionHeader.cpp | 4 +- .../type/scenecommand/SetCollisionHeader.h | 2 +- .../type/scenecommand/SetCsCamera.cpp | 4 +- .../resource/type/scenecommand/SetCsCamera.h | 2 +- .../type/scenecommand/SetCutscenes.cpp | 4 +- .../resource/type/scenecommand/SetCutscenes.h | 2 +- .../type/scenecommand/SetEchoSettings.cpp | 4 +- .../type/scenecommand/SetEchoSettings.h | 2 +- .../type/scenecommand/SetEntranceList.cpp | 4 +- .../type/scenecommand/SetEntranceList.h | 2 +- .../type/scenecommand/SetExitList.cpp | 4 +- .../resource/type/scenecommand/SetExitList.h | 2 +- .../type/scenecommand/SetLightList.cpp | 4 +- .../resource/type/scenecommand/SetLightList.h | 2 +- .../type/scenecommand/SetLightingSettings.cpp | 4 +- .../type/scenecommand/SetLightingSettings.h | 2 +- .../resource/type/scenecommand/SetMesh.cpp | 4 +- soh/soh/resource/type/scenecommand/SetMesh.h | 2 +- .../type/scenecommand/SetObjectList.cpp | 4 +- .../type/scenecommand/SetObjectList.h | 2 +- .../type/scenecommand/SetPathways.cpp | 4 +- .../resource/type/scenecommand/SetPathways.h | 2 +- .../type/scenecommand/SetRoomBehavior.cpp | 4 +- .../type/scenecommand/SetRoomBehavior.h | 2 +- .../type/scenecommand/SetRoomList.cpp | 4 +- .../resource/type/scenecommand/SetRoomList.h | 2 +- .../type/scenecommand/SetSkyboxModifier.cpp | 4 +- .../type/scenecommand/SetSkyboxModifier.h | 2 +- .../type/scenecommand/SetSkyboxSettings.cpp | 4 +- .../type/scenecommand/SetSkyboxSettings.h | 2 +- .../type/scenecommand/SetSoundSettings.cpp | 4 +- .../type/scenecommand/SetSoundSettings.h | 2 +- .../type/scenecommand/SetSpecialObjects.cpp | 4 +- .../type/scenecommand/SetSpecialObjects.h | 2 +- .../scenecommand/SetStartPositionList.cpp | 4 +- .../type/scenecommand/SetStartPositionList.h | 2 +- .../type/scenecommand/SetTimeSettings.cpp | 4 +- .../type/scenecommand/SetTimeSettings.h | 2 +- .../scenecommand/SetTransitionActorList.cpp | 4 +- .../scenecommand/SetTransitionActorList.h | 2 +- .../type/scenecommand/SetWindSettings.cpp | 4 +- .../type/scenecommand/SetWindSettings.h | 2 +- soh/soh/z_message_OTR.cpp | 8 +- soh/soh/z_play_otr.cpp | 4 +- soh/soh/z_scene_otr.cpp | 154 +++++++++--------- 163 files changed, 990 insertions(+), 2000 deletions(-) create mode 100644 soh/soh/resource/type/SohResourceType.h diff --git a/OTRExporter b/OTRExporter index d8f3c4dd4..e93bd2be0 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit d8f3c4dd4a46fb46c4f69cd387afadfa711606e9 +Subproject commit e93bd2be062b13106fdb29d98cf4ada4d7ad6827 diff --git a/libultraship b/libultraship index d5a39635a..a516b66ce 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit d5a39635a118f814613c0fdd1601f80c809a742d +Subproject commit a516b66ce0c89fe4e33c55b1fbfbde845d0bf129 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 9548de28d..4d82de6bc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -92,6 +92,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include // Resource Types/Factories +#include "soh/resource/type/SohResourceType.h" #include "soh/resource/type/Animation.h" #include "soh/resource/type/AudioSample.h" #include "soh/resource/type/AudioSequence.h" @@ -319,19 +320,24 @@ OTRGlobals::OTRGlobals() { SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Animation), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_PlayerAnimation), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Room), std::make_shared()); // Is room scene? maybe? - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_CollisionHeader), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Skeleton), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_SkeletonLimb), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Path), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Cutscene), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Text), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSample), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSoundFont), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_AudioSequence), std::make_shared()); - context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(static_cast(LUS::ResourceType::SOH_Background), std::make_shared()); + auto loader = context->GetResourceManager()->GetResourceLoader(); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Animation", static_cast(SOH::ResourceType::SOH_Animation), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast(SOH::ResourceType::SOH_PlayerAnimation), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "CollisionHeader", static_cast(SOH::ResourceType::SOH_CollisionHeader), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "CollisionHeader", static_cast(SOH::ResourceType::SOH_CollisionHeader), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Skeleton", static_cast(SOH::ResourceType::SOH_Skeleton), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "Skeleton", static_cast(SOH::ResourceType::SOH_Skeleton), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "SkeletonLimb", static_cast(SOH::ResourceType::SOH_SkeletonLimb), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "SkeletonLimb", static_cast(SOH::ResourceType::SOH_SkeletonLimb), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Path", static_cast(SOH::ResourceType::SOH_Path), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Cutscene", static_cast(SOH::ResourceType::SOH_Cutscene), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Text", static_cast(SOH::ResourceType::SOH_Text), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "Text", static_cast(SOH::ResourceType::SOH_Text), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSample", static_cast(SOH::ResourceType::SOH_AudioSample), 2); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast(SOH::ResourceType::SOH_AudioSoundFont), 2); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 2); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); gSaveStateMgr = std::make_shared(); gRandomizer = std::make_shared(); @@ -1390,7 +1396,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { // Actually update the CVar now before runing the alt asset update listeners CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); gfx_texture_cache_clear(); - LUS::SkeletonPatcher::UpdateSkeletons(); + SOH::SkeletonPatcher::UpdateSkeletons(); GameInteractor::Instance->ExecuteHooks(); } @@ -1618,7 +1624,7 @@ extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) { extern "C" uint8_t ResourceMgr_ResourceIsBackground(char* texPath) { auto res = GetResourceByNameHandlingMQ(texPath); - return res->GetInitData()->Type == static_cast(LUS::ResourceType::SOH_Background); + return res->GetInitData()->Type == static_cast(SOH::ResourceType::SOH_Background); } extern "C" char* ResourceMgr_LoadJPEG(char* data, size_t dataSize) @@ -1689,7 +1695,7 @@ extern "C" Sprite* GetSeedTexture(uint8_t index) { } extern "C" char* ResourceMgr_LoadPlayerAnimByName(const char* animPath) { - auto anim = std::static_pointer_cast(GetResourceByNameHandlingMQ(animPath)); + auto anim = std::static_pointer_cast(GetResourceByNameHandlingMQ(animPath)); return (char*)&anim->limbRotData[0]; } @@ -1953,7 +1959,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel // Therefore we can take this oppurtunity to take note of the Skeleton that is created... if (skelAnime != nullptr) { auto stringPath = std::string(path); - LUS::SkeletonPatcher::RegisterSkeleton(stringPath, skelAnime); + SOH::SkeletonPatcher::RegisterSkeleton(stringPath, skelAnime); } return skelHeader; @@ -1961,12 +1967,12 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel extern "C" void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime) { if (skelAnime != nullptr) - LUS::SkeletonPatcher::UnregisterSkeleton(skelAnime); + SOH::SkeletonPatcher::UnregisterSkeleton(skelAnime); } extern "C" void ResourceMgr_ClearSkeletons(SkelAnime* skelAnime) { if (skelAnime != nullptr) - LUS::SkeletonPatcher::ClearSkeletons(); + SOH::SkeletonPatcher::ClearSkeletons(); } extern "C" s32* ResourceMgr_LoadCSByName(const char* path) { diff --git a/soh/soh/resource/importer/AnimationFactory.cpp b/soh/soh/resource/importer/AnimationFactory.cpp index c2aaf3067..8e1aca9b7 100644 --- a/soh/soh/resource/importer/AnimationFactory.cpp +++ b/soh/soh/resource/importer/AnimationFactory.cpp @@ -2,32 +2,14 @@ #include "soh/resource/type/Animation.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -AnimationFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Animation with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::AnimationFactoryV0::ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) { - std::shared_ptr animation = std::static_pointer_cast(resource); - - ResourceVersionFactory::ParseFileBinary(reader, animation); + auto animation = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); AnimationType animType = (AnimationType)reader->ReadUInt32(); animation->type = animType; @@ -100,5 +82,7 @@ void LUS::AnimationFactoryV0::ParseFileBinary(std::shared_ptr read } else if (animType == AnimationType::Legacy) { SPDLOG_DEBUG("BEYTAH ANIMATION?!"); } + + return animation; } -} // namespace LUS +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/importer/AnimationFactory.h b/soh/soh/resource/importer/AnimationFactory.h index dee2026f9..36dfceaae 100644 --- a/soh/soh/resource/importer/AnimationFactory.h +++ b/soh/soh/resource/importer/AnimationFactory.h @@ -1,17 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class AnimationFactory : public ResourceFactory { +namespace SOH { +class ResourceFactoryBinaryAnimationV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class AnimationFactoryV0 : public ResourceVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/AudioSampleFactory.cpp b/soh/soh/resource/importer/AudioSampleFactory.cpp index 9d1477a51..b45e698e5 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.cpp +++ b/soh/soh/resource/importer/AudioSampleFactory.cpp @@ -2,33 +2,14 @@ #include "soh/resource/type/AudioSample.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -AudioSampleFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 2: - factory = std::make_shared(); - break; +namespace SOH { +std::shared_ptr ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; } - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load AudioSample with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::AudioSampleFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr audioSample = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, audioSample); + auto audioSample = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); audioSample->sample.codec = reader->ReadUByte(); audioSample->sample.medium = reader->ReadUByte(); @@ -65,9 +46,10 @@ void LUS::AudioSampleFactoryV0::ParseFileBinary(std::shared_ptr re } audioSample->book.book = audioSample->bookData.data(); audioSample->sample.book = &audioSample->book; -} -} // namespace LUS + return audioSample; +} +} // namespace SOH /* in ResourceMgr_LoadAudioSample we used to have diff --git a/soh/soh/resource/importer/AudioSampleFactory.h b/soh/soh/resource/importer/AudioSampleFactory.h index 6e9ddc17c..2680ccdc2 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.h +++ b/soh/soh/resource/importer/AudioSampleFactory.h @@ -1,19 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class AudioSampleFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryAudioSampleV2 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class AudioSampleFactoryV0 : public ResourceVersionFactory -{ - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/AudioSequenceFactory.cpp b/soh/soh/resource/importer/AudioSequenceFactory.cpp index a4862cb19..ba2a36697 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.cpp +++ b/soh/soh/resource/importer/AudioSequenceFactory.cpp @@ -2,33 +2,14 @@ #include "soh/resource/type/AudioSequence.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -AudioSequenceFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 2: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load AudioSequence with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::AudioSequenceFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr audioSequence = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, audioSequence); + auto audioSequence = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); audioSequence->sequence.seqDataSize = reader->ReadInt32(); audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize); @@ -48,5 +29,7 @@ void LUS::AudioSequenceFactoryV0::ParseFileBinary(std::shared_ptr for (uint32_t i = 0; i < audioSequence->sequence.numFonts; i++) { audioSequence->sequence.fonts[i] = reader->ReadUByte(); } + + return audioSequence; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/AudioSequenceFactory.h b/soh/soh/resource/importer/AudioSequenceFactory.h index 12b3809aa..fb4391d61 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.h +++ b/soh/soh/resource/importer/AudioSequenceFactory.h @@ -1,19 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class AudioSequenceFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryAudioSequenceV2 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class AudioSequenceFactoryV0 : public ResourceVersionFactory -{ - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.cpp b/soh/soh/resource/importer/AudioSoundFontFactory.cpp index 5a94cb5f8..6d7efc58c 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.cpp +++ b/soh/soh/resource/importer/AudioSoundFontFactory.cpp @@ -3,33 +3,14 @@ #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" -namespace LUS { -std::shared_ptr -AudioSoundFontFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 2: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load AudioSoundFont with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::AudioSoundFontFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr audioSoundFont = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, audioSoundFont); + auto audioSoundFont = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); audioSoundFont->soundFont.fntIndex = reader->ReadInt32(); audioSoundFont->medium = reader->ReadInt8(); @@ -186,5 +167,7 @@ void LUS::AudioSoundFontFactoryV0::ParseFileBinary(std::shared_ptr audioSoundFont->soundEffects.push_back(soundEffect); } audioSoundFont->soundFont.soundEffects = audioSoundFont->soundEffects.data(); + + return audioSoundFont; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.h b/soh/soh/resource/importer/AudioSoundFontFactory.h index 7dd5bc0d5..a63533db9 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.h +++ b/soh/soh/resource/importer/AudioSoundFontFactory.h @@ -1,19 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class AudioSoundFontFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryAudioSoundFontV2 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class AudioSoundFontFactoryV0 : public ResourceVersionFactory -{ - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/BackgroundFactory.cpp b/soh/soh/resource/importer/BackgroundFactory.cpp index 5b09ce70f..07c47cbe9 100644 --- a/soh/soh/resource/importer/BackgroundFactory.cpp +++ b/soh/soh/resource/importer/BackgroundFactory.cpp @@ -2,31 +2,14 @@ #include "soh/resource/type/Background.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -BackgroundFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Background with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryBackgroundV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void BackgroundFactoryV0::ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) { - std::shared_ptr background = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, background); + auto background = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); uint32_t dataSize = reader->ReadUInt32(); @@ -35,5 +18,7 @@ void BackgroundFactoryV0::ParseFileBinary(std::shared_ptr reader, for (uint32_t i = 0; i < dataSize; i++) { background->Data.push_back(reader->ReadUByte()); } + + return background; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/BackgroundFactory.h b/soh/soh/resource/importer/BackgroundFactory.h index 9767fdf8b..787ee509c 100644 --- a/soh/soh/resource/importer/BackgroundFactory.h +++ b/soh/soh/resource/importer/BackgroundFactory.h @@ -1,17 +1,11 @@ #pragma once #include "resource/Resource.h" -#include "resource/ResourceFactory.h" +#include "resource/ResourceFactoryBinary.h" -namespace LUS { -class BackgroundFactory : public ResourceFactory { +namespace SOH { +class ResourceFactoryBinaryBackgroundV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class BackgroundFactoryV0 : public ResourceVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.cpp b/soh/soh/resource/importer/CollisionHeaderFactory.cpp index 9300efdf0..c5372f249 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/CollisionHeaderFactory.cpp @@ -2,54 +2,14 @@ #include "soh/resource/type/CollisionHeader.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -CollisionHeaderFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryCollisionHeaderV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileBinary(reader, resource); - - return resource; -} - -std::shared_ptr -CollisionHeaderFactory::ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileXML(reader, resource); - - return resource; -} - -void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr collisionHeader = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, collisionHeader); + auto collisionHeader = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); collisionHeader->collisionHeaderData.minBounds.x = reader->ReadInt16(); collisionHeader->collisionHeaderData.minBounds.y = reader->ReadInt16(); @@ -159,10 +119,19 @@ void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptrwaterBoxes.push_back(waterBox); } collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data(); + + return collisionHeader; } -void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) { - std::shared_ptr collisionHeader = std::static_pointer_cast(resource); +std::shared_ptr ResourceFactoryXMLCollisionHeaderV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto collisionHeader = std::make_shared(file->InitData); + + auto reader = std::get>(file->Reader)->FirstChildElement(); + auto child = reader->FirstChildElement(); collisionHeader->collisionHeaderData.minBounds.x = reader->IntAttribute("MinBoundsX"); collisionHeader->collisionHeaderData.minBounds.y = reader->IntAttribute("MinBoundsY"); @@ -178,8 +147,6 @@ void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, s zero.z = 0; collisionHeader->camPosDataZero = zero; - auto child = reader->FirstChildElement(); - while (child != nullptr) { std::string childName = child->Name(); if (childName == "Vertex") { @@ -274,5 +241,7 @@ void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, s collisionHeader->collisionHeaderData.cameraDataList = collisionHeader->camData.data(); collisionHeader->collisionHeaderData.cameraDataListLen = collisionHeader->camDataCount; collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data(); + + return collisionHeader; } -} \ No newline at end of file +} // namespace SOH diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.h b/soh/soh/resource/importer/CollisionHeaderFactory.h index e0276b38f..abd878909 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.h +++ b/soh/soh/resource/importer/CollisionHeaderFactory.h @@ -1,20 +1,17 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" -namespace LUS { -class CollisionHeaderFactory : public ResourceFactory { +namespace SOH { +class ResourceFactoryBinaryCollisionHeaderV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; - std::shared_ptr - ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class CollisionHeaderFactoryV0 : public ResourceVersionFactory { +class ResourceFactoryXMLCollisionHeaderV0 : public LUS::ResourceFactoryXML { public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; - void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/CutsceneFactory.cpp b/soh/soh/resource/importer/CutsceneFactory.cpp index 27c747a6e..28f5e642b 100644 --- a/soh/soh/resource/importer/CutsceneFactory.cpp +++ b/soh/soh/resource/importer/CutsceneFactory.cpp @@ -2,36 +2,14 @@ #include "soh/resource/type/Cutscene.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -CutsceneFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Cutscene with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -static inline uint32_t read_CMD_BBBB(std::shared_ptr reader) { +static inline uint32_t read_CMD_BBBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); return v; } -static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { +static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); @@ -46,7 +24,7 @@ static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { return v; } -static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { +static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); @@ -61,7 +39,7 @@ static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { return v; } -static inline uint32_t read_CMD_HH(std::shared_ptr reader) { +static inline uint32_t read_CMD_HH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); @@ -79,11 +57,14 @@ static inline uint32_t read_CMD_HH(std::shared_ptr reader) { return v; } -void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr cutscene = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, cutscene); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryCutsceneV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto cutscene = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); uint32_t numEntries = reader->ReadUInt32(); cutscene->commands.reserve(numEntries); @@ -459,7 +440,7 @@ void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr reade case 0xFFFFFFFF: // CS_END { cutscene->commands.push_back(reader->ReadUInt32()); - return; + return cutscene; } default: SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId); @@ -467,5 +448,7 @@ void LUS::CutsceneFactoryV0::ParseFileBinary(std::shared_ptr reade break; } } + + return cutscene; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/CutsceneFactory.h b/soh/soh/resource/importer/CutsceneFactory.h index a5813f6fe..8194615af 100644 --- a/soh/soh/resource/importer/CutsceneFactory.h +++ b/soh/soh/resource/importer/CutsceneFactory.h @@ -1,19 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class CutsceneFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryCutsceneV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class CutsceneFactoryV0 : public ResourceVersionFactory -{ - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/PathFactory.cpp b/soh/soh/resource/importer/PathFactory.cpp index bb4f87eb6..07fc86f40 100644 --- a/soh/soh/resource/importer/PathFactory.cpp +++ b/soh/soh/resource/importer/PathFactory.cpp @@ -2,32 +2,14 @@ #include "soh/resource/type/Path.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -PathFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; +namespace SOH { +std::shared_ptr ResourceFactoryBinaryPathV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; } - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Path with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::PathFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr path = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, path); + auto path = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); path->numPaths = reader->ReadUInt32(); path->paths.reserve(path->numPaths); @@ -52,5 +34,7 @@ void LUS::PathFactoryV0::ParseFileBinary(std::shared_ptr reader, path->pathData.push_back(pathDataEntry); } + + return path; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/PathFactory.h b/soh/soh/resource/importer/PathFactory.h index 3a8c0d595..aa8ae747c 100644 --- a/soh/soh/resource/importer/PathFactory.h +++ b/soh/soh/resource/importer/PathFactory.h @@ -1,19 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class PathFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryPathV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class PathFactoryV0 : public ResourceVersionFactory -{ - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/PlayerAnimationFactory.cpp b/soh/soh/resource/importer/PlayerAnimationFactory.cpp index ae9457669..4c25d5e80 100644 --- a/soh/soh/resource/importer/PlayerAnimationFactory.cpp +++ b/soh/soh/resource/importer/PlayerAnimationFactory.cpp @@ -2,34 +2,14 @@ #include "soh/resource/type/PlayerAnimation.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -PlayerAnimationFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; +namespace SOH { +std::shared_ptr ResourceFactoryBinaryPlayerAnimationV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; } - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load PlayerAnimation with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::PlayerAnimationFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr playerAnimation = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, playerAnimation); + auto playerAnimation = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); uint32_t numEntries = reader->ReadUInt32(); playerAnimation->limbRotData.reserve(numEntries); @@ -37,5 +17,7 @@ void LUS::PlayerAnimationFactoryV0::ParseFileBinary(std::shared_ptrlimbRotData.push_back(reader->ReadInt16()); } -} -} // namespace LUS + + return playerAnimation; +}; +} // namespace SOH diff --git a/soh/soh/resource/importer/PlayerAnimationFactory.h b/soh/soh/resource/importer/PlayerAnimationFactory.h index b4981f7c6..8b459a38b 100644 --- a/soh/soh/resource/importer/PlayerAnimationFactory.h +++ b/soh/soh/resource/importer/PlayerAnimationFactory.h @@ -1,17 +1,11 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class PlayerAnimationFactory : public ResourceFactory { +namespace SOH { +class ResourceFactoryBinaryPlayerAnimationV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; - -class PlayerAnimationFactoryV0 : public ResourceVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/SceneFactory.cpp b/soh/soh/resource/importer/SceneFactory.cpp index b71f78a2c..679d574cb 100644 --- a/soh/soh/resource/importer/SceneFactory.cpp +++ b/soh/soh/resource/importer/SceneFactory.cpp @@ -1,4 +1,5 @@ #include "spdlog/spdlog.h" +#include "soh/resource/type/SohResourceType.h" #include "soh/resource/importer/SceneFactory.h" #include "soh/resource/type/Scene.h" #include "soh/resource/type/scenecommand/SceneCommand.h" @@ -28,67 +29,36 @@ #include "soh/resource/importer/scenecommand/SetLightListFactory.h" #include "soh/resource/importer/scenecommand/SetMeshFactory.h" -namespace LUS { - -std::shared_ptr -SceneFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - if (SceneFactory::sceneCommandFactories.empty()) { - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightingSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetWind] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetExitList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTimeSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxModifier] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEchoSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSoundSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSkyboxSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomBehavior] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCsCamera] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCameraSettings] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetRoomList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCollisionHeader] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetEntranceList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetSpecialObjects] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetObjectList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetStartPositionList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetActorList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetTransitionActorList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::EndMarker] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetAlternateHeaders] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetPathways] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetCutscenes] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetLightList] = std::make_shared(); - SceneFactory::sceneCommandFactories[LUS::SceneCommandID::SetMesh] = std::make_shared(); - } - - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Scene with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; +namespace SOH { +ResourceFactoryBinarySceneV0::ResourceFactoryBinarySceneV0() { + sceneCommandFactories[SceneCommandID::SetLightingSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetWind] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetExitList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetTimeSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSkyboxModifier] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetEchoSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSoundSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSkyboxSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetRoomBehavior] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCsCamera] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCameraSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetRoomList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCollisionHeader] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetEntranceList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSpecialObjects] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetObjectList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetStartPositionList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetActorList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetTransitionActorList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::EndMarker] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetAlternateHeaders] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetPathways] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCutscenes] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetLightList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetMesh] = std::make_shared(); } -void SceneFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr scene = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, scene); - - ParseSceneCommands(scene, reader); -} - -void SceneFactoryV0::ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader) { +void ResourceFactoryBinarySceneV0::ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader) { uint32_t commandCount = reader->ReadUInt32(); scene->commands.reserve(commandCount); @@ -97,19 +67,19 @@ void SceneFactoryV0::ParseSceneCommands(std::shared_ptr scene, std::share } } -std::shared_ptr SceneFactoryV0::ParseSceneCommand(std::shared_ptr scene, - std::shared_ptr reader, uint32_t index) { +std::shared_ptr ResourceFactoryBinarySceneV0::ParseSceneCommand(std::shared_ptr scene, + std::shared_ptr reader, uint32_t index) { SceneCommandID cmdID = (SceneCommandID)reader->ReadInt32(); - reader->Seek(-sizeof(int32_t), SeekOffsetType::Current); + reader->Seek(-sizeof(int32_t), LUS::SeekOffsetType::Current); std::shared_ptr result = nullptr; - std::shared_ptr commandFactory = SceneFactory::sceneCommandFactories[cmdID]; + auto commandFactory = ResourceFactoryBinarySceneV0::sceneCommandFactories[cmdID]; if (commandFactory != nullptr) { - auto initData = std::make_shared(); + auto initData = std::make_shared(); initData->Id = scene->GetInitData()->Id; - initData->Type = static_cast(ResourceType::SOH_SceneCommand); + initData->Type = static_cast(SOH::ResourceType::SOH_SceneCommand); initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index); initData->ResourceVersion = scene->GetInitData()->ResourceVersion; result = std::static_pointer_cast(commandFactory->ReadResource(initData, reader)); @@ -123,4 +93,16 @@ std::shared_ptr SceneFactoryV0::ParseSceneCommand(std::shared_ptr return result; } -} // namespace LUS +std::shared_ptr ResourceFactoryBinarySceneV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto scene = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + ParseSceneCommands(scene, reader); + + return scene; +}; +} // namespace SOH diff --git a/soh/soh/resource/importer/SceneFactory.h b/soh/soh/resource/importer/SceneFactory.h index 59fe08ddf..5dfed2739 100644 --- a/soh/soh/resource/importer/SceneFactory.h +++ b/soh/soh/resource/importer/SceneFactory.h @@ -4,26 +4,22 @@ #include "soh/resource/type/scenecommand/SceneCommand.h" #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" -namespace LUS { -class SceneFactory : public ResourceFactory { +namespace SOH { +class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + ResourceFactoryBinarySceneV0(); + + std::shared_ptr ReadResource(std::shared_ptr file) override; + void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); // Doing something very similar to what we do on the ResourceLoader. // Eventually, scene commands should be moved up to the ResourceLoader as well. // They can not right now because the exporter does not give them a proper resource type enum value, // and the exporter does not export the commands with a proper OTR header. - static inline std::unordered_map> sceneCommandFactories; -}; - -class SceneFactoryV0 : public ResourceVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; - void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); + static inline std::unordered_map> sceneCommandFactories; protected: - std::shared_ptr ParseSceneCommand(std::shared_ptr scene, std::shared_ptr reader, uint32_t index); + std::shared_ptr ParseSceneCommand(std::shared_ptr scene, std::shared_ptr reader, uint32_t index); }; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/SkeletonFactory.cpp b/soh/soh/resource/importer/SkeletonFactory.cpp index 2ce651dee..fedfda400 100644 --- a/soh/soh/resource/importer/SkeletonFactory.cpp +++ b/soh/soh/resource/importer/SkeletonFactory.cpp @@ -3,54 +3,14 @@ #include #include -namespace LUS { -std::shared_ptr -SkeletonFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -std::shared_ptr -SkeletonFactory::ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Skeleton with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinarySkeletonV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileXML(reader, resource); - - return resource; -} - -void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr skeleton = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, skeleton); + auto skeleton = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); skeleton->type = (SkeletonType)reader->ReadInt8(); skeleton->limbType = (LimbType)reader->ReadInt8(); @@ -66,17 +26,17 @@ void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr reader, skeleton->limbTable.push_back(limbPath); } - if (skeleton->type == LUS::SkeletonType::Curve) { + if (skeleton->type == SkeletonType::Curve) { skeleton->skeletonData.skelCurveLimbList.limbCount = skeleton->limbCount; skeleton->curveLimbArray.reserve(skeleton->skeletonData.skelCurveLimbList.limbCount); - } else if (skeleton->type == LUS::SkeletonType::Flex) { + } else if (skeleton->type == SkeletonType::Flex) { skeleton->skeletonData.flexSkeletonHeader.dListCount = skeleton->dListCount; } - if (skeleton->type == LUS::SkeletonType::Normal) { + if (skeleton->type == SkeletonType::Normal) { skeleton->skeletonData.skeletonHeader.limbCount = skeleton->limbCount; skeleton->standardLimbArray.reserve(skeleton->skeletonData.skeletonHeader.limbCount); - } else if (skeleton->type == LUS::SkeletonType::Flex) { + } else if (skeleton->type == SkeletonType::Flex) { skeleton->skeletonData.flexSkeletonHeader.sh.limbCount = skeleton->limbCount; skeleton->standardLimbArray.reserve(skeleton->skeletonData.flexSkeletonHeader.sh.limbCount); } @@ -87,21 +47,29 @@ void SkeletonFactoryV0::ParseFileBinary(std::shared_ptr reader, skeleton->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr); } - if (skeleton->type == LUS::SkeletonType::Normal) { + if (skeleton->type == SkeletonType::Normal) { skeleton->skeletonData.skeletonHeader.segment = (void**)skeleton->skeletonHeaderSegments.data(); - } else if (skeleton->type == LUS::SkeletonType::Flex) { + } else if (skeleton->type == SkeletonType::Flex) { skeleton->skeletonData.flexSkeletonHeader.sh.segment = (void**)skeleton->skeletonHeaderSegments.data(); - } else if (skeleton->type == LUS::SkeletonType::Curve) { + } else if (skeleton->type == SkeletonType::Curve) { skeleton->skeletonData.skelCurveLimbList.limbs = (SkelCurveLimb**)skeleton->skeletonHeaderSegments.data(); } else { SPDLOG_ERROR("unknown skeleton type {}", (uint32_t)skeleton->type); } skeleton->skeletonData.skeletonHeader.skeletonType = (uint8_t)skeleton->type; + + return skeleton; } -void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) -{ - std::shared_ptr skel = std::static_pointer_cast(resource); + +std::shared_ptr ResourceFactoryXMLSkeletonV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto skel = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader)->FirstChildElement(); + auto child = reader->FirstChildElement(); skel->type = SkeletonType::Flex; // Default to Flex for legacy reasons if (reader->FindAttribute("Type")) { @@ -137,8 +105,6 @@ void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_p skel->limbCount = reader->IntAttribute("LimbCount"); skel->dListCount = reader->IntAttribute("DisplayListCount"); - auto child = reader->FirstChildElement(); - while (child != nullptr) { std::string childName = child->Name(); @@ -157,6 +123,7 @@ void SkeletonFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_p skel->skeletonData.flexSkeletonHeader.sh.segment = (void**)skel->skeletonHeaderSegments.data(); skel->skeletonData.flexSkeletonHeader.dListCount = skel->dListCount; skel->skeletonData.skeletonHeader.skeletonType = (uint8_t)skel->type; -} -} // namespace LUS + return skel; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/SkeletonFactory.h b/soh/soh/resource/importer/SkeletonFactory.h index d64449393..5de02175f 100644 --- a/soh/soh/resource/importer/SkeletonFactory.h +++ b/soh/soh/resource/importer/SkeletonFactory.h @@ -1,23 +1,17 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" -namespace LUS { -class SkeletonFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinarySkeletonV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; - std::shared_ptr - ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class SkeletonFactoryV0 : public ResourceVersionFactory -{ +class ResourceFactoryXMLSkeletonV0 : public LUS::ResourceFactoryXML { public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; - void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -}; // namespace LUS - +} // namespace SOH diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.cpp b/soh/soh/resource/importer/SkeletonLimbFactory.cpp index 7ca8ae1cc..15ba92281 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.cpp +++ b/soh/soh/resource/importer/SkeletonLimbFactory.cpp @@ -3,54 +3,14 @@ #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" -namespace LUS { -std::shared_ptr -SkeletonLimbFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -std::shared_ptr -SkeletonLimbFactory::ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Skeleton Limb with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinarySkeletonLimbV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileXML(reader, resource); - - return resource; -} - -void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr skeletonLimb = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, skeletonLimb); + auto skeletonLimb = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); skeletonLimb->limbType = (LimbType)reader->ReadInt8(); skeletonLimb->skinSegmentType = (ZLimbSkinType)reader->ReadInt8(); @@ -124,7 +84,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr r skeletonLimb->childIndex = reader->ReadUByte(); skeletonLimb->siblingIndex = reader->ReadUByte(); - if (skeletonLimb->limbType == LUS::LimbType::LOD) { + if (skeletonLimb->limbType == LimbType::LOD) { skeletonLimb->limbData.lodLimb.jointPos.x = skeletonLimb->transX; skeletonLimb->limbData.lodLimb.jointPos.y = skeletonLimb->transY; skeletonLimb->limbData.lodLimb.jointPos.z = skeletonLimb->transZ; @@ -144,7 +104,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr r } else { skeletonLimb->limbData.lodLimb.dLists[1] = nullptr; } - } else if (skeletonLimb->limbType == LUS::LimbType::Standard) { + } else if (skeletonLimb->limbType == LimbType::Standard) { skeletonLimb->limbData.standardLimb.jointPos.x = skeletonLimb->transX; skeletonLimb->limbData.standardLimb.jointPos.y = skeletonLimb->transY; skeletonLimb->limbData.standardLimb.jointPos.z = skeletonLimb->transZ; @@ -156,7 +116,7 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr r skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr; skeletonLimb->limbData.standardLimb.dList = (Gfx*)skeletonLimb->dListPtr.c_str(); } - } else if (skeletonLimb->limbType == LUS::LimbType::Curve) { + } else if (skeletonLimb->limbType == LimbType::Curve) { skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex; skeletonLimb->limbData.skelCurveLimb.nextLimbIdx = skeletonLimb->siblingIndex; skeletonLimb->limbData.skelCurveLimb.dList[0] = nullptr; @@ -171,31 +131,31 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr r skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr; skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str(); } - } else if (skeletonLimb->limbType == LUS::LimbType::Skin) { + } else if (skeletonLimb->limbType == LimbType::Skin) { skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX; skeletonLimb->limbData.skinLimb.jointPos.y = skeletonLimb->transY; skeletonLimb->limbData.skinLimb.jointPos.z = skeletonLimb->transZ; skeletonLimb->limbData.skinLimb.child = skeletonLimb->childIndex; skeletonLimb->limbData.skinLimb.sibling = skeletonLimb->siblingIndex; - if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) { + if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) { skeletonLimb->limbData.skinLimb.segmentType = static_cast(skeletonLimb->skinSegmentType); - } else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) { + } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) { skeletonLimb->limbData.skinLimb.segmentType = 4; - } else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_5) { + } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_5) { skeletonLimb->limbData.skinLimb.segmentType = 5; } else { skeletonLimb->limbData.skinLimb.segmentType = 0; } - if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) { + if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) { if (skeletonLimb->skinDList != "") { skeletonLimb->skinDList = "__OTR__" + skeletonLimb->skinDList; skeletonLimb->limbData.skinLimb.segment = (Gfx*)skeletonLimb->skinDList.c_str(); } else { skeletonLimb->limbData.skinLimb.segment = nullptr; } - } else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) { + } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) { skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt; skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount; skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data(); @@ -220,10 +180,17 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr r skeletonLimb->limbData.skinLimb.segment = &skeletonLimb->skinAnimLimbData; } } + + return skeletonLimb; } -void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) -{ - std::shared_ptr skelLimb = std::static_pointer_cast(resource); + +std::shared_ptr ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto skelLimb = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader)->FirstChildElement(); std::string limbType = reader->Attribute("Type"); @@ -275,6 +242,7 @@ void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shar limbData.lodLimb.sibling = skelLimb->siblingIndex; // skelLimb->dList2Ptr = reader->Attribute("DisplayList2"); -} -} // namespace LUS + return skelLimb; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.h b/soh/soh/resource/importer/SkeletonLimbFactory.h index 8480a0126..125dde2b8 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.h +++ b/soh/soh/resource/importer/SkeletonLimbFactory.h @@ -1,23 +1,17 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" -namespace LUS { -class SkeletonLimbFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinarySkeletonLimbV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; - std::shared_ptr - ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class SkeletonLimbFactoryV0 : public ResourceVersionFactory -{ +class ResourceFactoryXMLSkeletonLimbV0 : public LUS::ResourceFactoryXML { public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; - void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -}; // namespace LUS - +} // namespace SOH diff --git a/soh/soh/resource/importer/TextFactory.cpp b/soh/soh/resource/importer/TextFactory.cpp index 314dd135c..89d229f80 100644 --- a/soh/soh/resource/importer/TextFactory.cpp +++ b/soh/soh/resource/importer/TextFactory.cpp @@ -2,74 +2,38 @@ #include "soh/resource/type/Text.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -TextFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - default: - // VERSION NOT SUPPORTED - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -std::shared_ptr -TextFactory::ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load Text with version {}", resource->GetInitData()->ResourceVersion); +namespace SOH { +std::shared_ptr ResourceFactoryBinaryTextV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { return nullptr; } - factory->ParseFileXML(reader, resource); - - return resource; -} - -void LUS::TextFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr text = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, text); + auto text = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); uint32_t msgCount = reader->ReadUInt32(); text->messages.reserve(msgCount); for (uint32_t i = 0; i < msgCount; i++) { - MessageEntry entry; - entry.id = reader->ReadUInt16(); - entry.textboxType = reader->ReadUByte(); - entry.textboxYPos = reader->ReadUByte(); - entry.msg = reader->ReadString(); + MessageEntry entry; + entry.id = reader->ReadUInt16(); + entry.textboxType = reader->ReadUByte(); + entry.textboxYPos = reader->ReadUByte(); + entry.msg = reader->ReadString(); - text->messages.push_back(entry); + text->messages.push_back(entry); } -} -void TextFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) { - std::shared_ptr txt = std::static_pointer_cast(resource); - auto child = reader->FirstChildElement(); + return text; +} + +std::shared_ptr ResourceFactoryXMLTextV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto txt = std::make_shared(file->InitData); + auto child = std::get>(file->Reader)->FirstChildElement()->FirstChildElement(); while (child != nullptr) { std::string childName = child->Name(); @@ -88,6 +52,7 @@ void TextFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptrNextSiblingElement(); } -} -} // namespace LUS + return txt; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/TextFactory.h b/soh/soh/resource/importer/TextFactory.h index 7a6ae2841..cb466204b 100644 --- a/soh/soh/resource/importer/TextFactory.h +++ b/soh/soh/resource/importer/TextFactory.h @@ -1,23 +1,17 @@ #pragma once #include "Resource.h" -#include "ResourceFactory.h" +#include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" -namespace LUS { -class TextFactory : public ResourceFactory -{ +namespace SOH { +class ResourceFactoryBinaryTextV0 : public LUS::ResourceFactoryBinary { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; - std::shared_ptr - ReadResourceXML(std::shared_ptr initData, tinyxml2::XMLElement *reader) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class TextFactoryV0 : public ResourceVersionFactory -{ +class ResourceFactoryXMLTextV0 : public LUS::ResourceFactoryXML { public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; - void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr resource) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -}; // namespace LUS - +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp index 4134e259a..ffcf17410 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp @@ -2,37 +2,13 @@ #include "soh/resource/type/scenecommand/EndMarker.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -EndMarkerFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load EndMarker with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::EndMarkerFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr endMarker = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, endMarker); +namespace SOH { +std::shared_ptr +EndMarkerFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto endMarker = std::make_shared(initData); ReadCommandId(endMarker, reader); - - // This has no data. -} -} // namespace LUS + return endMarker; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h index 8cd83b4f6..486aaa2fb 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h @@ -2,15 +2,9 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class EndMarkerFactory : public SceneCommandFactory { +namespace SOH { +class EndMarkerFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class EndMarkerFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp index 9ad0ba2d3..9ab5d1611 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp @@ -2,9 +2,8 @@ #include "soh/resource/type/scenecommand/SceneCommand.h" #include "spdlog/spdlog.h" -namespace LUS { -void SceneCommandVersionFactory::ReadCommandId(std::shared_ptr command, std::shared_ptr reader) { +namespace SOH { +void SceneCommandFactoryBinaryV0::ReadCommandId(std::shared_ptr command, std::shared_ptr reader) { command->cmdId = (SceneCommandID)reader->ReadInt32(); } -} - \ No newline at end of file +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h index d9a23818a..4cebc4a64 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h @@ -5,11 +5,12 @@ #include "ResourceFactory.h" #include "soh/resource/type/scenecommand/SceneCommand.h" -namespace LUS { -class SceneCommandFactory : public ResourceFactory {}; +namespace SOH { +class SceneCommandFactoryBinaryV0 { + public: + virtual std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) = 0; -class SceneCommandVersionFactory : public ResourceVersionFactory { -protected: - void ReadCommandId(std::shared_ptr command, std::shared_ptr reader); + protected: + void ReadCommandId(std::shared_ptr command, std::shared_ptr reader); }; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp index 0451eb4c3..86deea193 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp @@ -2,52 +2,30 @@ #include "soh/resource/type/scenecommand/SetActorList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetActorListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetActorList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetActorListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setActorList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setActorList); +namespace SOH { +std::shared_ptr +SetActorListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setActorList = std::make_shared(initData); ReadCommandId(setActorList, reader); setActorList->numActors = reader->ReadUInt32(); setActorList->actorList.reserve(setActorList->numActors); for (uint32_t i = 0; i < setActorList->numActors; i++) { - ActorEntry entry; + ActorEntry entry; - entry.id = reader->ReadUInt16(); - entry.pos.x = reader->ReadInt16(); - entry.pos.y = reader->ReadInt16(); - entry.pos.z = reader->ReadInt16(); - entry.rot.x = reader->ReadInt16(); - entry.rot.y = reader->ReadInt16(); - entry.rot.z = reader->ReadInt16(); - entry.params = reader->ReadUInt16(); + entry.id = reader->ReadUInt16(); + entry.pos.x = reader->ReadInt16(); + entry.pos.y = reader->ReadInt16(); + entry.pos.z = reader->ReadInt16(); + entry.rot.x = reader->ReadInt16(); + entry.rot.y = reader->ReadInt16(); + entry.rot.z = reader->ReadInt16(); + entry.params = reader->ReadUInt16(); setActorList->actorList.push_back(entry); } -} -} // namespace LUS + return setActorList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h index 1f4c213bb..49a269cfe 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetActorListFactory : public SceneCommandFactory { +namespace SOH { +class SetActorListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetActorListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp index 5258d970b..833d0af8c 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp @@ -3,47 +3,24 @@ #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" -namespace LUS { -std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetAlternateHeaders with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetAlternateHeadersFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setAlternateHeaders = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setAlternateHeaders); +namespace SOH { +std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setAlternateHeaders = std::make_shared(initData); ReadCommandId(setAlternateHeaders, reader); setAlternateHeaders->numHeaders = reader->ReadUInt32(); setAlternateHeaders->headers.reserve(setAlternateHeaders->numHeaders); for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { - auto headerName = reader->ReadString(); - if (!headerName.empty()) { - setAlternateHeaders->headers.push_back(std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); - } else { - setAlternateHeaders->headers.push_back(nullptr); - } + auto headerName = reader->ReadString(); + if (!headerName.empty()) { + setAlternateHeaders->headers.push_back(std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + } else { + setAlternateHeaders->headers.push_back(nullptr); + } } -} -} // namespace LUS + return setAlternateHeaders; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h index a534c4392..2bc430c0b 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetAlternateHeadersFactory : public SceneCommandFactory { +namespace SOH { +class SetAlternateHeadersFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetAlternateHeadersFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp index 14b332d2a..7e2911a17 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp @@ -2,38 +2,16 @@ #include "soh/resource/type/scenecommand/SetCameraSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetCameraSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetCameraSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setCameraSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setCameraSettings); +namespace SOH { +std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setCameraSettings = std::make_shared(initData); ReadCommandId(setCameraSettings, reader); setCameraSettings->settings.cameraMovement = reader->ReadInt8(); setCameraSettings->settings.worldMapArea = reader->ReadInt32(); -} -} // namespace LUS + return setCameraSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h index ec4dc9e42..2f1db272f 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetCameraSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetCameraSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetCameraSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp index e1c113ba3..bb83dc57b 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp @@ -3,37 +3,16 @@ #include "libultraship/libultraship.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetCollisionHeader with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetCollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setCollisionHeader = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setCollisionHeader); +namespace SOH { +std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setCollisionHeader = std::make_shared(initData); ReadCommandId(setCollisionHeader, reader); setCollisionHeader->fileName = reader->ReadString(); setCollisionHeader->collisionHeader = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); -} -} // namespace LUS + return setCollisionHeader; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h index 96c6ff0a1..b80ee34b4 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetCollisionHeaderFactory : public SceneCommandFactory { +namespace SOH { +class SetCollisionHeaderFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetCollisionHeaderFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp index d24e3b2c3..84c277989 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp @@ -2,32 +2,10 @@ #include "soh/resource/type/scenecommand/SetCsCamera.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetCsCameraFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetCsCamera with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetCsCameraFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setCsCamera = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setCsCamera); +namespace SOH { +std::shared_ptr +SetCsCameraFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setCsCamera = std::make_shared(initData); ReadCommandId(setCsCamera, reader); @@ -35,6 +13,7 @@ void LUS::SetCsCameraFactoryV0::ParseFileBinary(std::shared_ptr re reader->ReadInt32(); // segOffset // OTRTODO: FINISH! -} -} // namespace LUS + return setCsCamera; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h index ec74ed58e..08dc8e3c3 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetCsCameraFactory : public SceneCommandFactory { +namespace SOH { +class SetCsCameraFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetCsCameraFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp index db9392e7d..30f72d168 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp @@ -3,38 +3,16 @@ #include #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetCutscenesFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetCutscenes with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetCutscenesFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setCutscenes = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setCutscenes); +namespace SOH { +std::shared_ptr +SetCutscenesFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setCutscenes = std::make_shared(initData); ReadCommandId(setCutscenes, reader); setCutscenes->fileName = reader->ReadString(); setCutscenes->cutscene = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); -} -} // namespace LUS + return setCutscenes; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h index 7963036ba..bbbe38c98 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetCutscenesFactory : public SceneCommandFactory { +namespace SOH { +class SetCutscenesFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetCutscenesFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp index 530bcb8af..e9c3381cb 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp @@ -2,37 +2,15 @@ #include "soh/resource/type/scenecommand/SetEchoSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetEchoSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetEchoSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetEchoSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setEchoSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setEchoSettings); +namespace SOH { +std::shared_ptr +SetEchoSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setEchoSettings = std::make_shared(initData); ReadCommandId(setEchoSettings, reader); setEchoSettings->settings.echo = reader->ReadInt8(); -} -} // namespace LUS + return setEchoSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h index 90bf3222f..99bda6eae 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetEchoSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetEchoSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetEchoSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp index 0fd841278..766bb82da 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp @@ -2,32 +2,10 @@ #include "soh/resource/type/scenecommand/SetEntranceList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetEntranceListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetEntranceListList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetEntranceListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setEntranceList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setEntranceList); +namespace SOH { +std::shared_ptr +SetEntranceListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setEntranceList = std::make_shared(initData); ReadCommandId(setEntranceList, reader); @@ -41,6 +19,7 @@ void LUS::SetEntranceListFactoryV0::ParseFileBinary(std::shared_ptrentrances.push_back(entranceEntry); } -} -} // namespace LUS + return setEntranceList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h index ce20db4f7..35b7fba62 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetEntranceListFactory : public SceneCommandFactory { +namespace SOH { +class SetEntranceListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetEntranceListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp index 04ed0c56b..5fef9d096 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp @@ -2,32 +2,10 @@ #include "soh/resource/type/scenecommand/SetExitList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetExitListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared( initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetExitList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetExitListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setExitList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setExitList); +namespace SOH { +std::shared_ptr +SetExitListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setExitList = std::make_shared( initData); ReadCommandId(setExitList, reader); @@ -36,6 +14,7 @@ void LUS::SetExitListFactoryV0::ParseFileBinary(std::shared_ptr re for (uint32_t i = 0; i < setExitList->numExits; i++) { setExitList->exits.push_back(reader->ReadUInt16()); } -} -} // namespace LUS + return setExitList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h index 351ebe7ca..d82e8f04a 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetExitListFactory : public SceneCommandFactory { +namespace SOH { +class SetExitListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetExitListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp index 2d2a9afe4..2d05631cd 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp @@ -2,34 +2,10 @@ #include "soh/resource/type/scenecommand/SetLightList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetLightListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetLightList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetLightListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setLightList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setLightList); +namespace SOH { +std::shared_ptr +SetLightListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setLightList = std::make_shared(initData); ReadCommandId(setLightList, reader); @@ -40,7 +16,7 @@ void LUS::SetLightListFactoryV0::ParseFileBinary(std::shared_ptr r light.type = reader->ReadUByte(); - light.params.point.x = reader->ReadInt16(); + light.params.point.x = reader->ReadInt16(); light.params.point.y = reader->ReadInt16(); light.params.point.z = reader->ReadInt16(); @@ -49,10 +25,11 @@ void LUS::SetLightListFactoryV0::ParseFileBinary(std::shared_ptr r light.params.point.color[2] = reader->ReadUByte(); // b light.params.point.drawGlow = reader->ReadUByte(); - light.params.point.radius = reader->ReadInt16(); + light.params.point.radius = reader->ReadInt16(); setLightList->lightList.push_back(light); } -} -} // namespace LUS + return setLightList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h index 24292a289..1c4a6e9dc 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetLightListFactory : public SceneCommandFactory { +namespace SOH { +class SetLightListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetLightListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp index 3fdedd0e4..d0a7b89d5 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp @@ -2,33 +2,10 @@ #include "soh/resource/type/scenecommand/SetLightingSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetLightingSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetLightingSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetLightingSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setLightingSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setLightingSettings); +namespace SOH { +std::shared_ptr SetLightingSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setLightingSettings = std::make_shared(initData); ReadCommandId(setLightingSettings, reader); @@ -65,6 +42,7 @@ void LUS::SetLightingSettingsFactoryV0::ParseFileBinary(std::shared_ptrReadUInt16(); setLightingSettings->settings.push_back(lightSettings); } -} -} // namespace LUS + return setLightingSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h index 78a624ca6..df25600e2 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetLightingSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetLightingSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetLightingSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp index 1398641a7..8c17ecc07 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp @@ -3,34 +3,10 @@ #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" -namespace LUS { -std::shared_ptr -SetMeshFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetMesh with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetMeshFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setMesh = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setMesh); +namespace SOH { +std::shared_ptr +SetMeshFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setMesh = std::make_shared(initData); ReadCommandId(setMesh, reader); @@ -143,10 +119,10 @@ void LUS::SetMeshFactoryV0::ParseFileBinary(std::shared_ptr reader std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); - dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; - dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + auto opaRes = meshOpa != "" ? LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()) : nullptr; + auto xluRes = meshXlu != "" ? LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()) : nullptr; + dlist.opa = (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr); + dlist.xlu = (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr); setMesh->dlists2.push_back(dlist); } else { @@ -164,6 +140,7 @@ void LUS::SetMeshFactoryV0::ParseFileBinary(std::shared_ptr reader } else { SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); } -} -} // namespace LUS + return setMesh; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h index 8ca086d43..a912bdd37 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetMeshFactory : public SceneCommandFactory { +namespace SOH { +class SetMeshFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetMeshFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp index 27082f6e7..b84befb3b 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp @@ -2,33 +2,10 @@ #include "soh/resource/type/scenecommand/SetObjectList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetObjectListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetObjectList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetObjectListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setObjectList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setObjectList); +namespace SOH { +std::shared_ptr +SetObjectListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setObjectList = std::make_shared(initData); ReadCommandId(setObjectList, reader); @@ -37,6 +14,7 @@ void LUS::SetObjectListFactoryV0::ParseFileBinary(std::shared_ptr for (uint32_t i = 0; i < setObjectList->numObjects; i++) { setObjectList->objects.push_back(reader->ReadUInt16()); } -} -} // namespace LUS + return setObjectList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h index 65725bfb2..4c2f002c0 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetObjectListFactory : public SceneCommandFactory { +namespace SOH { +class SetObjectListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetObjectListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp index 1f40ab69d..61534ba48 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp @@ -3,32 +3,10 @@ #include "spdlog/spdlog.h" #include -namespace LUS { -std::shared_ptr -SetPathwaysFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetPathways with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetPathwaysFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setPathways = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setPathways); +namespace SOH { +std::shared_ptr +SetPathwaysFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setPathways = std::make_shared(initData); ReadCommandId(setPathways, reader); @@ -39,6 +17,7 @@ void LUS::SetPathwaysFactoryV0::ParseFileBinary(std::shared_ptr re auto path = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); setPathways->paths.push_back(path->GetPointer()); } -} -} // namespace LUS + return setPathways; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h index fc9b2c62d..c622c820d 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetPathwaysFactory : public SceneCommandFactory { +namespace SOH { +class SetPathwaysFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetPathwaysFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp index 409e3d410..e4601e59c 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp @@ -2,37 +2,16 @@ #include "soh/resource/type/scenecommand/SetRoomBehavior.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetRoomBehaviorFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetRoomBehavior with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetRoomBehaviorFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setRoomBehavior = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setRoomBehavior); +namespace SOH { +std::shared_ptr +SetRoomBehaviorFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setRoomBehavior = std::make_shared(initData); ReadCommandId(setRoomBehavior, reader); setRoomBehavior->roomBehavior.gameplayFlags = reader->ReadInt8(); setRoomBehavior->roomBehavior.gameplayFlags2 = reader->ReadInt32(); -} -} // namespace LUS + return setRoomBehavior; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h index ef5a77bd4..70a53ba1e 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetRoomBehaviorFactory : public SceneCommandFactory { +namespace SOH { +class SetRoomBehaviorFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetRoomBehaviorFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp index 136b410a0..7726877a1 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp @@ -2,49 +2,27 @@ #include "soh/resource/type/scenecommand/SetRoomList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetRoomListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetRoomList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetRoomListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setRoomList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setRoomList); +namespace SOH { +std::shared_ptr +SetRoomListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setRoomList = std::make_shared(initData); ReadCommandId(setRoomList, reader); setRoomList->numRooms = reader->ReadInt32(); setRoomList->rooms.reserve(setRoomList->numRooms); for (uint32_t i = 0; i < setRoomList->numRooms; i++) { - RomFile room; + RomFile room; - setRoomList->fileNames.push_back(reader->ReadString()); + setRoomList->fileNames.push_back(reader->ReadString()); - room.fileName = (char*)setRoomList->fileNames.back().c_str(); - room.vromStart = reader->ReadInt32(); - room.vromEnd = reader->ReadInt32(); + room.fileName = (char*)setRoomList->fileNames.back().c_str(); + room.vromStart = reader->ReadInt32(); + room.vromEnd = reader->ReadInt32(); setRoomList->rooms.push_back(room); } -} -} // namespace LUS + return setRoomList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h index 1ba5e5c1f..6bf9eaa5c 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetRoomListFactory : public SceneCommandFactory { +namespace SOH { +class SetRoomListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetRoomListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp index b68d2e56d..291ae578c 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp @@ -2,37 +2,16 @@ #include "soh/resource/type/scenecommand/SetSkyboxModifier.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetSkyboxModifier with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetSkyboxModifierFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setSkyboxModifier = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setSkyboxModifier); +namespace SOH { +std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setSkyboxModifier = std::make_shared(initData); ReadCommandId(setSkyboxModifier, reader); setSkyboxModifier->modifier.skyboxDisabled = reader->ReadInt8(); setSkyboxModifier->modifier.sunMoonDisabled = reader->ReadInt8(); -} -} // namespace LUS + return setSkyboxModifier; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h index 9556b6699..d467cc73d 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetSkyboxModifierFactory : public SceneCommandFactory { +namespace SOH { +class SetSkyboxModifierFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetSkyboxModifierFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp index 3b793c80e..f3e726b07 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp @@ -2,32 +2,10 @@ #include "soh/resource/type/scenecommand/SetSkyboxSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetSkyboxSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void SetSkyboxSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setSkyboxSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setSkyboxSettings); +namespace SOH { +std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setSkyboxSettings = std::make_shared(initData); ReadCommandId(setSkyboxSettings, reader); @@ -35,6 +13,7 @@ void SetSkyboxSettingsFactoryV0::ParseFileBinary(std::shared_ptr r setSkyboxSettings->settings.skyboxId = reader->ReadInt8(); setSkyboxSettings->settings.weather = reader->ReadInt8(); setSkyboxSettings->settings.indoors = reader->ReadInt8(); -} -} // namespace LUS + return setSkyboxSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h index 7c2da4bb1..581e56122 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetSkyboxSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetSkyboxSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetSkyboxSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp index 1817af81d..f85178e22 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp @@ -2,38 +2,17 @@ #include "soh/resource/type/scenecommand/SetSoundSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetSoundSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetSoundSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetSoundSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setSoundSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setSoundSettings); +namespace SOH { +std::shared_ptr SetSoundSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setSoundSettings = std::make_shared(initData); ReadCommandId(setSoundSettings, reader); setSoundSettings->settings.reverb = reader->ReadInt8(); setSoundSettings->settings.natureAmbienceId = reader->ReadInt8(); setSoundSettings->settings.seqId = reader->ReadInt8(); -} -} // namespace LUS + return setSoundSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h index 7195b0fb6..e1c4efb03 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetSoundSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetSoundSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetSoundSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp index 5f818f1d4..b7fd21aa4 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp @@ -2,37 +2,16 @@ #include "soh/resource/type/scenecommand/SetSpecialObjects.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr){ - SPDLOG_ERROR("Failed to load SetSpecialObjects with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetSpecialObjectsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setSpecialObjects = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setSpecialObjects); +namespace SOH { +std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setSpecialObjects = std::make_shared(initData); ReadCommandId(setSpecialObjects, reader); setSpecialObjects->specialObjects.elfMessage = reader->ReadInt8(); setSpecialObjects->specialObjects.globalObject = reader->ReadInt16(); -} -} // namespace LUS + return setSpecialObjects; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h index 3e3fc77d0..503cfb61f 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetSpecialObjectsFactory : public SceneCommandFactory { +namespace SOH { +class SetSpecialObjectsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetSpecialObjectsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp index bafb0b153..3165b4361 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp @@ -2,54 +2,30 @@ #include "soh/resource/type/scenecommand/SetStartPositionList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetStartPositionListFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) - { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) - { - SPDLOG_ERROR("Failed to load SetStartPositionList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetStartPositionListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) -{ - std::shared_ptr setStartPositionList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setStartPositionList); +namespace SOH { +std::shared_ptr SetStartPositionListFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setStartPositionList = std::make_shared(initData); ReadCommandId(setStartPositionList, reader); setStartPositionList->numStartPositions = reader->ReadUInt32(); setStartPositionList->startPositions.reserve(setStartPositionList->numStartPositions); for (uint32_t i = 0; i < setStartPositionList->numStartPositions; i++) { - ActorEntry entry; + ActorEntry entry; - entry.id = reader->ReadUInt16(); - entry.pos.x = reader->ReadInt16(); - entry.pos.y = reader->ReadInt16(); - entry.pos.z = reader->ReadInt16(); - entry.rot.x = reader->ReadInt16(); - entry.rot.y = reader->ReadInt16(); - entry.rot.z = reader->ReadInt16(); - entry.params = reader->ReadUInt16(); + entry.id = reader->ReadUInt16(); + entry.pos.x = reader->ReadInt16(); + entry.pos.y = reader->ReadInt16(); + entry.pos.z = reader->ReadInt16(); + entry.rot.x = reader->ReadInt16(); + entry.rot.y = reader->ReadInt16(); + entry.rot.z = reader->ReadInt16(); + entry.params = reader->ReadUInt16(); setStartPositionList->startPositions.push_back(entry); } -} -} // namespace LUS + return setStartPositionList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h index d2bbcb6a6..b07901f05 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetStartPositionListFactory : public SceneCommandFactory { +namespace SOH { +class SetStartPositionListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetStartPositionListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp index ab2ac12f0..d83b24583 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp @@ -2,38 +2,17 @@ #include "soh/resource/type/scenecommand/SetTimeSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetTimeSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetTimeSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetTimeSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setTimeSettings = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setTimeSettings); +namespace SOH { +std::shared_ptr +SetTimeSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setTimeSettings = std::make_shared(initData); ReadCommandId(setTimeSettings, reader); setTimeSettings->settings.hour = reader->ReadInt8(); setTimeSettings->settings.minute = reader->ReadInt8(); setTimeSettings->settings.timeIncrement = reader->ReadInt8(); -} -} // namespace LUS + return setTimeSettings; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h index b7ee1083c..d1336f788 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetTimeSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetTimeSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetTimeSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp index 575151bab..c751ad611 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp @@ -2,33 +2,11 @@ #include "soh/resource/type/scenecommand/SetTransitionActorList.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr SetTransitionActorListFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetTransitionActorList with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetTransitionActorListFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setTransitionActorList = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setTransitionActorList); - +namespace SOH { +std::shared_ptr SetTransitionActorListFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { + auto setTransitionActorList = std::make_shared(initData); + ReadCommandId(setTransitionActorList, reader); setTransitionActorList->numTransitionActors = reader->ReadUInt32(); @@ -49,6 +27,7 @@ void LUS::SetTransitionActorListFactoryV0::ParseFileBinary(std::shared_ptrtransitionActorList.push_back(entry); } -} -} // namespace LUS + return setTransitionActorList; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h index 25343ced8..c8fb65f9a 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetTransitionActorListFactory : public SceneCommandFactory { +namespace SOH { +class SetTransitionActorListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetTransitionActorListFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp index 995045014..3208004ce 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp @@ -2,32 +2,10 @@ #include "soh/resource/type/scenecommand/SetWindSettings.h" #include "spdlog/spdlog.h" -namespace LUS { -std::shared_ptr -SetWindSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { - auto resource = std::make_shared(initData); - std::shared_ptr factory = nullptr; - - switch (resource->GetInitData()->ResourceVersion) { - case 0: - factory = std::make_shared(); - break; - } - - if (factory == nullptr) { - SPDLOG_ERROR("Failed to load SetWindSettings with version {}", resource->GetInitData()->ResourceVersion); - return nullptr; - } - - factory->ParseFileBinary(reader, resource); - - return resource; -} - -void LUS::SetWindSettingsFactoryV0::ParseFileBinary(std::shared_ptr reader, - std::shared_ptr resource) { - std::shared_ptr setWind = std::static_pointer_cast(resource); - ResourceVersionFactory::ParseFileBinary(reader, setWind); +namespace SOH { +std::shared_ptr +SetWindSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { + auto setWind = std::make_shared(initData); ReadCommandId(setWind, reader); @@ -35,6 +13,7 @@ void LUS::SetWindSettingsFactoryV0::ParseFileBinary(std::shared_ptrsettings.windVertical = reader->ReadInt8(); setWind->settings.windSouth = reader->ReadInt8(); setWind->settings.windSpeed = reader->ReadUByte(); -} -} // namespace LUS + return setWind; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h index 0a783bb9f..6cc9fbc1b 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h @@ -2,15 +2,10 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" -namespace LUS { -class SetWindSettingsFactory : public SceneCommandFactory { +namespace SOH { +class SetWindSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; - -class SetWindSettingsFactoryV0 : public SceneCommandVersionFactory { - public: - void ParseFileBinary(std::shared_ptr reader, std::shared_ptr resource) override; -}; -}; // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Animation.cpp b/soh/soh/resource/type/Animation.cpp index 46327c732..d11d05394 100644 --- a/soh/soh/resource/type/Animation.cpp +++ b/soh/soh/resource/type/Animation.cpp @@ -1,6 +1,6 @@ #include "Animation.h" -namespace LUS { +namespace SOH { AnimationData* Animation::GetPointer() { return &animationData; } @@ -18,4 +18,4 @@ size_t Animation::GetPointerSize() { return 0; } } -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/Animation.h b/soh/soh/resource/type/Animation.h index 3d6b810bf..abd319d97 100644 --- a/soh/soh/resource/type/Animation.h +++ b/soh/soh/resource/type/Animation.h @@ -3,85 +3,85 @@ #include "Resource.h" #include -namespace LUS { - enum class AnimationType { - Normal = 0, - Link = 1, - Curve = 2, - Legacy = 3, - }; +namespace SOH { +enum class AnimationType { + Normal = 0, + Link = 1, + Curve = 2, + Legacy = 3, +}; - struct RotationIndex { - uint16_t x, y, z; +struct RotationIndex { + uint16_t x, y, z; - RotationIndex(uint16_t nX, uint16_t nY, uint16_t nZ) : x(nX), y(nY), z(nZ) { - } - }; + RotationIndex(uint16_t nX, uint16_t nY, uint16_t nZ) : x(nX), y(nY), z(nZ) { + } +}; - typedef struct { - /* 0x0000 */ u16 unk_00; // appears to be flags - /* 0x0002 */ s16 unk_02; - /* 0x0004 */ s16 unk_04; - /* 0x0006 */ s16 unk_06; - /* 0x0008 */ f32 unk_08; - } TransformData; // size = 0xC +typedef struct { + /* 0x0000 */ u16 unk_00; // appears to be flags + /* 0x0002 */ s16 unk_02; + /* 0x0004 */ s16 unk_04; + /* 0x0006 */ s16 unk_06; + /* 0x0008 */ f32 unk_08; +} TransformData; // size = 0xC - typedef struct { - /* 0x0000 */ u8* refIndex; - /* 0x0004 */ TransformData* transformData; - /* 0x0008 */ s16* copyValues; - /* 0x000C */ s16 unk_0C; - /* 0x000E */ s16 unk_0E; - } TransformUpdateIndex; // size = 0x10 +typedef struct { + /* 0x0000 */ u8* refIndex; + /* 0x0004 */ TransformData* transformData; + /* 0x0008 */ s16* copyValues; + /* 0x000C */ s16 unk_0C; + /* 0x000E */ s16 unk_0E; +} TransformUpdateIndex; // size = 0x10 - typedef struct { - /* 0x00 */ s16 frameCount; - } AnimationHeaderCommon; +typedef struct { + /* 0x00 */ s16 frameCount; +} AnimationHeaderCommon; - // Index into the frame data table. - typedef struct { - /* 0x00 */ u16 x; - /* 0x02 */ u16 y; - /* 0x04 */ u16 z; - } JointIndex; // size = 0x06 +// Index into the frame data table. +typedef struct { + /* 0x00 */ u16 x; + /* 0x02 */ u16 y; + /* 0x04 */ u16 z; +} JointIndex; // size = 0x06 - typedef struct { - /* 0x00 */ AnimationHeaderCommon common; - /* 0x04 */ s16* frameData; // "tbl" - /* 0x08 */ JointIndex* jointIndices; // "ref_tbl" - /* 0x0C */ u16 staticIndexMax; - } AnimationHeader; // size = 0x10 +typedef struct { + /* 0x00 */ AnimationHeaderCommon common; + /* 0x04 */ s16* frameData; // "tbl" + /* 0x08 */ JointIndex* jointIndices; // "ref_tbl" + /* 0x0C */ u16 staticIndexMax; +} AnimationHeader; // size = 0x10 - typedef struct { - /* 0x00 */ AnimationHeaderCommon common; - /* 0x04 */ void* segment; - } LinkAnimationHeader; // size = 0x8 +typedef struct { + /* 0x00 */ AnimationHeaderCommon common; + /* 0x04 */ void* segment; +} LinkAnimationHeader; // size = 0x8 - union AnimationData { - AnimationHeader animationHeader; - LinkAnimationHeader linkAnimationHeader; - TransformUpdateIndex transformUpdateIndex; - }; +union AnimationData { +AnimationHeader animationHeader; +LinkAnimationHeader linkAnimationHeader; +TransformUpdateIndex transformUpdateIndex; +}; - class Animation : public Resource { - public: - using Resource::Resource; +class Animation : public LUS::Resource { +public: + using Resource::Resource; - Animation() : Resource(std::shared_ptr()) {} + Animation() : Resource(std::shared_ptr()) {} - AnimationData* GetPointer(); - size_t GetPointerSize(); + AnimationData* GetPointer(); + size_t GetPointerSize(); - AnimationType type; - AnimationData animationData; + AnimationType type; + AnimationData animationData; - // NORMAL - std::vector rotationValues; - std::vector rotationIndices; + // NORMAL + std::vector rotationValues; + std::vector rotationIndices; - // CURVE - std::vector refIndexArr; - std::vector transformDataArr; - std::vector copyValuesArr; - }; -}; // namespace LUS \ No newline at end of file + // CURVE + std::vector refIndexArr; + std::vector transformDataArr; + std::vector copyValuesArr; +}; +}; // namespace LUS diff --git a/soh/soh/resource/type/AudioSample.cpp b/soh/soh/resource/type/AudioSample.cpp index 951aae6c1..288765822 100644 --- a/soh/soh/resource/type/AudioSample.cpp +++ b/soh/soh/resource/type/AudioSample.cpp @@ -1,6 +1,6 @@ #include "AudioSample.h" -namespace LUS { +namespace SOH { Sample* AudioSample::GetPointer() { return &sample; } @@ -8,4 +8,4 @@ Sample* AudioSample::GetPointer() { size_t AudioSample::GetPointerSize() { return sizeof(Sample); } -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/AudioSample.h b/soh/soh/resource/type/AudioSample.h index eda8aa456..4d6929c59 100644 --- a/soh/soh/resource/type/AudioSample.h +++ b/soh/soh/resource/type/AudioSample.h @@ -5,7 +5,7 @@ #include "Resource.h" #include -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ uintptr_t start; /* 0x04 */ uintptr_t end; @@ -39,11 +39,11 @@ namespace LUS { s32 sampleRate; // For wav samples only... } Sample; // size = 0x10 - class AudioSample : public Resource { + class AudioSample : public LUS::Resource { public: using Resource::Resource; - AudioSample() : Resource(std::shared_ptr()) {} + AudioSample() : Resource(std::shared_ptr()) {} Sample* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/AudioSequence.cpp b/soh/soh/resource/type/AudioSequence.cpp index c09514a67..41029d47d 100644 --- a/soh/soh/resource/type/AudioSequence.cpp +++ b/soh/soh/resource/type/AudioSequence.cpp @@ -1,6 +1,6 @@ #include "AudioSequence.h" -namespace LUS { +namespace SOH { Sequence* AudioSequence::GetPointer() { return &sequence; @@ -9,4 +9,4 @@ Sequence* AudioSequence::GetPointer() { size_t AudioSequence::GetPointerSize() { return sizeof(Sequence); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/AudioSequence.h b/soh/soh/resource/type/AudioSequence.h index 2b2bb8be9..457db6243 100644 --- a/soh/soh/resource/type/AudioSequence.h +++ b/soh/soh/resource/type/AudioSequence.h @@ -5,7 +5,7 @@ #include "Resource.h" #include -namespace LUS { +namespace SOH { typedef struct { char* seqData; @@ -17,11 +17,11 @@ typedef struct { uint8_t fonts[16]; } Sequence; -class AudioSequence : public Resource { +class AudioSequence : public LUS::Resource { public: using Resource::Resource; - AudioSequence() : Resource(std::shared_ptr()) {} + AudioSequence() : Resource(std::shared_ptr()) {} Sequence* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/AudioSoundFont.cpp b/soh/soh/resource/type/AudioSoundFont.cpp index 43ac40abf..12218cb64 100644 --- a/soh/soh/resource/type/AudioSoundFont.cpp +++ b/soh/soh/resource/type/AudioSoundFont.cpp @@ -1,6 +1,6 @@ #include "AudioSoundFont.h" -namespace LUS { +namespace SOH { SoundFont* AudioSoundFont::GetPointer() { return &soundFont; } @@ -8,4 +8,4 @@ SoundFont* AudioSoundFont::GetPointer() { size_t AudioSoundFont::GetPointerSize() { return sizeof(SoundFont); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/AudioSoundFont.h b/soh/soh/resource/type/AudioSoundFont.h index c47218090..11b899d3e 100644 --- a/soh/soh/resource/type/AudioSoundFont.h +++ b/soh/soh/resource/type/AudioSoundFont.h @@ -6,7 +6,7 @@ #include "soh/resource/type/AudioSample.h" #include -namespace LUS { +namespace SOH { typedef struct { /* 0x0 */ s16 delay; @@ -52,11 +52,11 @@ typedef struct { s32 fntIndex; } SoundFont; // size = 0x14 -class AudioSoundFont : public Resource { +class AudioSoundFont : public LUS::Resource { public: using Resource::Resource; - AudioSoundFont() : Resource(std::shared_ptr()) {} + AudioSoundFont() : Resource(std::shared_ptr()) {} SoundFont* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Background.cpp b/soh/soh/resource/type/Background.cpp index bc1047b5c..5465b1ad9 100644 --- a/soh/soh/resource/type/Background.cpp +++ b/soh/soh/resource/type/Background.cpp @@ -1,6 +1,6 @@ #include "Background.h" -namespace LUS { +namespace SOH { uint8_t* Background::GetPointer() { return Data.data(); } @@ -8,4 +8,4 @@ uint8_t* Background::GetPointer() { size_t Background::GetPointerSize() { return Data.size() * sizeof(uint8_t); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Background.h b/soh/soh/resource/type/Background.h index 7f22658e0..9edc4b0d6 100644 --- a/soh/soh/resource/type/Background.h +++ b/soh/soh/resource/type/Background.h @@ -2,12 +2,12 @@ #include "resource/Resource.h" -namespace LUS { -class Background : public Resource { +namespace SOH { +class Background : public LUS::Resource { public: using Resource::Resource; - Background() : Resource(std::shared_ptr()) {} + Background() : Resource(std::shared_ptr()) {} uint8_t* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/CollisionHeader.cpp b/soh/soh/resource/type/CollisionHeader.cpp index 5625d2b59..dbfd737ee 100644 --- a/soh/soh/resource/type/CollisionHeader.cpp +++ b/soh/soh/resource/type/CollisionHeader.cpp @@ -1,6 +1,6 @@ #include "CollisionHeader.h" -namespace LUS { +namespace SOH { CollisionHeaderData* CollisionHeader::GetPointer() { return &collisionHeaderData; } @@ -8,4 +8,4 @@ CollisionHeaderData* CollisionHeader::GetPointer() { size_t CollisionHeader::GetPointerSize() { return sizeof(collisionHeaderData); } -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/CollisionHeader.h b/soh/soh/resource/type/CollisionHeader.h index e401aa7f5..e2ddf3f7a 100644 --- a/soh/soh/resource/type/CollisionHeader.h +++ b/soh/soh/resource/type/CollisionHeader.h @@ -6,7 +6,7 @@ #include #include "z64math.h" -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ u16 type; @@ -67,11 +67,11 @@ typedef struct { size_t cameraDataListLen; // OTRTODO: Added to allow for bounds checking the cameraDataList. } CollisionHeaderData; // original name: BGDataInfo -class CollisionHeader : public Resource { +class CollisionHeader : public LUS::Resource { public: using Resource::Resource; - CollisionHeader() : Resource(std::shared_ptr()) {} + CollisionHeader() : Resource(std::shared_ptr()) {} CollisionHeaderData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Cutscene.cpp b/soh/soh/resource/type/Cutscene.cpp index c7e98062a..60440ceb2 100644 --- a/soh/soh/resource/type/Cutscene.cpp +++ b/soh/soh/resource/type/Cutscene.cpp @@ -1,7 +1,7 @@ #include "Cutscene.h" #include -namespace LUS { +namespace SOH { uint32_t* Cutscene::GetPointer() { return commands.data(); } @@ -9,4 +9,4 @@ uint32_t* Cutscene::GetPointer() { size_t Cutscene::GetPointerSize() { return commands.size() * sizeof(uint32_t); } -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/Cutscene.h b/soh/soh/resource/type/Cutscene.h index 5bd268e61..3ca8b3d50 100644 --- a/soh/soh/resource/type/Cutscene.h +++ b/soh/soh/resource/type/Cutscene.h @@ -7,7 +7,7 @@ #include "Vec3f.h" #include "Color3b.h" -namespace LUS { +namespace SOH { enum class CutsceneCommands { Cmd00 = 0x0000, @@ -44,11 +44,11 @@ enum class CutsceneCommands { Error = 0xFEAF, }; -class Cutscene : public Resource { +class Cutscene : public LUS::Resource { public: using Resource::Resource; - Cutscene() : Resource(std::shared_ptr()) {} + Cutscene() : Resource(std::shared_ptr()) {} uint32_t* GetPointer(); size_t GetPointerSize(); @@ -57,7 +57,7 @@ class Cutscene : public Resource { uint32_t endFrame; std::vector commands; }; -} // namespace LUS +} // namespace SOH ///////////// diff --git a/soh/soh/resource/type/Path.cpp b/soh/soh/resource/type/Path.cpp index 535db4e7d..072c65fd0 100644 --- a/soh/soh/resource/type/Path.cpp +++ b/soh/soh/resource/type/Path.cpp @@ -1,6 +1,6 @@ #include "Path.h" -namespace LUS { +namespace SOH { PathData* Path::GetPointer() { return pathData.data(); } @@ -8,4 +8,4 @@ PathData* Path::GetPointer() { size_t Path::GetPointerSize() { return pathData.size() * sizeof(PathData); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Path.h b/soh/soh/resource/type/Path.h index 5dd16dec9..c4078bed3 100644 --- a/soh/soh/resource/type/Path.h +++ b/soh/soh/resource/type/Path.h @@ -6,18 +6,18 @@ #include #include "z64math.h" -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ u8 count; // number of points in the path /* 0x04 */ Vec3s* points; // Segment Address to the array of points } PathData; // size = 0x8 -class Path : public Resource { +class Path : public LUS::Resource { public: using Resource::Resource; - Path() : Resource(std::shared_ptr()) {} + Path() : Resource(std::shared_ptr()) {} PathData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/PlayerAnimation.cpp b/soh/soh/resource/type/PlayerAnimation.cpp index 55925f49c..189460e4d 100644 --- a/soh/soh/resource/type/PlayerAnimation.cpp +++ b/soh/soh/resource/type/PlayerAnimation.cpp @@ -1,7 +1,7 @@ #include "PlayerAnimation.h" #include -namespace LUS { +namespace SOH { int16_t* PlayerAnimation::GetPointer() { return limbRotData.data(); } @@ -9,4 +9,4 @@ int16_t* PlayerAnimation::GetPointer() { size_t PlayerAnimation::GetPointerSize() { return limbRotData.size() * sizeof(int16_t); } -} // namespace LUS \ No newline at end of file +} // namespace SOH diff --git a/soh/soh/resource/type/PlayerAnimation.h b/soh/soh/resource/type/PlayerAnimation.h index 4eb51b139..d8c47a5f6 100644 --- a/soh/soh/resource/type/PlayerAnimation.h +++ b/soh/soh/resource/type/PlayerAnimation.h @@ -7,17 +7,16 @@ #include "Vec3f.h" #include "Color3b.h" -namespace LUS { - -class PlayerAnimation : public Resource { +namespace SOH { +class PlayerAnimation : public LUS::Resource { public: using Resource::Resource; - PlayerAnimation() : Resource(std::shared_ptr()) {} + PlayerAnimation() : Resource(std::shared_ptr()) {} int16_t* GetPointer(); size_t GetPointerSize(); std::vector limbRotData; }; -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/Scene.cpp b/soh/soh/resource/type/Scene.cpp index bfe219e54..15829c40e 100644 --- a/soh/soh/resource/type/Scene.cpp +++ b/soh/soh/resource/type/Scene.cpp @@ -1,6 +1,6 @@ #include "Scene.h" -namespace LUS { +namespace SOH { void* Scene::GetPointer() { // Scene is a special type that requries C++ processing. As such, we return nothing. return nullptr; @@ -9,4 +9,4 @@ void* Scene::GetPointer() { size_t Scene::GetPointerSize() { return 0; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Scene.h b/soh/soh/resource/type/Scene.h index f726da359..79ff69392 100644 --- a/soh/soh/resource/type/Scene.h +++ b/soh/soh/resource/type/Scene.h @@ -7,13 +7,13 @@ #include "scenecommand/SceneCommand.h" #include -namespace LUS { +namespace SOH { -class Scene : public Resource { +class Scene : public LUS::Resource { public: using Resource::Resource; - Scene() : Resource(std::shared_ptr()) {} + Scene() : Resource(std::shared_ptr()) {} void* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 13798d3c5..39c28f533 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -3,7 +3,7 @@ #include "soh/OTRGlobals.h" #include "libultraship/libultraship.h" -namespace LUS { +namespace SOH { SkeletonData* Skeleton::GetPointer() { return &skeletonData; } @@ -79,4 +79,4 @@ void SkeletonPatcher::UpdateSkeletons() { } } } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Skeleton.h b/soh/soh/resource/type/Skeleton.h index 490614a44..81aa90c68 100644 --- a/soh/soh/resource/type/Skeleton.h +++ b/soh/soh/resource/type/Skeleton.h @@ -5,7 +5,7 @@ #include "SkeletonLimb.h" #include -namespace LUS { +namespace SOH { enum class SkeletonType { Normal, @@ -50,11 +50,11 @@ union SkeletonData { SkelCurveLimbList skelCurveLimbList; }; -class Skeleton : public Resource { +class Skeleton : public LUS::Resource { public: using Resource::Resource; - Skeleton() : Resource(std::shared_ptr()) {} + Skeleton() : Resource(std::shared_ptr()) {} SkeletonData* GetPointer(); size_t GetPointerSize(); @@ -91,4 +91,4 @@ class SkeletonPatcher { }; -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/SkeletonLimb.cpp b/soh/soh/resource/type/SkeletonLimb.cpp index 8e5a8ef6d..eb599e641 100644 --- a/soh/soh/resource/type/SkeletonLimb.cpp +++ b/soh/soh/resource/type/SkeletonLimb.cpp @@ -1,6 +1,6 @@ #include "SkeletonLimb.h" -namespace LUS { +namespace SOH { SkeletonLimbData* SkeletonLimb::GetPointer() { return &limbData; } @@ -21,4 +21,4 @@ size_t SkeletonLimb::GetPointerSize() { return 0; } } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/SkeletonLimb.h b/soh/soh/resource/type/SkeletonLimb.h index 2110b3484..bae04092c 100644 --- a/soh/soh/resource/type/SkeletonLimb.h +++ b/soh/soh/resource/type/SkeletonLimb.h @@ -4,7 +4,7 @@ #include "libultraship/libultra.h" #include "z64math.h" -namespace LUS { +namespace SOH { enum class LimbType { Invalid, Standard, @@ -97,11 +97,11 @@ union SkeletonLimbData { SkinLimb skinLimb; }; -class SkeletonLimb : public Resource { +class SkeletonLimb : public LUS::Resource { public: using Resource::Resource; - SkeletonLimb() : Resource(std::shared_ptr()) {} + SkeletonLimb() : Resource(std::shared_ptr()) {} SkeletonLimbData* GetPointer(); size_t GetPointerSize(); @@ -131,4 +131,4 @@ public: std::vector> skinLimbModifVertexArrays; std::vector> skinLimbModifTransformationArrays; }; -} // namespace LUS \ No newline at end of file +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h new file mode 100644 index 000000000..fdf39031e --- /dev/null +++ b/soh/soh/resource/type/SohResourceType.h @@ -0,0 +1,21 @@ +#pragma once + +namespace SOH { +enum class ResourceType { + SOH_Animation = 0x4F414E4D, // OANM + SOH_PlayerAnimation = 0x4F50414D, // OPAM + SOH_Room = 0x4F524F4D, // OROM + SOH_CollisionHeader = 0x4F434F4C, // OCOL + SOH_Skeleton = 0x4F534B4C, // OSKL + SOH_SkeletonLimb = 0x4F534C42, // OSLB + SOH_Path = 0x4F505448, // OPTH + SOH_Cutscene = 0x4F435654, // OCUT + SOH_Text = 0x4F545854, // OTXT + SOH_Audio = 0x4F415544, // OAUD + SOH_AudioSample = 0x4F534D50, // OSMP + SOH_AudioSoundFont = 0x4F534654, // OSFT + SOH_AudioSequence = 0x4F534551, // OSEQ + SOH_Background = 0x4F424749, // OBGI + SOH_SceneCommand = 0x4F52434D, // ORCM +}; +} // namespace SOH diff --git a/soh/soh/resource/type/Text.cpp b/soh/soh/resource/type/Text.cpp index eee289f8a..4678dbbad 100644 --- a/soh/soh/resource/type/Text.cpp +++ b/soh/soh/resource/type/Text.cpp @@ -1,6 +1,6 @@ #include "Text.h" -namespace LUS { +namespace SOH { MessageEntry* Text::GetPointer() { return messages.data(); } @@ -8,4 +8,4 @@ MessageEntry* Text::GetPointer() { size_t Text::GetPointerSize() { return messages.size() * sizeof(MessageEntry); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/Text.h b/soh/soh/resource/type/Text.h index db0cb36a0..03cf7340b 100644 --- a/soh/soh/resource/type/Text.h +++ b/soh/soh/resource/type/Text.h @@ -5,7 +5,7 @@ #include "Resource.h" #include -namespace LUS { +namespace SOH { // TODO: we've moved away from using classes for this stuff class MessageEntry { @@ -16,11 +16,11 @@ public: std::string msg; }; -class Text : public Resource { +class Text : public LUS::Resource { public: using Resource::Resource; - Text() : Resource(std::shared_ptr()) {} + Text() : Resource(std::shared_ptr()) {} MessageEntry* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/scenecommand/EndMarker.cpp b/soh/soh/resource/type/scenecommand/EndMarker.cpp index 9d12c1518..ba8898187 100644 --- a/soh/soh/resource/type/scenecommand/EndMarker.cpp +++ b/soh/soh/resource/type/scenecommand/EndMarker.cpp @@ -1,6 +1,6 @@ #include "EndMarker.h" -namespace LUS { +namespace SOH { Marker* EndMarker::GetPointer() { return &endMarker; } @@ -8,4 +8,4 @@ Marker* EndMarker::GetPointer() { size_t EndMarker::GetPointerSize() { return sizeof(Marker); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/EndMarker.h b/soh/soh/resource/type/scenecommand/EndMarker.h index 9f981f1f9..4f45051c2 100644 --- a/soh/soh/resource/type/scenecommand/EndMarker.h +++ b/soh/soh/resource/type/scenecommand/EndMarker.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { } Marker; diff --git a/soh/soh/resource/type/scenecommand/RomFile.h b/soh/soh/resource/type/scenecommand/RomFile.h index ebdc3dc3b..19a5545e7 100644 --- a/soh/soh/resource/type/scenecommand/RomFile.h +++ b/soh/soh/resource/type/scenecommand/RomFile.h @@ -2,7 +2,7 @@ #include -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ uintptr_t vromStart; /* 0x04 */ uintptr_t vromEnd; diff --git a/soh/soh/resource/type/scenecommand/SceneCommand.h b/soh/soh/resource/type/scenecommand/SceneCommand.h index 6fb845568..5eb44ae9d 100644 --- a/soh/soh/resource/type/scenecommand/SceneCommand.h +++ b/soh/soh/resource/type/scenecommand/SceneCommand.h @@ -6,7 +6,7 @@ #include "Resource.h" #include -namespace LUS { +namespace SOH { enum class SceneCommandID : uint8_t { SetStartPositionList = 0x00, @@ -47,10 +47,10 @@ enum class SceneCommandID : uint8_t { Error = 0xFF }; -class ISceneCommand : public IResource { +class ISceneCommand : public LUS::IResource { public: using IResource::IResource; - ISceneCommand() : IResource(std::shared_ptr()) {} + ISceneCommand() : IResource(std::shared_ptr()) {} SceneCommandID cmdId; }; diff --git a/soh/soh/resource/type/scenecommand/SetActorList.cpp b/soh/soh/resource/type/scenecommand/SetActorList.cpp index d37ebb148..5bb62e764 100644 --- a/soh/soh/resource/type/scenecommand/SetActorList.cpp +++ b/soh/soh/resource/type/scenecommand/SetActorList.cpp @@ -1,6 +1,6 @@ #include "SetActorList.h" -namespace LUS { +namespace SOH { ActorEntry* SetActorList::GetPointer() { return actorList.data(); } @@ -8,4 +8,4 @@ ActorEntry* SetActorList::GetPointer() { size_t SetActorList::GetPointerSize() { return actorList.size() * sizeof(ActorEntry); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetActorList.h b/soh/soh/resource/type/scenecommand/SetActorList.h index 117175d7d..0eb53c585 100644 --- a/soh/soh/resource/type/scenecommand/SetActorList.h +++ b/soh/soh/resource/type/scenecommand/SetActorList.h @@ -9,7 +9,7 @@ // #include #include "z64math.h" -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ s16 id; /* 0x02 */ Vec3s pos; diff --git a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.cpp b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.cpp index 15b3c97d4..911fef455 100644 --- a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.cpp +++ b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.cpp @@ -1,6 +1,6 @@ #include "SetAlternateHeaders.h" -namespace LUS { +namespace SOH { void* SetAlternateHeaders::GetPointer() { // Like Scene, SetAlternateHeader is a special type that is only acted upon in C++. return nullptr; @@ -9,4 +9,4 @@ void* SetAlternateHeaders::GetPointer() { size_t SetAlternateHeaders::GetPointerSize() { return 0; } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h index dc7272369..fdddee3f8 100644 --- a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h +++ b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h @@ -11,7 +11,7 @@ #include -namespace LUS { +namespace SOH { class SetAlternateHeaders : public SceneCommand { public: diff --git a/soh/soh/resource/type/scenecommand/SetCameraSettings.cpp b/soh/soh/resource/type/scenecommand/SetCameraSettings.cpp index e1d2967e7..5c41f1c8f 100644 --- a/soh/soh/resource/type/scenecommand/SetCameraSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetCameraSettings.cpp @@ -1,6 +1,6 @@ #include "SetCameraSettings.h" -namespace LUS { +namespace SOH { CameraSettings* SetCameraSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ CameraSettings* SetCameraSettings::GetPointer() { size_t SetCameraSettings::GetPointerSize() { return sizeof(CameraSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetCameraSettings.h b/soh/soh/resource/type/scenecommand/SetCameraSettings.h index adbde2e02..1d8062f9a 100644 --- a/soh/soh/resource/type/scenecommand/SetCameraSettings.h +++ b/soh/soh/resource/type/scenecommand/SetCameraSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { int8_t cameraMovement; int32_t worldMapArea; diff --git a/soh/soh/resource/type/scenecommand/SetCollisionHeader.cpp b/soh/soh/resource/type/scenecommand/SetCollisionHeader.cpp index db8cdcb32..a1c22b9ea 100644 --- a/soh/soh/resource/type/scenecommand/SetCollisionHeader.cpp +++ b/soh/soh/resource/type/scenecommand/SetCollisionHeader.cpp @@ -1,6 +1,6 @@ #include "SetCollisionHeader.h" -namespace LUS { +namespace SOH { CollisionHeaderData* SetCollisionHeader::GetPointer() { if (collisionHeader == nullptr) { return nullptr; @@ -14,4 +14,4 @@ size_t SetCollisionHeader::GetPointerSize() { } return collisionHeader->GetPointerSize(); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetCollisionHeader.h b/soh/soh/resource/type/scenecommand/SetCollisionHeader.h index 79573fe74..e2f63d089 100644 --- a/soh/soh/resource/type/scenecommand/SetCollisionHeader.h +++ b/soh/soh/resource/type/scenecommand/SetCollisionHeader.h @@ -9,7 +9,7 @@ #include "soh/resource/type/CollisionHeader.h" // #include -namespace LUS { +namespace SOH { class SetCollisionHeader : public SceneCommand { public: using SceneCommand::SceneCommand; diff --git a/soh/soh/resource/type/scenecommand/SetCsCamera.cpp b/soh/soh/resource/type/scenecommand/SetCsCamera.cpp index d3eafb803..762ee1e65 100644 --- a/soh/soh/resource/type/scenecommand/SetCsCamera.cpp +++ b/soh/soh/resource/type/scenecommand/SetCsCamera.cpp @@ -1,6 +1,6 @@ #include "SetCsCamera.h" -namespace LUS { +namespace SOH { CsCamera* SetCsCamera::GetPointer() { return &csCamera; } @@ -8,4 +8,4 @@ CsCamera* SetCsCamera::GetPointer() { size_t SetCsCamera::GetPointerSize() { return sizeof(CsCamera); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetCsCamera.h b/soh/soh/resource/type/scenecommand/SetCsCamera.h index db0e3d682..c44d9f935 100644 --- a/soh/soh/resource/type/scenecommand/SetCsCamera.h +++ b/soh/soh/resource/type/scenecommand/SetCsCamera.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { } CsCamera; diff --git a/soh/soh/resource/type/scenecommand/SetCutscenes.cpp b/soh/soh/resource/type/scenecommand/SetCutscenes.cpp index 42d1326d5..6643eda47 100644 --- a/soh/soh/resource/type/scenecommand/SetCutscenes.cpp +++ b/soh/soh/resource/type/scenecommand/SetCutscenes.cpp @@ -1,6 +1,6 @@ #include "SetCutscenes.h" -namespace LUS { +namespace SOH { uint32_t* SetCutscenes::GetPointer() { if (cutscene == nullptr) { return nullptr; @@ -14,4 +14,4 @@ size_t SetCutscenes::GetPointerSize() { } return cutscene->GetPointerSize(); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetCutscenes.h b/soh/soh/resource/type/scenecommand/SetCutscenes.h index 482553934..be74770c0 100644 --- a/soh/soh/resource/type/scenecommand/SetCutscenes.h +++ b/soh/soh/resource/type/scenecommand/SetCutscenes.h @@ -9,7 +9,7 @@ #include "soh/resource/type/Cutscene.h" // #include -namespace LUS { +namespace SOH { class SetCutscenes : public SceneCommand { public: using SceneCommand::SceneCommand; diff --git a/soh/soh/resource/type/scenecommand/SetEchoSettings.cpp b/soh/soh/resource/type/scenecommand/SetEchoSettings.cpp index 47cfa85ad..d4b2b1e15 100644 --- a/soh/soh/resource/type/scenecommand/SetEchoSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetEchoSettings.cpp @@ -1,6 +1,6 @@ #include "SetEchoSettings.h" -namespace LUS { +namespace SOH { EchoSettings* SetEchoSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ EchoSettings* SetEchoSettings::GetPointer() { size_t SetEchoSettings::GetPointerSize() { return sizeof(EchoSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetEchoSettings.h b/soh/soh/resource/type/scenecommand/SetEchoSettings.h index ea2f664d4..30f54d1b3 100644 --- a/soh/soh/resource/type/scenecommand/SetEchoSettings.h +++ b/soh/soh/resource/type/scenecommand/SetEchoSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { int8_t echo; } EchoSettings; diff --git a/soh/soh/resource/type/scenecommand/SetEntranceList.cpp b/soh/soh/resource/type/scenecommand/SetEntranceList.cpp index d33ac189b..e82711da2 100644 --- a/soh/soh/resource/type/scenecommand/SetEntranceList.cpp +++ b/soh/soh/resource/type/scenecommand/SetEntranceList.cpp @@ -1,6 +1,6 @@ #include "SetEntranceList.h" -namespace LUS { +namespace SOH { EntranceEntry* SetEntranceList::GetPointer() { return entrances.data(); } @@ -8,4 +8,4 @@ EntranceEntry* SetEntranceList::GetPointer() { size_t SetEntranceList::GetPointerSize() { return entrances.size() * sizeof(EntranceEntry); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetEntranceList.h b/soh/soh/resource/type/scenecommand/SetEntranceList.h index d31dda78c..7c41b4b04 100644 --- a/soh/soh/resource/type/scenecommand/SetEntranceList.h +++ b/soh/soh/resource/type/scenecommand/SetEntranceList.h @@ -8,7 +8,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ u8 spawn; /* 0x01 */ u8 room; diff --git a/soh/soh/resource/type/scenecommand/SetExitList.cpp b/soh/soh/resource/type/scenecommand/SetExitList.cpp index 99966cdb4..3de483b0e 100644 --- a/soh/soh/resource/type/scenecommand/SetExitList.cpp +++ b/soh/soh/resource/type/scenecommand/SetExitList.cpp @@ -1,6 +1,6 @@ #include "SetExitList.h" -namespace LUS { +namespace SOH { uint16_t* SetExitList::GetPointer() { return exits.data(); } @@ -8,4 +8,4 @@ uint16_t* SetExitList::GetPointer() { size_t SetExitList::GetPointerSize() { return exits.size() * sizeof(int16_t); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetExitList.h b/soh/soh/resource/type/scenecommand/SetExitList.h index c6f0b3f42..f97f11d1e 100644 --- a/soh/soh/resource/type/scenecommand/SetExitList.h +++ b/soh/soh/resource/type/scenecommand/SetExitList.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { class SetExitList : public SceneCommand { public: using SceneCommand::SceneCommand; diff --git a/soh/soh/resource/type/scenecommand/SetLightList.cpp b/soh/soh/resource/type/scenecommand/SetLightList.cpp index c59f75c20..459e957cb 100644 --- a/soh/soh/resource/type/scenecommand/SetLightList.cpp +++ b/soh/soh/resource/type/scenecommand/SetLightList.cpp @@ -1,6 +1,6 @@ #include "SetLightList.h" -namespace LUS { +namespace SOH { LightInfo* SetLightList::GetPointer() { return lightList.data(); } @@ -8,4 +8,4 @@ LightInfo* SetLightList::GetPointer() { size_t SetLightList::GetPointerSize() { return lightList.size() * sizeof(LightInfo); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetLightList.h b/soh/soh/resource/type/scenecommand/SetLightList.h index bbc5aad3d..c3ede1f16 100644 --- a/soh/soh/resource/type/scenecommand/SetLightList.h +++ b/soh/soh/resource/type/scenecommand/SetLightList.h @@ -8,7 +8,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { /* 0x0 */ s16 x; /* 0x2 */ s16 y; diff --git a/soh/soh/resource/type/scenecommand/SetLightingSettings.cpp b/soh/soh/resource/type/scenecommand/SetLightingSettings.cpp index 69127f19c..042062512 100644 --- a/soh/soh/resource/type/scenecommand/SetLightingSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetLightingSettings.cpp @@ -1,6 +1,6 @@ #include "SetLightingSettings.h" -namespace LUS { +namespace SOH { EnvLightSettings* SetLightingSettings::GetPointer() { return settings.data(); } @@ -8,4 +8,4 @@ EnvLightSettings* SetLightingSettings::GetPointer() { size_t SetLightingSettings::GetPointerSize() { return settings.size() * sizeof(EnvLightSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetLightingSettings.h b/soh/soh/resource/type/scenecommand/SetLightingSettings.h index ca894fec3..b8f08d834 100644 --- a/soh/soh/resource/type/scenecommand/SetLightingSettings.h +++ b/soh/soh/resource/type/scenecommand/SetLightingSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ u8 ambientColor[3]; /* 0x03 */ s8 light1Dir[3]; diff --git a/soh/soh/resource/type/scenecommand/SetMesh.cpp b/soh/soh/resource/type/scenecommand/SetMesh.cpp index 5ecd2cbfa..1e2cd396c 100644 --- a/soh/soh/resource/type/scenecommand/SetMesh.cpp +++ b/soh/soh/resource/type/scenecommand/SetMesh.cpp @@ -1,6 +1,6 @@ #include "SetMesh.h" -namespace LUS { +namespace SOH { MeshHeader* SetMesh::GetPointer() { return &meshHeader; } @@ -8,4 +8,4 @@ MeshHeader* SetMesh::GetPointer() { size_t SetMesh::GetPointerSize() { return sizeof(MeshHeader); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetMesh.h b/soh/soh/resource/type/scenecommand/SetMesh.h index a3a6c9731..33ab24202 100644 --- a/soh/soh/resource/type/scenecommand/SetMesh.h +++ b/soh/soh/resource/type/scenecommand/SetMesh.h @@ -8,7 +8,7 @@ #include "libultraship/libultra.h" #include "z64math.h" -namespace LUS { +namespace SOH { typedef struct { /* 0x00 */ u8 type; } PolygonBase; diff --git a/soh/soh/resource/type/scenecommand/SetObjectList.cpp b/soh/soh/resource/type/scenecommand/SetObjectList.cpp index 921166675..04aeb27d0 100644 --- a/soh/soh/resource/type/scenecommand/SetObjectList.cpp +++ b/soh/soh/resource/type/scenecommand/SetObjectList.cpp @@ -1,6 +1,6 @@ #include "SetObjectList.h" -namespace LUS { +namespace SOH { int16_t* SetObjectList::GetPointer() { return objects.data(); } @@ -8,4 +8,4 @@ int16_t* SetObjectList::GetPointer() { size_t SetObjectList::GetPointerSize() { return objects.size() * sizeof(int16_t); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetObjectList.h b/soh/soh/resource/type/scenecommand/SetObjectList.h index c6f786636..e843d4db0 100644 --- a/soh/soh/resource/type/scenecommand/SetObjectList.h +++ b/soh/soh/resource/type/scenecommand/SetObjectList.h @@ -8,7 +8,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { class SetObjectList : public SceneCommand { public: using SceneCommand::SceneCommand; diff --git a/soh/soh/resource/type/scenecommand/SetPathways.cpp b/soh/soh/resource/type/scenecommand/SetPathways.cpp index b69108ea6..fe1d7c5d8 100644 --- a/soh/soh/resource/type/scenecommand/SetPathways.cpp +++ b/soh/soh/resource/type/scenecommand/SetPathways.cpp @@ -1,6 +1,6 @@ #include "SetPathways.h" -namespace LUS { +namespace SOH { PathData** SetPathways::GetPointer() { return paths.data(); } @@ -8,4 +8,4 @@ PathData** SetPathways::GetPointer() { size_t SetPathways::GetPointerSize() { return paths.size() * sizeof(PathData*); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetPathways.h b/soh/soh/resource/type/scenecommand/SetPathways.h index 5846c382f..cf875cf5e 100644 --- a/soh/soh/resource/type/scenecommand/SetPathways.h +++ b/soh/soh/resource/type/scenecommand/SetPathways.h @@ -8,7 +8,7 @@ // #include #include "soh/resource/type/Path.h" -namespace LUS { +namespace SOH { class SetPathways : public SceneCommand { public: diff --git a/soh/soh/resource/type/scenecommand/SetRoomBehavior.cpp b/soh/soh/resource/type/scenecommand/SetRoomBehavior.cpp index deababc87..11bb4e95f 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomBehavior.cpp +++ b/soh/soh/resource/type/scenecommand/SetRoomBehavior.cpp @@ -1,6 +1,6 @@ #include "SetRoomBehavior.h" -namespace LUS { +namespace SOH { RoomBehavior* SetRoomBehavior::GetPointer() { return &roomBehavior; } @@ -8,4 +8,4 @@ RoomBehavior* SetRoomBehavior::GetPointer() { size_t SetRoomBehavior::GetPointerSize() { return sizeof(RoomBehavior); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetRoomBehavior.h b/soh/soh/resource/type/scenecommand/SetRoomBehavior.h index c2a28176e..c05e96a66 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomBehavior.h +++ b/soh/soh/resource/type/scenecommand/SetRoomBehavior.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { int8_t gameplayFlags; int32_t gameplayFlags2; diff --git a/soh/soh/resource/type/scenecommand/SetRoomList.cpp b/soh/soh/resource/type/scenecommand/SetRoomList.cpp index cf8c1d61a..c81d3645e 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomList.cpp +++ b/soh/soh/resource/type/scenecommand/SetRoomList.cpp @@ -1,6 +1,6 @@ #include "SetRoomList.h" -namespace LUS { +namespace SOH { RomFile* SetRoomList::GetPointer() { return rooms.data(); } @@ -8,4 +8,4 @@ RomFile* SetRoomList::GetPointer() { size_t SetRoomList::GetPointerSize() { return rooms.size() * sizeof(RomFile); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetRoomList.h b/soh/soh/resource/type/scenecommand/SetRoomList.h index 66d83dc9c..09ba46f22 100644 --- a/soh/soh/resource/type/scenecommand/SetRoomList.h +++ b/soh/soh/resource/type/scenecommand/SetRoomList.h @@ -10,7 +10,7 @@ #include -namespace LUS { +namespace SOH { // typedef struct { // /* 0x00 */ uintptr_t vromStart; // /* 0x04 */ uintptr_t vromEnd; diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.cpp b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.cpp index 9926ec01a..122d93d77 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.cpp +++ b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.cpp @@ -1,6 +1,6 @@ #include "SetSkyboxModifier.h" -namespace LUS { +namespace SOH { SkyboxModifier* SetSkyboxModifier::GetPointer() { return &modifier; } @@ -8,4 +8,4 @@ SkyboxModifier* SetSkyboxModifier::GetPointer() { size_t SetSkyboxModifier::GetPointerSize() { return sizeof(SkyboxModifier); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h index 6a54879e6..a60adfcaf 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h +++ b/soh/soh/resource/type/scenecommand/SetSkyboxModifier.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { uint8_t skyboxDisabled; uint8_t sunMoonDisabled; diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.cpp b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.cpp index 7f12d4fa3..527f0462c 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.cpp @@ -1,6 +1,6 @@ #include "SetSkyboxSettings.h" -namespace LUS { +namespace SOH { SkyboxSettings* SetSkyboxSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ SkyboxSettings* SetSkyboxSettings::GetPointer() { size_t SetSkyboxSettings::GetPointerSize() { return sizeof(SetSkyboxSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h index a2a9593b0..f256e103e 100644 --- a/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h +++ b/soh/soh/resource/type/scenecommand/SetSkyboxSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { uint8_t unk; uint8_t skyboxId; diff --git a/soh/soh/resource/type/scenecommand/SetSoundSettings.cpp b/soh/soh/resource/type/scenecommand/SetSoundSettings.cpp index f6f1941d1..c136d34db 100644 --- a/soh/soh/resource/type/scenecommand/SetSoundSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetSoundSettings.cpp @@ -1,6 +1,6 @@ #include "SetSoundSettings.h" -namespace LUS { +namespace SOH { SoundSettings* SetSoundSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ SoundSettings* SetSoundSettings::GetPointer() { size_t SetSoundSettings::GetPointerSize() { return sizeof(SoundSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetSoundSettings.h b/soh/soh/resource/type/scenecommand/SetSoundSettings.h index c4ee4668d..b72c2b74d 100644 --- a/soh/soh/resource/type/scenecommand/SetSoundSettings.h +++ b/soh/soh/resource/type/scenecommand/SetSoundSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { uint8_t seqId; uint8_t natureAmbienceId; diff --git a/soh/soh/resource/type/scenecommand/SetSpecialObjects.cpp b/soh/soh/resource/type/scenecommand/SetSpecialObjects.cpp index 3887107da..304ab514c 100644 --- a/soh/soh/resource/type/scenecommand/SetSpecialObjects.cpp +++ b/soh/soh/resource/type/scenecommand/SetSpecialObjects.cpp @@ -1,6 +1,6 @@ #include "SetSpecialObjects.h" -namespace LUS { +namespace SOH { SpecialObjects* SetSpecialObjects::GetPointer() { return &specialObjects; } @@ -8,4 +8,4 @@ SpecialObjects* SetSpecialObjects::GetPointer() { size_t SetSpecialObjects::GetPointerSize() { return sizeof(SpecialObjects); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetSpecialObjects.h b/soh/soh/resource/type/scenecommand/SetSpecialObjects.h index 78cfcd425..2a8906461 100644 --- a/soh/soh/resource/type/scenecommand/SetSpecialObjects.h +++ b/soh/soh/resource/type/scenecommand/SetSpecialObjects.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { int8_t elfMessage; int16_t globalObject; diff --git a/soh/soh/resource/type/scenecommand/SetStartPositionList.cpp b/soh/soh/resource/type/scenecommand/SetStartPositionList.cpp index 89fb40049..5fa17b2a0 100644 --- a/soh/soh/resource/type/scenecommand/SetStartPositionList.cpp +++ b/soh/soh/resource/type/scenecommand/SetStartPositionList.cpp @@ -1,6 +1,6 @@ #include "SetStartPositionList.h" -namespace LUS { +namespace SOH { ActorEntry* SetStartPositionList::GetPointer() { return startPositions.data(); } @@ -8,4 +8,4 @@ ActorEntry* SetStartPositionList::GetPointer() { size_t SetStartPositionList::GetPointerSize() { return startPositions.size() * sizeof(ActorEntry); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetStartPositionList.h b/soh/soh/resource/type/scenecommand/SetStartPositionList.h index 1c5d4242f..28d2d0d31 100644 --- a/soh/soh/resource/type/scenecommand/SetStartPositionList.h +++ b/soh/soh/resource/type/scenecommand/SetStartPositionList.h @@ -9,7 +9,7 @@ #include "soh/resource/type/scenecommand/SetActorList.h" // #include -namespace LUS { +namespace SOH { // typedef struct { // /* 0x00 */ s16 id; // /* 0x02 */ Vec3s pos; diff --git a/soh/soh/resource/type/scenecommand/SetTimeSettings.cpp b/soh/soh/resource/type/scenecommand/SetTimeSettings.cpp index 9a10fb022..c9380a0a0 100644 --- a/soh/soh/resource/type/scenecommand/SetTimeSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetTimeSettings.cpp @@ -1,6 +1,6 @@ #include "SetTimeSettings.h" -namespace LUS { +namespace SOH { TimeSettings* SetTimeSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ TimeSettings* SetTimeSettings::GetPointer() { size_t SetTimeSettings::GetPointerSize() { return sizeof(TimeSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetTimeSettings.h b/soh/soh/resource/type/scenecommand/SetTimeSettings.h index 637398652..cd47e33dc 100644 --- a/soh/soh/resource/type/scenecommand/SetTimeSettings.h +++ b/soh/soh/resource/type/scenecommand/SetTimeSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { uint8_t hour; uint8_t minute; diff --git a/soh/soh/resource/type/scenecommand/SetTransitionActorList.cpp b/soh/soh/resource/type/scenecommand/SetTransitionActorList.cpp index 86387e682..c944e99f2 100644 --- a/soh/soh/resource/type/scenecommand/SetTransitionActorList.cpp +++ b/soh/soh/resource/type/scenecommand/SetTransitionActorList.cpp @@ -1,6 +1,6 @@ #include "SetTransitionActorList.h" -namespace LUS { +namespace SOH { TransitionActorEntry* SetTransitionActorList::GetPointer() { return transitionActorList.data(); } @@ -8,4 +8,4 @@ TransitionActorEntry* SetTransitionActorList::GetPointer() { size_t SetTransitionActorList::GetPointerSize() { return transitionActorList.size() * sizeof(TransitionActorEntry); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetTransitionActorList.h b/soh/soh/resource/type/scenecommand/SetTransitionActorList.h index bb6fc2ac6..389526b0d 100644 --- a/soh/soh/resource/type/scenecommand/SetTransitionActorList.h +++ b/soh/soh/resource/type/scenecommand/SetTransitionActorList.h @@ -9,7 +9,7 @@ // #include #include "z64math.h" -namespace LUS { +namespace SOH { typedef struct { struct { s8 room; // Room to switch to diff --git a/soh/soh/resource/type/scenecommand/SetWindSettings.cpp b/soh/soh/resource/type/scenecommand/SetWindSettings.cpp index 3aa9ce7a6..64bc8ecc8 100644 --- a/soh/soh/resource/type/scenecommand/SetWindSettings.cpp +++ b/soh/soh/resource/type/scenecommand/SetWindSettings.cpp @@ -1,6 +1,6 @@ #include "SetWindSettings.h" -namespace LUS { +namespace SOH { WindSettings* SetWindSettings::GetPointer() { return &settings; } @@ -8,4 +8,4 @@ WindSettings* SetWindSettings::GetPointer() { size_t SetWindSettings::GetPointerSize() { return sizeof(WindSettings); } -} // namespace LUS +} // namespace SOH diff --git a/soh/soh/resource/type/scenecommand/SetWindSettings.h b/soh/soh/resource/type/scenecommand/SetWindSettings.h index e79b445ae..f3f9da968 100644 --- a/soh/soh/resource/type/scenecommand/SetWindSettings.h +++ b/soh/soh/resource/type/scenecommand/SetWindSettings.h @@ -7,7 +7,7 @@ #include "SceneCommand.h" #include -namespace LUS { +namespace SOH { typedef struct { int8_t windWest; int8_t windVertical; diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index ce594879a..05432fc53 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -15,7 +15,7 @@ extern "C" MessageTableEntry* sFraMessageEntryTablePtr; extern "C" MessageTableEntry* sStaffMessageEntryTablePtr; //extern "C" MessageTableEntry* _message_0xFFFC_nes; -static void SetMessageEntry(MessageTableEntry& entry, const LUS::MessageEntry& msgEntry) { +static void SetMessageEntry(MessageTableEntry& entry, const SOH::MessageEntry& msgEntry) { entry.textId = msgEntry.id; entry.typePos = (msgEntry.textboxType << 4) | msgEntry.textboxYPos; entry.segment = msgEntry.msg.c_str(); @@ -26,7 +26,7 @@ static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEnt auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(folderPath).get(); for (auto& tPath : lst) { - auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); + auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); for (size_t j = 0; j < file->messages.size(); ++j) { // Check if same text ID exists already @@ -43,7 +43,7 @@ static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEnt } MessageTableEntry* OTRMessage_LoadTable(const std::string& filePath, bool isNES) { - auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); + auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); if (file == nullptr) return nullptr; @@ -120,7 +120,7 @@ extern "C" void OTRMessage_Init() if (sStaffMessageEntryTablePtr == NULL) { auto file2 = - std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource( + std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource( "text/staff_message_data_static/staff_message_data_static")); // OTRTODO: Should not be malloc'ing here. It's fine for now since we check that the message table is already null. sStaffMessageEntryTablePtr = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file2->messages.size()); diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 828380ea7..522a24eb8 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -10,7 +10,7 @@ extern "C" void Play_InitScene(PlayState * play, s32 spawn); extern "C" void Play_InitEnvironment(PlayState * play, s16 skyboxId); void OTRPlay_InitScene(PlayState* play, s32 spawn); -s32 OTRScene_ExecuteCommands(PlayState* play, LUS::Scene* scene); +s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene); //LUS::OTRResource* OTRPlay_LoadFile(PlayState* play, RomFile* file) { LUS::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName) @@ -75,7 +75,7 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn) { func_80096FD4(play, &play->roomCtx.curRoom); YREG(15) = 0; gSaveContext.worldMapArea = 0; - OTRScene_ExecuteCommands(play, (LUS::Scene*)play->sceneSegment); + OTRScene_ExecuteCommands(play, (SOH::Scene*)play->sceneSegment); Play_InitEnvironment(play, play->skyboxId); // Unpause the timer for Boss Rush when the scene loaded isn't the Chamber of Sages. if (IS_BOSS_RUSH && play->sceneNum != SCENE_CHAMBER_OF_THE_SAGES) { diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 8bfb13308..9367fa8db 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -37,7 +37,7 @@ extern LUS::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName); extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); extern "C" RomFile sNaviMsgFiles[]; -s32 OTRScene_ExecuteCommands(PlayState* play, LUS::Scene* scene); +s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene); std::shared_ptr ResourceMgr_LoadFile(const char* path) { std::string Path = path; @@ -53,9 +53,9 @@ std::shared_ptr ResourceMgr_LoadFile(const char* path) { // Forward Declaration of function declared in OTRGlobals.cpp std::shared_ptr GetResourceByNameHandlingMQ(const char* path); -bool Scene_CommandSpawnList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetStartPositionList* cmdStartPos = std::static_pointer_cast(cmd); - LUS::SetStartPositionList* cmdStartPos = (LUS::SetStartPositionList*)cmd; +bool Scene_CommandSpawnList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetStartPositionList* cmdStartPos = std::static_pointer_cast(cmd); + SOH::SetStartPositionList* cmdStartPos = (SOH::SetStartPositionList*)cmd; ActorEntry* entries = (ActorEntry*)cmdStartPos->GetRawPointer(); play->linkActorEntry = &entries[play->setupEntranceList[play->curSpawn].spawn]; @@ -67,9 +67,9 @@ bool Scene_CommandSpawnList(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandActorList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetActorList* cmdActor = std::static_pointer_cast(cmd); - LUS::SetActorList* cmdActor = (LUS::SetActorList*)cmd; +bool Scene_CommandActorList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetActorList* cmdActor = std::static_pointer_cast(cmd); + SOH::SetActorList* cmdActor = (SOH::SetActorList*)cmd; play->numSetupActors = cmdActor->numActors; play->setupActorList = (ActorEntry*)cmdActor->GetRawPointer(); @@ -77,24 +77,24 @@ bool Scene_CommandActorList(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandUnused2(PlayState* play, LUS::ISceneCommand* cmd) { +bool Scene_CommandUnused2(PlayState* play, SOH::ISceneCommand* cmd) { // OTRTODO: Do we need to implement this? // play->unk_11DFC = SEGMENTED_TO_VIRTUAL(cmd->unused02.segment); return false; } -bool Scene_CommandCollisionHeader(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetCollisionHeader* cmdCol = std::static_pointer_cast(cmd); - LUS::SetCollisionHeader* cmdCol = (LUS::SetCollisionHeader*)cmd; +bool Scene_CommandCollisionHeader(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetCollisionHeader* cmdCol = std::static_pointer_cast(cmd); + SOH::SetCollisionHeader* cmdCol = (SOH::SetCollisionHeader*)cmd; BgCheck_Allocate(&play->colCtx, play, (CollisionHeader*)cmdCol->GetRawPointer()); return false; } -bool Scene_CommandRoomList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetRoomList* cmdRoomList = std::static_pointer_cast(cmd); - LUS::SetRoomList* cmdRoomList = (LUS::SetRoomList*)cmd; +bool Scene_CommandRoomList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetRoomList* cmdRoomList = std::static_pointer_cast(cmd); + SOH::SetRoomList* cmdRoomList = (SOH::SetRoomList*)cmd; play->numRooms = cmdRoomList->numRooms; play->roomList = (RomFile*)cmdRoomList->GetRawPointer(); @@ -102,17 +102,17 @@ bool Scene_CommandRoomList(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandEntranceList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetEntranceList* otrEntrance = std::static_pointer_cast(cmd); - LUS::SetEntranceList* otrEntrance = (LUS::SetEntranceList*)cmd; +bool Scene_CommandEntranceList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetEntranceList* otrEntrance = std::static_pointer_cast(cmd); + SOH::SetEntranceList* otrEntrance = (SOH::SetEntranceList*)cmd; play->setupEntranceList = (EntranceEntry*)otrEntrance->GetRawPointer(); return false; } -bool Scene_CommandSpecialFiles(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetSpecialObjects* specialCmd = std::static_pointer_cast(cmd); - LUS::SetSpecialObjects* specialCmd = (LUS::SetSpecialObjects*)cmd; +bool Scene_CommandSpecialFiles(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetSpecialObjects* specialCmd = std::static_pointer_cast(cmd); + SOH::SetSpecialObjects* specialCmd = (SOH::SetSpecialObjects*)cmd; if (specialCmd->specialObjects.globalObject != 0) { play->objectCtx.subKeepIndex = Object_Spawn(&play->objectCtx, specialCmd->specialObjects.globalObject); @@ -127,9 +127,9 @@ bool Scene_CommandSpecialFiles(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandRoomBehavior(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetRoomBehavior* cmdRoom = std::static_pointer_cast(cmd); - LUS::SetRoomBehavior* cmdRoom = (LUS::SetRoomBehavior*)cmd; +bool Scene_CommandRoomBehavior(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetRoomBehavior* cmdRoom = std::static_pointer_cast(cmd); + SOH::SetRoomBehavior* cmdRoom = (SOH::SetRoomBehavior*)cmd; play->roomCtx.curRoom.behaviorType1 = cmdRoom->roomBehavior.gameplayFlags; play->roomCtx.curRoom.behaviorType2 = cmdRoom->roomBehavior.gameplayFlags2 & 0xFF; @@ -139,9 +139,9 @@ bool Scene_CommandRoomBehavior(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandMeshHeader(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetMesh* otrMesh = static_pointer_cast(cmd); - LUS::SetMesh* otrMesh = (LUS::SetMesh*)cmd; +bool Scene_CommandMeshHeader(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetMesh* otrMesh = static_pointer_cast(cmd); + SOH::SetMesh* otrMesh = (SOH::SetMesh*)cmd; play->roomCtx.curRoom.meshHeader = (MeshHeader*)otrMesh->GetRawPointer(); return false; @@ -156,9 +156,9 @@ bool OTRfunc_800982FC(ObjectContext* objectCtx, s32 bankIndex, s16 objectId) { return false; } -bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetObjectList* cmdObj = static_pointer_cast(cmd); - LUS::SetObjectList* cmdObj = (LUS::SetObjectList*)cmd; +bool Scene_CommandObjectList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetObjectList* cmdObj = static_pointer_cast(cmd); + SOH::SetObjectList* cmdObj = (SOH::SetObjectList*)cmd; s32 i; s32 j; @@ -199,9 +199,9 @@ bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandLightList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetLightList* cmdLight = static_pointer_cast(cmd); - LUS::SetLightList* cmdLight = (LUS::SetLightList*)cmd; +bool Scene_CommandLightList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetLightList* cmdLight = static_pointer_cast(cmd); + SOH::SetLightList* cmdLight = (SOH::SetLightList*)cmd; for (size_t i = 0; i < cmdLight->lightList.size(); i++) { LightContext_InsertLight(play, &play->lightCtx, (LightInfo*)&cmdLight->lightList[i]); @@ -210,17 +210,17 @@ bool Scene_CommandLightList(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandPathList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetPathways* cmdPath = static_pointer_cast(cmd); - LUS::SetPathways* cmdPath = (LUS::SetPathways*)cmd; +bool Scene_CommandPathList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetPathways* cmdPath = static_pointer_cast(cmd); + SOH::SetPathways* cmdPath = (SOH::SetPathways*)cmd; play->setupPathList = (Path*)(cmdPath->GetPointer()[0]); return false; } -bool Scene_CommandTransitionActorList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetTransitionActorList* cmdActor = static_pointer_cast(cmd); - LUS::SetTransitionActorList* cmdActor = (LUS::SetTransitionActorList*)cmd; +bool Scene_CommandTransitionActorList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetTransitionActorList* cmdActor = static_pointer_cast(cmd); + SOH::SetTransitionActorList* cmdActor = (SOH::SetTransitionActorList*)cmd; play->transiActorCtx.numActors = cmdActor->numTransitionActors; play->transiActorCtx.list = (TransitionActorEntry*)cmdActor->GetRawPointer(); @@ -232,16 +232,16 @@ bool Scene_CommandTransitionActorList(PlayState* play, LUS::ISceneCommand* cmd) // transiActorCtx->numActors = 0; //} -bool Scene_CommandLightSettingsList(PlayState* play, LUS::ISceneCommand* cmd) { +bool Scene_CommandLightSettingsList(PlayState* play, SOH::ISceneCommand* cmd) { play->envCtx.lightSettingsList = (EnvLightSettings*)cmd->GetRawPointer(); return false; } // Scene Command 0x11: Skybox Settings -bool Scene_CommandSkyboxSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetSkyboxSettings* cmdSky = static_pointer_cast(cmd); - LUS::SetSkyboxSettings* cmdSky = (LUS::SetSkyboxSettings*)cmd; +bool Scene_CommandSkyboxSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetSkyboxSettings* cmdSky = static_pointer_cast(cmd); + SOH::SetSkyboxSettings* cmdSky = (SOH::SetSkyboxSettings*)cmd; play->skyboxId = cmdSky->settings.skyboxId; play->envCtx.unk_17 = play->envCtx.unk_18 = cmdSky->settings.weather; @@ -250,9 +250,9 @@ bool Scene_CommandSkyboxSettings(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandSkyboxDisables(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetSkyboxModifier* cmdSky = static_pointer_cast(cmd); - LUS::SetSkyboxModifier* cmdSky = (LUS::SetSkyboxModifier*)cmd; +bool Scene_CommandSkyboxDisables(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetSkyboxModifier* cmdSky = static_pointer_cast(cmd); + SOH::SetSkyboxModifier* cmdSky = (SOH::SetSkyboxModifier*)cmd; play->envCtx.sunMoonDisabled = cmdSky->modifier.sunMoonDisabled; play->envCtx.skyboxDisabled = cmdSky->modifier.skyboxDisabled; @@ -260,9 +260,9 @@ bool Scene_CommandSkyboxDisables(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandTimeSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetTimeSettings* cmdTime = static_pointer_cast(cmd); - LUS::SetTimeSettings* cmdTime = (LUS::SetTimeSettings*)cmd; +bool Scene_CommandTimeSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetTimeSettings* cmdTime = static_pointer_cast(cmd); + SOH::SetTimeSettings* cmdTime = (SOH::SetTimeSettings*)cmd; if ((cmdTime->settings.hour != 0xFF) && (cmdTime->settings.minute != 0xFF)) { gSaveContext.skyboxTime = gSaveContext.dayTime = @@ -300,9 +300,9 @@ bool Scene_CommandTimeSettings(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandWindSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetWind* cmdWind = std::static_pointer_cast(cmd); - LUS::SetWindSettings* cmdWind = (LUS::SetWindSettings*)cmd; +bool Scene_CommandWindSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetWind* cmdWind = std::static_pointer_cast(cmd); + SOH::SetWindSettings* cmdWind = (SOH::SetWindSettings*)cmd; play->envCtx.windDirection.x = cmdWind->settings.windWest; play->envCtx.windDirection.y = cmdWind->settings.windVertical; @@ -313,19 +313,19 @@ bool Scene_CommandWindSettings(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandExitList(PlayState* play, LUS::ISceneCommand* cmd) { +bool Scene_CommandExitList(PlayState* play, SOH::ISceneCommand* cmd) { play->setupExitList = (s16*)cmd->GetRawPointer(); return false; } -bool Scene_CommandUndefined9(PlayState* play, LUS::ISceneCommand* cmd) { +bool Scene_CommandUndefined9(PlayState* play, SOH::ISceneCommand* cmd) { return false; } -bool Scene_CommandSoundSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetSoundSettings* cmdSnd = static_pointer_cast(cmd); - LUS::SetSoundSettings* cmdSnd = (LUS::SetSoundSettings*)cmd; +bool Scene_CommandSoundSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetSoundSettings* cmdSnd = static_pointer_cast(cmd); + SOH::SetSoundSettings* cmdSnd = (SOH::SetSoundSettings*)cmd; play->sequenceCtx.seqId = cmdSnd->settings.seqId; play->sequenceCtx.natureAmbienceId = cmdSnd->settings.natureAmbienceId; @@ -337,18 +337,18 @@ bool Scene_CommandSoundSettings(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool Scene_CommandEchoSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetEchoSettings* cmdEcho = static_pointer_cast(cmd); - LUS::SetEchoSettings* cmdEcho = (LUS::SetEchoSettings*)cmd; +bool Scene_CommandEchoSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetEchoSettings* cmdEcho = static_pointer_cast(cmd); + SOH::SetEchoSettings* cmdEcho = (SOH::SetEchoSettings*)cmd; play->roomCtx.curRoom.echo = cmdEcho->settings.echo; return false; } -bool Scene_CommandAlternateHeaderList(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetAlternateHeaders* cmdHeaders = static_pointer_cast(cmd); - LUS::SetAlternateHeaders* cmdHeaders = (LUS::SetAlternateHeaders*)cmd; +bool Scene_CommandAlternateHeaderList(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetAlternateHeaders* cmdHeaders = static_pointer_cast(cmd); + SOH::SetAlternateHeaders* cmdHeaders = (SOH::SetAlternateHeaders*)cmd; // s32 pad; // SceneCmd* altHeader; @@ -358,8 +358,8 @@ bool Scene_CommandAlternateHeaderList(PlayState* play, LUS::ISceneCommand* cmd) // osSyncPrintf("\n[ZU]sceneset counter=[%X]", ((void)0, gSaveContext.sceneSetupIndex)); if (gSaveContext.sceneSetupIndex != 0) { - LUS::Scene* desiredHeader = - std::static_pointer_cast(cmdHeaders->headers[gSaveContext.sceneSetupIndex - 1]).get(); + SOH::Scene* desiredHeader = + std::static_pointer_cast(cmdHeaders->headers[gSaveContext.sceneSetupIndex - 1]).get(); if (desiredHeader != nullptr) { OTRScene_ExecuteCommands(play, desiredHeader); @@ -369,8 +369,8 @@ bool Scene_CommandAlternateHeaderList(PlayState* play, LUS::ISceneCommand* cmd) osSyncPrintf("\nげぼはっ! 指定されたデータがないでええっす!"); if (gSaveContext.sceneSetupIndex == 3) { - LUS::Scene* desiredHeader = - std::static_pointer_cast(cmdHeaders->headers[gSaveContext.sceneSetupIndex - 2]).get(); + SOH::Scene* desiredHeader = + std::static_pointer_cast(cmdHeaders->headers[gSaveContext.sceneSetupIndex - 2]).get(); // "Using adult day data there!" osSyncPrintf("\nそこで、大人の昼データを使用するでええっす!!"); @@ -385,9 +385,9 @@ bool Scene_CommandAlternateHeaderList(PlayState* play, LUS::ISceneCommand* cmd) return false; } -bool Scene_CommandCutsceneData(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetCutscenes* cmdCS = std::static_pointer_cast(cmd); - LUS::SetCutscenes* cmdCS = (LUS::SetCutscenes*)cmd; +bool Scene_CommandCutsceneData(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetCutscenes* cmdCS = std::static_pointer_cast(cmd); + SOH::SetCutscenes* cmdCS = (SOH::SetCutscenes*)cmd; play->csCtx.segment = cmdCS->cutscene->commands.data(); @@ -396,9 +396,9 @@ bool Scene_CommandCutsceneData(PlayState* play, LUS::ISceneCommand* cmd) { } // Camera & World Map Area -bool Scene_CommandMiscSettings(PlayState* play, LUS::ISceneCommand* cmd) { - // LUS::SetCameraSettings* cmdCam = std::static_pointer_cast(cmd); - LUS::SetCameraSettings* cmdCam = (LUS::SetCameraSettings*)cmd; +bool Scene_CommandMiscSettings(PlayState* play, SOH::ISceneCommand* cmd) { + // SOH::SetCameraSettings* cmdCam = std::static_pointer_cast(cmd); + SOH::SetCameraSettings* cmdCam = (SOH::SetCameraSettings*)cmd; YREG(15) = cmdCam->settings.cameraMovement; gSaveContext.worldMapArea = cmdCam->settings.worldMapArea; @@ -420,7 +420,7 @@ bool Scene_CommandMiscSettings(PlayState* play, LUS::ISceneCommand* cmd) { return false; } -bool (*sceneCommands[])(PlayState*, LUS::ISceneCommand*) = { +bool (*sceneCommands[])(PlayState*, SOH::ISceneCommand*) = { Scene_CommandSpawnList, // SCENE_CMD_ID_SPAWN_LIST Scene_CommandActorList, // SCENE_CMD_ID_ACTOR_LIST Scene_CommandUnused2, // SCENE_CMD_ID_UNUSED_2 @@ -449,8 +449,8 @@ bool (*sceneCommands[])(PlayState*, LUS::ISceneCommand*) = { Scene_CommandMiscSettings, // SCENE_CMD_ID_MISC_SETTINGS }; -s32 OTRScene_ExecuteCommands(PlayState* play, LUS::Scene* scene) { - LUS::SceneCommandID cmdCode; +s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene) { + SOH::SceneCommandID cmdCode; for (int i = 0; i < scene->commands.size(); i++) { auto sceneCmd = scene->commands[i]; @@ -487,7 +487,7 @@ extern "C" s32 OTRfunc_800973FC(PlayState* play, RoomContext* roomCtx) { roomCtx->curRoom.segment = roomCtx->unk_34; gSegments[3] = VIRTUAL_TO_PHYSICAL(roomCtx->unk_34); - OTRScene_ExecuteCommands(play, (LUS::Scene*)roomCtx->roomToLoad); + OTRScene_ExecuteCommands(play, (SOH::Scene*)roomCtx->roomToLoad); Player_SetBootData(play, GET_PLAYER(play)); Actor_SpawnTransitionActors(play, &play->actorCtx); @@ -523,7 +523,7 @@ extern "C" s32 OTRfunc_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomN //&roomCtx->loadQueue, NULL, __FILE__, __LINE__); auto roomData = - std::static_pointer_cast(GetResourceByNameHandlingMQ(play->roomList[roomNum].fileName)); + std::static_pointer_cast(GetResourceByNameHandlingMQ(play->roomList[roomNum].fileName)); roomCtx->status = 1; roomCtx->roomToLoad = roomData.get(); From a8d3724a53f57c501612b39c2c5291323ece9814 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 15 Feb 2024 21:28:06 -0600 Subject: [PATCH 093/300] Add missing cvars mostly that patrick forgot because he likes ranch dressing but also some that I missed oops (#3944) --- soh/soh/Enhancements/presets.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index d16e343e1..d25d92780 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -260,6 +260,22 @@ const std::vector enhancementsCvars = { "gAddTraps.Tele", "gAddTraps.Void", "gToTMedallionsColors", + "gCuccoStayDurationMultiplier", + "gDeleteFileOnDeath", + "gEnemySizeScalesHealth", + "gEnhancements.BetterAmmoRendering", + "gEnhancements.EquimentAlwaysVisible", + "gEnhancements.FixDaruniaDanceSpeed", + "gEnhancements.OpenAllHours", + "gEnhancements.ResetNaviTimer", + "gEnhancements.ScaleAdultEquimentAsChild", + "gEnhancements.SwordToggle", + "gFixZoraHintDialogue", + "gHurtContainer", + "gPauseWarp", + "gPermanentHeartLoss", + "gRemoveExplosiveLimit", + "gToggleStrength", }; const std::vector cheatCvars = { From 45992125463a648997159b77517c8a2f4d1fd246 Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 15 Feb 2024 23:02:58 -0500 Subject: [PATCH 094/300] [Fixes] Fix Raised Floor Switches (#3851) * Lower by 1 * gEnhancements. * Update z_obj_switch.c Co-authored-by: Archez * Moved to Hook * Properly this time * Added to presets * Added a Return; * Use Hex Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> --------- Co-authored-by: Archez Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> Co-authored-by: Garrett Cox --- soh/soh/Enhancements/mods.cpp | 19 +++++++++++++++++++ soh/soh/Enhancements/presets.h | 7 +++++++ soh/soh/SohMenuBar.cpp | 3 +++ 3 files changed, 29 insertions(+) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 4788fb4f5..d1147f5fc 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -23,6 +23,7 @@ #include "src/overlays/actors/ovl_En_Tp/z_en_tp.h" #include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h" #include "src/overlays/actors/ovl_En_Xc/z_en_xc.h" +#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" #include "objects/object_link_boy/object_link_boy.h" #include "objects/object_link_child/object_link_child.h" @@ -1359,6 +1360,23 @@ void RegisterToTMedallions() { }); } + +void RegisterFloorSwitchesHook() { + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + if (actor->id != ACTOR_OBJ_SWITCH || !CVarGetInteger("gEnhancements.FixFloorSwitches", 0)) { + return; + } + + ObjSwitch* switchActor = reinterpret_cast(actor); + s32 type = (switchActor->dyna.actor.params & 7); + + if (switchActor->dyna.actor.params == 0x1200 || switchActor->dyna.actor.params == 0x3A00) { + switchActor->dyna.actor.world.pos.y -= 1; + } + }); +} + void RegisterPauseMenuHooks() { static bool pauseWarpHooksRegistered = false; GameInteractor::Instance->RegisterGameHook([&]() { @@ -1411,6 +1429,7 @@ void InitMods() { RegisterOpenAllHours(); RegisterToTMedallions(); NameTag_RegisterHooks(); + RegisterFloorSwitchesHook(); RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); RegisterPauseMenuHooks(); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index d25d92780..025581b0d 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -270,6 +270,7 @@ const std::vector enhancementsCvars = { "gEnhancements.ResetNaviTimer", "gEnhancements.ScaleAdultEquimentAsChild", "gEnhancements.SwordToggle", + "gEnhancements.FixFloorSwitches", "gFixZoraHintDialogue", "gHurtContainer", "gPauseWarp", @@ -543,6 +544,8 @@ const std::vector vanillaPlusPresetEntries = { PRESET_ENTRY_S32("gNaviTextFix", 1), // Extend Silver Rupee Jingle PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), + // Fix some Floor Switches + PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), @@ -614,6 +617,8 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), // Fix enemies not spawning on ground over water PRESET_ENTRY_S32("gEnemySpawnsOverWaterboxes", 1), + // Fix some Floor Switches + PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), @@ -736,6 +741,8 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32("gNaviTextFix", 1), // Extend Silver Rupee Jingle PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), + // Fix some Floor Switches + PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 96d99fbb1..a3f91b145 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1252,6 +1252,9 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Fixes Darunia's dancing speed so he dances to the beat of Saria's Song, like in vanilla."); + UIWidgets::PaddedEnhancementCheckbox("Fix raised Floor Switches", "gEnhancements.FixFloorSwitches", true, false); + UIWidgets::Tooltip("Fixes the two raised floor switches, the one in Forest Temple Basement and the one at the top of Fire Temple. \n" + "This will lower them, making activating them easier"); UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", "gFixZoraHintDialogue", true, false); UIWidgets::Tooltip("Fixes one Zora's dialogue giving a hint about bringing Ruto's Letter to King Zora to properly occur before moving King Zora rather than after"); From c484ea227b8bb2e8343485dbe041c47b1f2f4a2e Mon Sep 17 00:00:00 2001 From: Patrick12115 <115201185+Patrick12115@users.noreply.github.com> Date: Thu, 15 Feb 2024 23:12:09 -0500 Subject: [PATCH 095/300] [Difficulty Options] Leever Spawn Rate (#3460) * Spawn Rate * Update z_en_reeba.c Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> * gEnhancements * Merging issues * Added preset entry and changed timer value math * Update soh/src/overlays/actors/ovl_En_Reeba/z_en_reeba.c * this should do it * Update soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c * move out of loop --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> Co-authored-by: Garrett Cox --- soh/soh/Enhancements/presets.h | 1 + soh/soh/SohMenuBar.cpp | 2 ++ soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 025581b0d..3fede1e9b 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -269,6 +269,7 @@ const std::vector enhancementsCvars = { "gEnhancements.OpenAllHours", "gEnhancements.ResetNaviTimer", "gEnhancements.ScaleAdultEquimentAsChild", + "gEnhancements.LeeverSpawnRate", "gEnhancements.SwordToggle", "gEnhancements.FixFloorSwitches", "gFixZoraHintDialogue", diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index a3f91b145..3ba5030f3 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -977,6 +977,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("All dogs can be traded in and will count as Richard."); UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", "gCuccoStayDurationMultiplier", 1, 5, "", 1, true, true, false); UIWidgets::Tooltip("Cuccos will stay in place longer after putting them down, by a multiple of the value of the slider."); + UIWidgets::PaddedEnhancementSliderInt("Leever Spawn Rate: %d seconds", "##LeeverSpawnRate", "gEnhancements.LeeverSpawnRate", 0, 10, "", 0, true, true, false); + UIWidgets::Tooltip("The time between leever groups spawning."); ImGui::EndMenu(); } diff --git a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c index a43dd8679..146f0deaa 100644 --- a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c +++ b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c @@ -169,6 +169,10 @@ void EnEncount1_SpawnLeevers(EnEncount1* this, PlayState* play) { break; } } + int32_t modifiedSpawnRate = CVarGetInteger("gEnhancements.LeeverSpawnRate", 0); + if (modifiedSpawnRate) { + this->timer = 20 * modifiedSpawnRate; + } } } } From d0b09743b9b9eef10ec7d102b78483e352dd7795 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 15 Feb 2024 23:25:16 -0500 Subject: [PATCH 096/300] Fix missing ImGui::EndDisabled (#3946) --- soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 72ad74e19..4f04bc64b 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1412,6 +1412,7 @@ void DrawSillyTab() { CVarSetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 1); } Reset_Option_Double("Reset##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed"); + ImGui::EndDisabled(); } // Copies the RGB values from one cosmetic option to another, multiplied by the passed in amount, this From 30ff3e9585eccaddae10058b2c773202b9aeab32 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 16 Feb 2024 02:03:22 -0500 Subject: [PATCH 097/300] fix the torch --- soh/src/code/z_onepointdemo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index ad5df65bd..68c0a4dff 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -1174,11 +1174,11 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1 if (actor != NULL && actor->id != ACTOR_PLAYER) { if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) { - return; + return SUBCAM_NONE; } } else { if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) { - return; + return SUBCAM_NONE; } } From 19af4481c08d44fe4bff85eb4662bfb559c4dbfb Mon Sep 17 00:00:00 2001 From: Archez Date: Tue, 20 Feb 2024 09:31:24 -0500 Subject: [PATCH 098/300] fix object unload using wrong index (#3949) --- soh/soh/z_scene_otr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 33104326e..be1840ecd 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -178,7 +178,7 @@ bool Scene_CommandObjectList(PlayState* play, LUS::ISceneCommand* cmd) { // Loop until a mismatch in the object lists // Then clear all object ids past that in the context object list and kill actors for those objects for (i = play->objectCtx.unk_09, k = 0; i < play->objectCtx.num; i++, k++) { - if (i >= cmdObj->objects.size() || play->objectCtx.status[i].id != cmdObj->objects[k]) { + if (k >= cmdObj->objects.size() || play->objectCtx.status[i].id != cmdObj->objects[k]) { for (j = i; j < play->objectCtx.num; j++) { play->objectCtx.status[j].id = OBJECT_INVALID; } From ef9fc0a9ec8716201dfaeb2d28d059171a066b7a Mon Sep 17 00:00:00 2001 From: Archez Date: Tue, 20 Feb 2024 09:38:10 -0500 Subject: [PATCH 099/300] fix endianess issue with camera setting data (#3950) --- soh/src/code/z_camera_data.inc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/soh/src/code/z_camera_data.inc b/soh/src/code/z_camera_data.inc index b9e0ba864..90b1874c7 100644 --- a/soh/src/code/z_camera_data.inc +++ b/soh/src/code/z_camera_data.inc @@ -16,9 +16,11 @@ typedef struct { union { u32 unk_00; struct { - u32 unk_bit0 : 1; - u32 unk_bit1 : 1; - u32 validModes : 30; + // SoH [Port] These bitfield values are unused and led to shifting in validModes for little endian systems + // Removing those so that validModes can be a complete 32 bit value + // u32 unk_bit0 : 1; + // u32 unk_bit1 : 1; + u32 validModes; }; }; CameraMode* cameraModes; From 8b178f938603fc62c2ed2c9a374745a19baf8872 Mon Sep 17 00:00:00 2001 From: Adam Bird Date: Tue, 20 Feb 2024 16:52:42 -0500 Subject: [PATCH 100/300] RandoV3 fixes for mix/decouple boss entrances --- .../randomizer/3drando/location_access.cpp | 2 +- soh/soh/Enhancements/randomizer/entrance.cpp | 211 ++++++++++++++---- soh/soh/Enhancements/randomizer/entrance.h | 10 +- .../randomizer/option_descriptions.cpp | 4 +- .../Enhancements/randomizer/randomizer.cpp | 17 -- soh/soh/Enhancements/randomizer/settings.cpp | 7 + soh/soh/SaveManager.cpp | 2 +- 7 files changed, 184 insertions(+), 69 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index 7eb1436df..e389e440e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -502,7 +502,7 @@ Area* AreaTable(const RandomizerRegion areaKey) { std::vector GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary /*= true*/) { std::vector entrancesToShuffle = {}; for (RandomizerRegion area : Areas::GetAllAreas()) { - for (auto& exit: AreaTable(area)->exits) { + for (auto& exit : AreaTable(area)->exits) { if ((exit.GetType() == type || type == Rando::EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != Rando::EntranceType::None) { entrancesToShuffle.push_back(&exit); } diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index ee9df1dc1..2f4b43d26 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -10,6 +10,7 @@ EntranceLinkInfo NO_RETURN_ENTRANCE = { EntranceType::None, RR_NONE, RR_NONE, -1 Entrance::Entrance(RandomizerRegion connectedRegion_, std::vector conditions_met_) : connectedRegion(connectedRegion_) { + originalConnectedRegion = connectedRegion_; conditions_met.resize(2); for (size_t i = 0; i < conditions_met_.size(); i++) { conditions_met[i] = conditions_met_[i]; @@ -109,6 +110,10 @@ RandomizerRegion Entrance::GetConnectedRegionKey() const { return connectedRegion; } +RandomizerRegion Entrance::GetOriginalConnectedRegionKey() const { + return originalConnectedRegion; +} + Area* Entrance::GetConnectedRegion() const { return AreaTable(connectedRegion); } @@ -173,14 +178,6 @@ void Entrance::SetIndex(int16_t newIndex) { index = newIndex; } -int16_t Entrance::GetBlueWarp() const { - return blueWarp; -} - -void Entrance::SetBlueWarp(int16_t newBlueWarp) { - blueWarp = newBlueWarp; -} - Entrance* Entrance::GetAssumed() const { return assumed; } @@ -226,7 +223,7 @@ Entrance* Entrance::GetNewTarget() { AreaTable(RR_ROOT)->AddExit(RR_ROOT, connectedRegion, [] { return true; }); Entrance* targetEntrance = AreaTable(RR_ROOT)->GetExit(connectedRegion); targetEntrance->SetReplacement(this); - targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName); + targetEntrance->SetName(AreaTable(RR_ROOT)->regionName + " -> " + GetConnectedRegion()->regionName); return targetEntrance; } @@ -246,6 +243,11 @@ void EntranceShuffler::SetNoRandomEntrances(bool noRandomEntrances) { mNoRandomEntrances = noRandomEntrances; } +// Construct entrance name from parent and connected region keys +std::string EntranceNameByRegions(RandomizerRegion parentRegion, RandomizerRegion connectedRegion) { + return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName; +} + void SetAllEntrancesData(std::vector& entranceShuffleTable) { auto ctx = Rando::Context::GetInstance(); for (auto& entrancePair : entranceShuffleTable) { @@ -256,26 +258,22 @@ void SetAllEntrancesData(std::vector& entranceShuffleTable) { // set data Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion); forwardEntrance->SetIndex(forwardEntry.index); - forwardEntrance->SetBlueWarp(forwardEntry.blueWarp); forwardEntrance->SetType(forwardEntry.type); forwardEntrance->SetAsPrimary(); - // When decouple entrances is on, mark it for entrances except boss rooms - if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES) && forwardEntry.type != EntranceType::ChildBoss && - forwardEntry.type != EntranceType::AdultBoss) { + // When decouple entrances is on, mark the forward entrance + if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { forwardEntrance->SetDecoupled(); } if (returnEntry.parentRegion != RR_NONE) { Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion); returnEntrance->SetIndex(returnEntry.index); - returnEntrance->SetBlueWarp(returnEntry.blueWarp); returnEntrance->SetType(returnEntry.type); forwardEntrance->BindTwoWay(returnEntrance); // Mark reverse entrance as decoupled - if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES) && returnEntry.type != EntranceType::ChildBoss && - returnEntry.type != EntranceType::AdultBoss) { + if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { returnEntrance->SetDecoupled(); } } @@ -925,24 +923,23 @@ int EntranceShuffler::ShuffleAllEntrances() { mCurNumRandomizedEntrances = 0; std::vector entranceShuffleTable = { - // Parent Region Connected Region index blue warp + // Type Parent Region Connected Region Index { { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, 0x0000 }, - { EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457 } }, + { EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, 0x0209 } }, { { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, 0x0004 }, - { EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A } }, + { EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, 0x0242 } }, { { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, 0x0028 }, - { EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x0221, 0x010E } }, + { EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x0221 } }, { { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, 0x0169 }, - { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, 0x0215, 0x0608 } }, + { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, 0x0215 } }, { { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, 0x0165 }, - { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, 0x024A, 0x0564 } }, + { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, 0x024A } }, { { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, 0x0010 }, - { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, 0x021D, 0x060C } }, + { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, 0x021D } }, { { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, 0x0082 }, - { EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, - 0x0610 } }, + { EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1 } }, { { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, 0x0037 }, - { EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580 } }, + { EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, 0x0205 } }, { { EntranceType::Dungeon, RR_KAKARIKO_VILLAGE, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098 }, { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAKARIKO_VILLAGE, 0x02A6 } }, { { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_ICE_CAVERN_ENTRYWAY, 0x0088 }, @@ -1190,22 +1187,32 @@ int EntranceShuffler::ShuffleAllEntrances() { { { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, 0x05F4 }, NO_RETURN_ENTRANCE }, { { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, 0x040F }, - { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457 } }, + { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, 0x0252 } }, { { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, 0x040B }, - { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A } }, + { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5 } }, { { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, 0x0301 }, - { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, - 0x010E } }, + { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407 } }, { { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, 0x000C }, - { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608 } }, + { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E } }, { { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, 0x0305 }, - { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564 } }, + { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175 } }, { { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, 0x0417 }, - { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C } }, + { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423 } }, { { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, 0x008D }, - { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610 } }, + { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5 } }, { { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, 0x0413 }, - { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580 } }, + { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2 } }, + + { { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, 0x0457 }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, 0x047A }, + NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, 0x010E }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, 0x0608 }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, 0x0564 }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, 0x060C }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, 0x0610 }, NO_RETURN_ENTRANCE }, + { { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, 0x0580 }, + NO_RETURN_ENTRANCE }, }; std::map priorityEntranceTable = { @@ -1262,6 +1269,11 @@ int EntranceShuffler::ShuffleAllEntrances() { entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM; }); } + if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { + for (Entrance* entrance : entrancePools[EntranceType::Boss]) { + entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse()); + } + } } else { entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); @@ -1273,6 +1285,14 @@ int EntranceShuffler::ShuffleAllEntrances() { entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM; }); } + if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { + for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) { + entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse()); + } + for (Entrance* entrance : entrancePools[EntranceType::AdultBoss]) { + entrancePools[EntranceType::AdultBossReverse].push_back(entrance->GetReverse()); + } + } } } @@ -1346,11 +1366,13 @@ int EntranceShuffler::ShuffleAllEntrances() { // combine entrance pools if mixing pools. Only continue if more than one pool is selected. int totalMixedPools = - (ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + - (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0); + (ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_BOSS_ENTRANCES) ? 1 : 0) + + (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) + + (ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0); if (totalMixedPools < 2) { ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetSelectedIndex(RO_GENERIC_OFF); ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); @@ -1364,6 +1386,12 @@ int EntranceShuffler::ShuffleAllEntrances() { poolsToMix.insert(EntranceType::DungeonReverse); } } + if (ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES)) { + poolsToMix.insert(EntranceType::Boss); + if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { + poolsToMix.insert(EntranceType::BossReverse); + } + } if (ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { poolsToMix.insert(EntranceType::Overworld); } @@ -1503,6 +1531,94 @@ int EntranceShuffler::ShuffleAllEntrances() { } } + // Determine blue warp targets + // RANDOTODO: add bluewarp shuffle + if (true /* ctx->GetOption(RSK_SHUFFLE_BLUEWARP_ENTRANCES).Is(RO_BLUEWARP_ENTRANCE_SHUFFLE_DUNGEON) */) { + // If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance + std::map bossExits = { + { EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE)) }, + { EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL)) }, + { EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN)) }, + { EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW)) }, + { EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL)) }, + { EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA)) }, + { EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY)) }, + { EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION)) }, + }; + + // If a boss room is inside a dungeon entrance (or inside a dungeon which is inside a dungeon entrance), make + // the blue warp go to that dungeon's blue warp target + std::map dungeonExits = { + { EntranceNameByRegions(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE), + GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE)) }, + { EntranceNameByRegions(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL), + GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL)) }, + { EntranceNameByRegions(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN), + GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN)) }, + { EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW), + GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW)) }, + { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL), + GetEntrance(EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL)) }, + { EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA), + GetEntrance(EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA)) }, + { EntranceNameByRegions(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY), + GetEntrance(EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS)) }, + { EntranceNameByRegions(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION), + GetEntrance(EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION)) }, + }; + + // Pair + std::vector bossRoomExitPairs = { + { GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE)), + GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL)), + GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN)), + GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW)), + GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL)), + GetEntrance(EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA)), + GetEntrance(EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS)), + GetEntrance(EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY)) }, + { GetEntrance(EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION)), + GetEntrance(EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY)) }, + }; + + for (EntrancePair pair : bossRoomExitPairs) { + Entrance* target = pair.second->GetReplacement() != nullptr ? pair.second->GetReplacement() : pair.second; + + if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { + while (bossExits.find(target->GetName()) != bossExits.end()) { + Entrance* next = bossExits.at(target->GetName()); + target = next->GetReplacement() != nullptr ? next->GetReplacement() : next; + } + + if (dungeonExits.find(target->GetName()) != dungeonExits.end()) { + target = dungeonExits.at(target->GetName()); + } + } + + pair.first->Connect(target->GetOriginalConnectedRegionKey()); + pair.first->SetReplacement(target); + } + } + + // Validate the world one last time to ensure all special conditions are still valid + if (!ValidateWorld(nullptr)) { + return ENTRANCE_SHUFFLE_FAILURE; + } + return ENTRANCE_SHUFFLE_SUCCESS; } @@ -1518,16 +1634,21 @@ void EntranceShuffler::CreateEntranceOverrides() { int i = 0; for (Entrance* entrance : allShuffleableEntrances) { + // Include blue warps when dungeons or bosses are shuffled + bool includeBluewarps = + entrance->GetType() == Rando::EntranceType::BlueWarp && + (ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES)); + // Double-check to make sure the entrance is actually shuffled - if (!entrance->IsShuffled()) { + if (!entrance->IsShuffled() && !includeBluewarps) { continue; } auto message = "Setting " + entrance->to_string() + "\n"; SPDLOG_DEBUG(message); + uint8_t type = (uint8_t)entrance->GetType(); int16_t originalIndex = entrance->GetIndex(); - int16_t originalBlueWarp = entrance->GetBlueWarp(); int16_t replacementIndex = entrance->GetReplacement()->GetIndex(); int16_t destinationIndex = -1; @@ -1541,9 +1662,9 @@ void EntranceShuffler::CreateEntranceOverrides() { } entranceOverrides[i] = { + .type = type, .index = originalIndex, .destination = destinationIndex, - .blueWarp = originalBlueWarp, .override = replacementIndex, .overrideDestination = replacementDestinationIndex, }; @@ -1559,9 +1680,9 @@ void EntranceShuffler::CreateEntranceOverrides() { /// @brief set all the entrances to be 0 to indicate an unshuffled entrance void EntranceShuffler::UnshuffleAllEntrances() { for (auto& entranceOveride : entranceOverrides) { + entranceOveride.type = 0; entranceOveride.index = 0; entranceOveride.destination = 0; - entranceOveride.blueWarp = 0; entranceOveride.override = 0; entranceOveride.overrideDestination = 0; } @@ -1575,12 +1696,12 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) { for (auto it = entrancesJson.begin(); it != entrancesJson.end(); ++it, i++) { nlohmann::json entranceJson = *it; for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) { - if (entranceIt.key() == "index") { + if (entranceIt.key() == "type") { + entranceOverrides[i].type = entranceIt.value(); + } else if (entranceIt.key() == "index") { entranceOverrides[i].index = entranceIt.value(); } else if (entranceIt.key() == "destination") { entranceOverrides[i].destination = entranceIt.value(); - } else if (entranceIt.key() == "blueWarp") { - entranceOverrides[i].blueWarp = entranceIt.value(); } else if (entranceIt.key() == "override") { entranceOverrides[i].override = entranceIt.value(); } else if (entranceIt.key() == "overrideDestination") { @@ -1593,5 +1714,5 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) { } // namespace Rando extern "C" EntranceOverride* Randomizer_GetEntranceOverrides() { - return Rando::Context::GetInstance()->GetEntranceShuffler()->entranceOverrides.data(); + return Rando::Context::GetInstance()->GetEntranceShuffler()->entranceOverrides.data(); } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/entrance.h b/soh/soh/Enhancements/randomizer/entrance.h index 0886ddb26..e17687842 100644 --- a/soh/soh/Enhancements/randomizer/entrance.h +++ b/soh/soh/Enhancements/randomizer/entrance.h @@ -15,12 +15,16 @@ enum class EntranceType { OwlDrop, Spawn, WarpSong, + BlueWarp, Dungeon, GanonDungeon, DungeonReverse, Boss, + BossReverse, ChildBoss, + ChildBossReverse, AdultBoss, + AdultBossReverse, Interior, InteriorReverse, SpecialInterior, @@ -45,6 +49,7 @@ class Entrance { uint32_t Getuint32_t() const; bool CheckConditionAtAgeTime(bool& age, bool& time, bool passAnyway = false) const; RandomizerRegion GetConnectedRegionKey() const; + RandomizerRegion GetOriginalConnectedRegionKey() const; Area* GetConnectedRegion() const; void SetParentRegion(RandomizerRegion newParent); RandomizerRegion GetParentRegionKey() const; @@ -61,8 +66,6 @@ class Entrance { void SetDecoupled(); int16_t GetIndex() const; void SetIndex(int16_t newIndex); - int16_t GetBlueWarp() const; - void SetBlueWarp(int16_t newBlueWarp); Entrance* GetAssumed() const; void SetReplacement(Entrance* newReplacement); Entrance* GetReplacement() const; @@ -78,6 +81,7 @@ class Entrance { private: RandomizerRegion parentRegion; RandomizerRegion connectedRegion; + RandomizerRegion originalConnectedRegion; std::vector conditions_met; EntranceType type = EntranceType::None; @@ -86,7 +90,6 @@ class Entrance { Entrance* assumed = nullptr; Entrance* replacement = nullptr; int16_t index = 0xFFFF; - int16_t blueWarp = 0; bool shuffled = false; bool primary = false; bool addedToPool = false; @@ -99,7 +102,6 @@ typedef struct { RandomizerRegion parentRegion; RandomizerRegion connectedRegion; int16_t index; - int16_t blueWarp; } EntranceLinkInfo; typedef struct { diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 95db75e55..e50846005 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -170,12 +170,14 @@ void Settings::CreateOptionDescriptions() { "This also adds the one-way entrance from Gerudo Valley to Lake Hylia in the pool of " "overworld entrances when they are shuffled."; mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS] = - "Shuffle entrances into a mixed pool instead of separate ones.\n" + "Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose " + "entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n" "\n" "For example, enabling the settings to shuffle grotto, dungeon, and overworld entrances and " "selecting grotto and dungeon entrances here will allow a dungeon to be inside a grotto or " "vice versa, while overworld entrances are shuffled in their own separate pool and indoors stay vanilla."; mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES] = "Dungeon entrances will be part of the mixed pool"; + mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES] = "Boss entrances will be part of the mixed pool"; mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES] = "Overworld entrances will be part of the mixed pool"; mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES] = "Interior entrances will be part of the mixed pool"; mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES] = "Grotto entrances will be part of the mixed pool"; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b2d9c7866..179f8144e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -236,23 +236,6 @@ std::unordered_map getItemIdToItemId = { { GI_CLAIM_CHECK, ITEM_CLAIM_CHECK } }; -std::string sanitize(std::string stringValue) { - // Add backslashes. - for (auto i = stringValue.begin();;) { - auto const pos = std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; }); - if (pos == stringValue.end()) { - break; - } - i = std::next(stringValue.insert(pos, '\\'), 2); - } - - // Removes others. - stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(), [](char const c) { - return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }), stringValue.end()); - - return stringValue; -} - #pragma optimize("", off) #pragma GCC push_options #pragma GCC optimize ("O0") diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 3fc4efa86..ac947d4da 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -68,6 +68,7 @@ void Settings::CreateOptions() { mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", "gRandomizeShuffleOverworldSpanws", mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]); mOptions[RSK_MIXED_ENTRANCE_POOLS] = Option::Bool("Mixed Entrance Pools", "gRandomizeMixedEntrances", mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]); mOptions[RSK_MIX_DUNGEON_ENTRANCES] = Option::Bool("Mix Dungeons", "gRandomizeMixDungeons", mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE); + mOptions[RSK_MIX_BOSS_ENTRANCES] = Option::Bool("Mix Bosses", "gRandomizeMixBosses", mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE); mOptions[RSK_MIX_OVERWORLD_ENTRANCES] = Option::Bool("Mix Overworld", "gRandomizeMixOverworld", mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE); mOptions[RSK_MIX_INTERIOR_ENTRANCES] = Option::Bool("Mix Interiors", "gRandomizeMixInteriors", mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE); mOptions[RSK_MIX_GROTTO_ENTRANCES] = Option::Bool("Mix Grottos", "gRandomizeMixGrottos", mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]); @@ -638,6 +639,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DECOUPLED_ENTRANCES], &mOptions[RSK_MIXED_ENTRANCE_POOLS], &mOptions[RSK_MIX_DUNGEON_ENTRANCES], + &mOptions[RSK_MIX_BOSS_ENTRANCES], &mOptions[RSK_MIX_OVERWORLD_ENTRANCES], &mOptions[RSK_MIX_INTERIOR_ENTRANCES], &mOptions[RSK_MIX_GROTTO_ENTRANCES] @@ -828,6 +830,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS], &mOptions[RSK_MIXED_ENTRANCE_POOLS], &mOptions[RSK_MIX_DUNGEON_ENTRANCES], + &mOptions[RSK_MIX_BOSS_ENTRANCES], &mOptions[RSK_MIX_OVERWORLD_ENTRANCES], &mOptions[RSK_MIX_INTERIOR_ENTRANCES], &mOptions[RSK_MIX_GROTTO_ENTRANCES], @@ -1159,6 +1162,7 @@ void Settings::CreateOptions() { { "World Settings:Overworld Spawns", RSK_SHUFFLE_OVERWORLD_SPAWNS }, { "World Settings:Mixed Entrance Pools", RSK_MIXED_ENTRANCE_POOLS }, { "World Settings:Mix Dungeons", RSK_MIX_DUNGEON_ENTRANCES }, + { "World Settings:Mix Bosses", RSK_MIX_BOSS_ENTRANCES }, { "World Settings:Mix Overworld", RSK_MIX_OVERWORLD_ENTRANCES }, { "World Settings:Mix Interiors", RSK_MIX_INTERIOR_ENTRANCES }, { "World Settings:Mix Grottos", RSK_MIX_GROTTO_ENTRANCES }, @@ -1534,12 +1538,14 @@ void Settings::UpdateOptionProperties() { if (CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF)) { mOptions[RSK_MIXED_ENTRANCE_POOLS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MIX_DUNGEON_ENTRANCES].Unhide(); + mOptions[RSK_MIX_BOSS_ENTRANCES].Unhide(); mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Unhide(); mOptions[RSK_MIX_INTERIOR_ENTRANCES].Unhide(); mOptions[RSK_MIX_GROTTO_ENTRANCES].Unhide(); } else { mOptions[RSK_MIXED_ENTRANCE_POOLS].AddFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MIX_DUNGEON_ENTRANCES].Hide(); + mOptions[RSK_MIX_BOSS_ENTRANCES].Hide(); mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Hide(); mOptions[RSK_MIX_INTERIOR_ENTRANCES].Hide(); mOptions[RSK_MIX_GROTTO_ENTRANCES].Hide(); @@ -2309,6 +2315,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SHUFFLE_OVERWORLD_SPAWNS: case RSK_MIXED_ENTRANCE_POOLS: case RSK_MIX_DUNGEON_ENTRANCES: + case RSK_MIX_BOSS_ENTRANCES: case RSK_MIX_OVERWORLD_ENTRANCES: case RSK_MIX_INTERIOR_ENTRANCES: case RSK_MIX_GROTTO_ENTRANCES: diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 0fc3394c9..cb5820204 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -357,9 +357,9 @@ void SaveManager::LoadRandomizerVersion3() { auto entranceCtx = randoContext->GetEntranceShuffler(); SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) { SaveManager::Instance->LoadStruct("", [&]() { + SaveManager::Instance->LoadData("type", entranceCtx->entranceOverrides[i].type); SaveManager::Instance->LoadData("index", entranceCtx->entranceOverrides[i].index); SaveManager::Instance->LoadData("destination", entranceCtx->entranceOverrides[i].destination); - SaveManager::Instance->LoadData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp); SaveManager::Instance->LoadData("override", entranceCtx->entranceOverrides[i].override); SaveManager::Instance->LoadData("overrideDestination", entranceCtx->entranceOverrides[i].overrideDestination); From 00b358115196648cb50bcff4cce08694ce759000 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Tue, 20 Feb 2024 18:15:10 -0800 Subject: [PATCH 101/300] Skull Kid (#86) Co-authored-by: Garrett Cox --- .../Enhancements/game-interactor/GameInteractor.h | 3 ++- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 1 + soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 14 ++++---------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 2cac52637..f27342c3e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -271,8 +271,9 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, // Opt: *EnFr GI_VB_GIVE_ITEM_FROM_FROGS, + // Opt: *EnSkj + GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, - // Opt: *EnSyatekiMan GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 87c7f5b3c..511c0d7e6 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -803,6 +803,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: + case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: case GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF: case GI_VB_GIVE_ITEM_SKULL_TOKEN: case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 207d9612b..8b6545f76 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1039,11 +1039,8 @@ void EnSkj_SariaSongTalk(EnSkj* this, PlayState* play) { EnSkj_SetupWaitInRange(this); } else { func_80AFFE24(this); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1054,15 +1051,12 @@ void func_80AFFE24(EnSkj* this) { } void func_80AFFE44(EnSkj* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { this->actor.parent = NULL; EnSkj_SetupPostSariasSong(this); } else { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1072,7 +1066,7 @@ void EnSkj_SetupPostSariasSong(EnSkj* this) { } void EnSkj_ChangeModeAfterSong(EnSkj* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { Flags_SetItemGetInf(ITEMGETINF_16); EnSkj_SetNaviId(this); EnSkj_SetupWaitInRange(this); From 0dda3a6c298af5481e967de0fd9ae1ba21547e24 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Tue, 20 Feb 2024 21:00:10 -0600 Subject: [PATCH 102/300] More boss intro skips --- soh/soh/Enhancements/randomizer/savefile.cpp | 5 ++- .../Enhancements/timesaver_hook_handlers.cpp | 37 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 19ef26ac0..95840b15c 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -247,9 +247,10 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); + // Now handled by cutscene skips // Skip cutscenes before Nabooru fight - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); // Now handled by cutscene skips // Skip boss cutscenes diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index cd34e5608..1a349805f 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -638,6 +638,43 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { } } break; + case SCENE_FOREST_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); + } + } + break; + case SCENE_FIRE_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); + } + } + break; + case SCENE_WATER_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); + } + } + break; + case SCENE_SPIRIT_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + } + } + break; + case SCENE_SHADOW_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); + } + } + break; } } From 72581f74827ef5cc16dcde42f77671bcc372015b Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Tue, 20 Feb 2024 21:04:16 -0600 Subject: [PATCH 103/300] Re-add some UI I accidentally removed --- soh/soh/SohMenuBar.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 2ec571e26..15f67f763 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -643,8 +643,37 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); - UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); - UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); + UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); + UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); + UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); + bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); + static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, + forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); + UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); + UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); + UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); + UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false); + UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); + UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false); + UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); + + ImGui::TableNextColumn(); + UIWidgets::Spacer(0); + ImGui::Text("Changes:"); + UIWidgets::PaddedSeparator(); + + UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); + UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); + UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); + UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" + "This doesn't work if the save was made in a grotto."); + UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); + UIWidgets::Tooltip("Prevent forced Navi conversations"); + UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false); + UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. "); UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); From 37e89c0c7c9f8cf060ff2499ba5ec324aa73a2b2 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Tue, 20 Feb 2024 21:49:07 -0600 Subject: [PATCH 104/300] Migrate song of storms check --- .../Enhancements/randomizer/location_list.cpp | 2 +- .../Enhancements/timesaver_hook_handlers.cpp | 41 +++++++++++++++++++ soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c | 20 +-------- soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h | 3 ++ 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 67b2b35ed..faebd65c9 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1316,7 +1316,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x00), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x5B), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); //Beehives locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 1a349805f..58cdfb6fe 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -18,6 +18,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Sa/z_en_sa.h" #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" +#include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -51,6 +52,19 @@ void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { } } +void EnFu_EndTeachSong(EnFu* enFu, PlayState* play) { + if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { + func_80078884(NA_SE_SY_CORRECT_CHIME); + enFu->actionFunc = EnFu_WaitAdult; + enFu->actor.flags &= ~ACTOR_FLAG_WILL_TALK; + + play->msgCtx.ocarinaMode = OCARINA_MODE_04; + Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS); + return; + } +} + u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) { return 0x207D; } @@ -518,6 +532,8 @@ static uint32_t itemOcarinaUpdateHook = 0; static uint32_t itemOcarinaframesSinceSpawn = 0; static uint32_t enMa1UpdateHook = 0; static uint32_t enMa1KillHook = 0; +static uint32_t enFuUpdateHook = 0; +static uint32_t enFuKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); @@ -593,6 +609,28 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_EN_FU) { + enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + EnFu* enFu = static_cast(innerActorRef); + if (enFu->actionFunc == EnFu_TeachSong) { + enFu->actionFunc = EnFu_EndTeachSong; + GameInteractor::Instance->UnregisterGameHook(enFuUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enFuKillHook); + enFuUpdateHook = 0; + enFuKillHook = 0; + } + } + }); + enMa1KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + }); + } + if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { EnZl4* enZl4 = static_cast(actorRef); if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; @@ -740,6 +778,9 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { case EVENTCHKINF_LEARNED_SONG_OF_TIME: vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy(); break; + case EVENTCHKINF_LEARNED_SONG_OF_STORMS: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy(); + break; } break; case FLAG_RANDOMIZER_INF: diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 278fb18e2..ad1d6f12a 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -161,20 +161,12 @@ void GivePlayerRandoRewardSongOfStorms(EnFu* windmillGuy, PlayState* play, Rando } } -void func_WaitForSongGive(EnFu* this, PlayState* play) { - GivePlayerRandoRewardSongOfStorms(this, play, RC_SONG_FROM_WINDMILL); -} - void func_80A1DB60(EnFu* this, PlayState* play) { if (play->csCtx.state == CS_STATE_IDLE) { this->actionFunc = EnFu_WaitAdult; Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS); play->msgCtx.ocarinaMode = OCARINA_MODE_04; } - - if (IS_RANDO) { - this->actionFunc = func_WaitForSongGive; - } } void func_80A1DBA0(EnFu* this, PlayState* play) { @@ -186,10 +178,6 @@ void func_80A1DBA0(EnFu* this, PlayState* play) { void func_80A1DBD4(EnFu* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) { - play->msgCtx.ocarinaMode = OCARINA_MODE_03; - } - if (play->msgCtx.ocarinaMode >= OCARINA_MODE_04) { this->actionFunc = EnFu_WaitAdult; play->msgCtx.ocarinaMode = OCARINA_MODE_04; @@ -199,12 +187,6 @@ void func_80A1DBD4(EnFu* this, PlayState* play) { this->actionFunc = func_80A1DB60; this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - if (!IS_RANDO) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gSongOfStormsCs); - gSaveContext.cutsceneTrigger = 1; - Item_Give(play, ITEM_SONG_STORMS); - } - play->msgCtx.ocarinaMode = OCARINA_MODE_00; Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_02) { @@ -249,7 +231,7 @@ void EnFu_WaitAdult(EnFu* this, PlayState* play) { } else if (player->stateFlags2 & 0x1000000) { this->actor.textId = 0x5035; Message_StartTextbox(play, this->actor.textId, NULL); - this->actionFunc = IS_RANDO ? func_80A1DBD4 : EnFu_TeachSong; + this->actionFunc = EnFu_TeachSong; this->behaviorFlags |= FU_WAIT; } else if (Actor_ProcessTalkRequest(&this->actor, play)) { this->actionFunc = func_80A1DBA0; diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h index 7fddd6543..fd371000d 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h @@ -41,4 +41,7 @@ typedef struct EnFu { /* 0x02AC */ EnFuActionFunc actionFunc; } EnFu; // size = 0x02B0 +void EnFu_TeachSong(EnFu* enFu, PlayState* play); +void EnFu_WaitAdult(EnFu* enFu, PlayState* play); + #endif From cd25f1d3c1fcecd574e6a4019c6f9cc41260ff1c Mon Sep 17 00:00:00 2001 From: Archez Date: Wed, 21 Feb 2024 00:20:25 -0500 Subject: [PATCH 105/300] Fix performance of dlist viewer (#3961) --- soh/soh/Enhancements/debugger/dlViewer.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/debugger/dlViewer.cpp b/soh/soh/Enhancements/debugger/dlViewer.cpp index da44a908a..028234fc1 100644 --- a/soh/soh/Enhancements/debugger/dlViewer.cpp +++ b/soh/soh/Enhancements/debugger/dlViewer.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "dlViewer.h" @@ -68,14 +67,12 @@ std::map cmdMap = { void PerformDisplayListSearch() { auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); - std::regex dlSearch(".*((DL)|(DL_.*))$"); - displayListSearchResults.clear(); // Filter the file results even further as StormLib can only use wildcard searching for (size_t i = 0; i < result->size(); i++) { std::string val = result->at(i); - if (std::regex_search(val.c_str(), dlSearch)) { + if (val.ends_with("DL") || val.find("DL_") != std::string::npos) { displayListSearchResults.push_back(val); } } @@ -99,8 +96,6 @@ void DLViewerWindow::DrawElement() { return; } - ImGui::Text("%d", searchDebounceFrames); - // Debounce the search field as listing otr files is expensive if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) { doSearch = true; From bcbe4cb1c35798cc1017844fc453de8ab8bfc6f1 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 21 Feb 2024 00:21:26 -0500 Subject: [PATCH 106/300] we crash if we try to SPDLOG in the destructors (#3951) * we crash if we try to SPDLOG in the destructors * rip em out * newline * add to destroy * Revert "rip em out" This reverts commit 738a9b80f327fe728e176d63ab2d54a36fb908ad. * Revert "we crash if we try to SPDLOG in the destructors" This reverts commit 327d305e00ab9cb05ca93c5566a06ae9a345d329. --- soh/soh/Enhancements/controls/InputViewer.h | 2 +- soh/soh/SohGui.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/controls/InputViewer.h b/soh/soh/Enhancements/controls/InputViewer.h index 646c15d9d..6f2e2c587 100644 --- a/soh/soh/Enhancements/controls/InputViewer.h +++ b/soh/soh/Enhancements/controls/InputViewer.h @@ -44,4 +44,4 @@ public: ~InputViewerSettingsWindow(); void Draw(); -}; \ No newline at end of file +}; diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 4cb43d3a8..bbc12b1a1 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -224,5 +224,7 @@ namespace SohGui { mStatsWindow = nullptr; mConsoleWindow = nullptr; mSohMenuBar = nullptr; + mInputViewer = nullptr; + mInputViewerSettings = nullptr; } } From 7bebe7a5738f355278b8e0d512958678aeeae442 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Wed, 21 Feb 2024 14:01:49 -0600 Subject: [PATCH 107/300] Migrate okarina_tag changes --- .../game-interactor/GameInteractor.h | 13 +++ .../Enhancements/randomizer/hook_handlers.cpp | 10 +++ .../Enhancements/randomizer/location_list.cpp | 2 +- .../Enhancements/timesaver_hook_handlers.cpp | 81 +++++++++++++++++-- .../z_bg_spot02_objects.c | 26 +----- .../z_bg_spot02_objects.h | 3 + .../ovl_En_Okarina_Tag/z_en_okarina_tag.c | 48 +++-------- 7 files changed, 117 insertions(+), 66 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index f27342c3e..940e49cae 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -206,6 +206,9 @@ typedef enum { // Opt: *EnSyatekiMan // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, + // Opt: *EnOkarinaTag + // Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME) + GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, /*** Play Cutscenes ***/ @@ -235,6 +238,16 @@ typedef enum { GI_VB_PLAY_BOLERO_OF_FIRE_CS, GI_VB_PLAY_SERENADE_OF_WATER_CS, GI_VB_PLAY_EYEDROPS_CS, + // Opt: *EnOkarinaTag + GI_VB_PLAY_DRAIN_WELL_CS, + // Opt: *EnOkarinaTag + // Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SUN) + GI_VB_PLAY_SUNS_SONG_CS, + // Opt: *EnOkarinaTag + GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, + GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, + // Opt: *EnOkarinaTag + GI_VB_PLAY_DOOR_OF_TIME_CS, /*** Give Items ***/ diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 511c0d7e6..c55331edf 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -796,6 +796,16 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } + case GI_VB_BE_ELIGIBLE_TO_OPEN_DOT: { + bool eligible = RAND_GET_OPTION(RSK_DOOR_OF_TIME) != RO_DOOROFTIME_CLOSED || ( + INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_TIME && + CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && + CHECK_QUEST_ITEM(QUEST_GORON_RUBY) && + CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) + ); + *should = eligible; + break; + } case GI_VB_TRADE_CLAIM_CHECK: case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index faebd65c9..8deeab8c8 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1314,7 +1314,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x00), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 58cdfb6fe..44102f944 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -19,6 +19,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" +#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -471,6 +472,44 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case GI_VB_PLAY_DRAIN_WELL_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + *should = false; + Flags_SetSwitch(gPlayState, 0x2); + Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); + Flags_SetEventChkInf(EVENTCHKINF_DRAINED_WELL_IN_KAKARIKO); + } + break; + } + case GI_VB_PLAY_SUNS_SONG_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + *should = false; + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG); + // SoH [Randomizer] TODO: Increment time X amount (find out X) + // When time is 0, it's changed to 0x46A7 + // When it's 0x8000, it's changed to 0xC090 + } + break; + case GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + *should = false; + } + break; + } + case GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + *should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); + } + break; + } + case GI_VB_PLAY_DOOR_OF_TIME_CS: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + *should = false; + Flags_SetEnv(gPlayState, 2); + func_80078884(NA_SE_SY_CORRECT_CHIME); + } + break; + } case GI_VB_GIVE_ITEM_MINUET_OF_FOREST: case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE: case GI_VB_GIVE_ITEM_SERENADE_OF_WATER: @@ -534,6 +573,8 @@ static uint32_t enMa1UpdateHook = 0; static uint32_t enMa1KillHook = 0; static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; +static uint32_t bgSpot02UpdateHook = 0; +static uint32_t bgSpot02KillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); @@ -610,7 +651,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { } if (actor->id == ACTOR_EN_FU) { - enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + enFuUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { EnFu* enFu = static_cast(innerActorRef); @@ -623,11 +664,36 @@ void TimeSaverOnActorInitHandler(void* actorRef) { } } }); - enMa1KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { - GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); - GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); - enMa1UpdateHook = 0; - enMa1KillHook = 0; + enFuKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enFuUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enFuKillHook); + enFuUpdateHook = 0; + enFuKillHook = 0; + }); + } + + if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) { + SPDLOG_INFO("Registering BG_SPOT02 hook"); + bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0))) { + SPDLOG_INFO("on update BG_SPOT02 hook"); + BgSpot02Objects* bgSpot02 = static_cast(innerActorRef); + if (bgSpot02->actionFunc == func_808ACC34) { + SPDLOG_INFO("BGspot02 OVERRIDDEN"); + bgSpot02->actionFunc = func_808AC908; + GameInteractor::Instance->UnregisterGameHook(bgSpot02UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot02KillHook); + bgSpot02UpdateHook = 0; + bgSpot02KillHook = 0; + } + } + }); + bgSpot02KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(bgSpot02UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot02KillHook); + bgSpot02UpdateHook = 0; + bgSpot02KillHook = 0; }); } @@ -781,6 +847,9 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { case EVENTCHKINF_LEARNED_SONG_OF_STORMS: vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy(); break; + case EVENTCHKINF_LEARNED_SUNS_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SUNS_SONG).GetGIEntry_Copy(); + break; } break; case FLAG_RANDOMIZER_INF: diff --git a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c index 2eb3faeda..cc7d4c854 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c @@ -6,6 +6,7 @@ #include "z_bg_spot02_objects.h" #include "objects/object_spot02_objects/object_spot02_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -129,20 +130,7 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) { static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; Vec3f pos; - // We want to do most of the same things in rando, but we're not in a cutscene and the flag for - // destroying the royal tombstone is already set. - if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) { - Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); - this->timer = 25; - pos.x = (Math_SinS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.x; - pos.y = this->dyna.actor.world.pos.y + 30.0f; - pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z; - EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30); - this->actionFunc = func_808ACA08; - } - - if (play->csCtx.state != 0) { - if (play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2) { + if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, play->csCtx.state != 0 && play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2, this)) { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); this->timer = 25; @@ -151,7 +139,6 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) { pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z; EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30); this->actionFunc = func_808ACA08; - } } } @@ -174,7 +161,7 @@ void func_808ACA08(BgSpot02Objects* this, PlayState* play) { // This shouldn't execute in rando even without the check since we never // enter the cutscene context. - if (play->csCtx.frames == 402 && !(IS_RANDO)) { + if (play->csCtx.frames == 402) { if (!LINK_IS_ADULT) { Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID); } else { @@ -217,13 +204,6 @@ void BgSpot02Objects_Draw(Actor* thisx, PlayState* play) { } void func_808ACC34(BgSpot02Objects* this, PlayState* play) { - // This is the actionFunc that the game settles on when you load the Graveyard - // When we're in rando and the flag for the gravestone being destroyed gets set, - // set the actionFunc to the function where the gravestone explodes. - if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) { - this->actionFunc = func_808AC908; - } - if (play->csCtx.state != 0 && play->csCtx.npcActions[0] != NULL && play->csCtx.npcActions[0]->action == 2) { this->unk_16A++; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h index 0b54fa617..cf5152a7e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h +++ b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h @@ -19,4 +19,7 @@ typedef struct BgSpot02Objects { /* 0x0172 */ u16 unk_172; } BgSpot02Objects; // size = 0x0174 +void func_808ACC34(BgSpot02Objects* bgSpot02Objects, PlayState* play); +void func_808AC908(BgSpot02Objects* bgSpot02Objects, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 74afaacff..34c094320 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -8,6 +8,7 @@ #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "scenes/overworld/spot02/spot02_scene.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -192,7 +193,7 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; - } else if (((this->type != 4) || !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME)) && + } else if (((this->type != 4) || GameInteractor_Should(GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME), this)) && ((this->type != 6) || !Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) && (this->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) { @@ -234,47 +235,30 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) { this->actionFunc = func_80ABF28C; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (!IS_RANDO || (IS_RANDO && Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) != RO_DOOROFTIME_CLOSED)) { - func_80078884(NA_SE_SY_CORRECT_CHIME); - } + func_80078884(NA_SE_SY_CORRECT_CHIME); if (this->switchFlag >= 0) { Flags_SetSwitch(play, this->switchFlag); } switch (this->type) { - case 1: + case 1: // Zora's River Waterfall Flags_SetSwitch(play, this->switchFlag); Flags_SetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN); break; - case 2: - if (!IS_RANDO) { + case 2: // Kakariko Windmill + if (GameInteractor_Should(GI_VB_PLAY_DRAIN_WELL_CS, true, this)) { play->csCtx.segment = D_80ABF9D0; gSaveContext.cutsceneTrigger = 1; - } else { - Flags_SetEventChkInf(EVENTCHKINF_DRAINED_WELL_IN_KAKARIKO); - Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); } func_800F574C(1.18921f, 0x5A); break; - case 4: - if (IS_RANDO) { - if (Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) == RO_DOOROFTIME_CLOSED && - (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_OCARINA_TIME || - !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || !CHECK_QUEST_ITEM(QUEST_GORON_RUBY) || - !CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) { - func_80078884(NA_SE_SY_OCARINA_ERROR); - break; - } else { - Flags_SetEnv(play, 2); - func_80078884(NA_SE_SY_CORRECT_CHIME); - } - } else { + case 4: // Door of Time + if (GameInteractor_Should(GI_VB_PLAY_DOOR_OF_TIME_CS, true, this)) { play->csCtx.segment = D_80ABFB40; gSaveContext.cutsceneTrigger = 1; } break; - case 6: - // Don't start the cutscene in a rando save. - if (!(IS_RANDO)) { + case 6: // Royal Family Tomb + if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, true, this)) { play->csCtx.segment = LINK_IS_ADULT ? SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_003C80) : SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_005020); gSaveContext.cutsceneTrigger = 1; @@ -311,7 +295,7 @@ void func_80ABF708(EnOkarinaTag* this, PlayState* play) { yawDiff = this->actor.yawTowardsPlayer - this->actor.world.rot.y; this->unk_15A++; if (!(this->actor.xzDistToPlayer > 120.0f)) { - if (CHECK_QUEST_ITEM(QUEST_SONG_SUN) || IS_RANDO) { + if (CHECK_QUEST_ITEM(QUEST_SONG_SUN)) { this->actor.textId = 0x5021; } yawDiffNew = ABS(yawDiff); @@ -323,23 +307,15 @@ void func_80ABF708(EnOkarinaTag* this, PlayState* play) { } } -void GivePlayerRandoRewardSunSong(EnOkarinaTag* song, PlayState* play, RandomizerCheck check) { - Flags_SetTreasure(play, 0x1F); - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, GI_LETTER_ZELDA); - GiveItemEntryFromActor(&song->actor, play, getItemEntry, 10000.0f, 100.0f); -} - void func_80ABF7CC(EnOkarinaTag* this, PlayState* play) { // "Open sesame sesame!" osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 開けゴマゴマゴマ! ☆☆☆☆☆ %d\n" VT_RST, Message_GetState(&play->msgCtx)); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - if (!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_SONG_SUN)) { + if (GameInteractor_Should(GI_VB_PLAY_SUNS_SONG_CS, !CHECK_QUEST_ITEM(QUEST_SONG_SUN), this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gSunSongGraveSunSongTeachCs); gSaveContext.cutsceneTrigger = 1; - } else if (IS_RANDO && !Flags_GetTreasure(play, 0x1F)) { - GivePlayerRandoRewardSunSong(this, play, RC_SONG_FROM_ROYAL_FAMILYS_TOMB); } this->actionFunc = func_80ABF708; } From b293cac51c756c0718c14b2869359a17049c5441 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Wed, 21 Feb 2024 15:26:11 -0600 Subject: [PATCH 108/300] Enable timesaver enhancements by default on rando --- soh/soh/Enhancements/presets.h | 12 +++ .../Enhancements/randomizer/hook_handlers.cpp | 2 +- .../Enhancements/timesaver_hook_handlers.cpp | 86 +++++++++---------- soh/soh/SohMenuBar.cpp | 66 +++++++------- 4 files changed, 89 insertions(+), 77 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 822b61c75..3cce3dd74 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -280,6 +280,18 @@ const std::vector enhancementsCvars = { "gPermanentHeartLoss", "gRemoveExplosiveLimit", "gToggleStrength", + "gTimeSavers.SkipCutscene.Intro", + "gTimeSavers.SkipCutscene.Entrances", + "gTimeSavers.SkipCutscene.Story", + "gTimeSavers.SkipCutscene.LearnSong", + "gTimeSavers.SkipCutscene.BossIntro", + "gTimeSavers.SkipCutscene.GlitchAiding", + "gTimeSavers.SkipCutscene.OnePoint", + "gTimeSavers.NoForcedDialog", + "gTimeSavers.SkipOwlInteractions", + "gTimeSavers.SkipMiscInteractions", + "gTimeSavers.DisableTitleCard", + "gTimeSavers.SkipGetItemAnimation", }; const std::vector cheatCvars = { diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index c77e537f3..9f2e2633a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -218,7 +218,7 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { } } - if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { static uint32_t updateHook; updateHook = GameInteractor::Instance->RegisterGameHook([]() { Player* player = GET_PLAYER(gPlayState); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 08608b8ed..27d10c00e 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -102,12 +102,12 @@ void TimeSaverOnGameFrameUpdateHandler() { void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { case GI_VB_PLAY_TRANSITION_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.cutsceneIndex = 0; *should = false; } - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { // Song of Time if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) { gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_16; @@ -144,7 +144,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } } - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { uint8_t isBlueWarp = 0; // Deku Tree Blue warp if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { @@ -228,13 +228,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; case GI_VB_PLAY_ENTRANCE_CS: { s32* entranceFlag = static_cast(opt); - if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { *should = false; } break; } case GI_VB_PLAY_ONEPOINT_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { s16* csId = static_cast(opt); switch (*csId) { case 4180: @@ -250,7 +250,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_PLAY_ONEPOINT_ACTOR_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { Actor* actor = static_cast(opt); switch (actor->category) { case ACTORCAT_BG: @@ -312,18 +312,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_SHOW_TITLE_CARD: - if (CVarGetInteger("gTimeSavers.DisableTitleCard", 0)) { + if (CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO)) { *should = false; } break; case GI_VB_WONDER_TALK: { - if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { *should = false; } break; } case GI_VB_NAVI_TALK: { - if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { ElfMsg* naviTalk = static_cast(opt); Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F); Actor_Kill(&naviTalk->actor); @@ -332,14 +332,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_NOT_BE_GREETED_BY_SARIA: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); *should = true; } break; case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: if ( - CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && + CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) @@ -349,7 +349,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case GI_VB_PLAY_DEKU_TREE_INTRO_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { BgTreemouth* treeMouth = static_cast(opt); Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -362,18 +362,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: case GI_VB_GIVE_ITEM_FAIRY_OCARINA: case GI_VB_GIVE_ITEM_LIGHT_ARROW: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { *should = false; } break; case GI_VB_PLAY_NABOORU_CAPTURED_CS: - if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA); *should = false; } break; case GI_VB_PLAY_PULL_MASTER_SWORD_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { // Normally, these would be done in the cutscene, but we're skipping it Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); @@ -388,7 +388,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case GI_VB_OWL_INTERACTION: { - if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) && *should) { + if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && *should) { EnOwl* enOwl = static_cast(opt); s32 owlType = (enOwl->actor.params & 0xFC0) >> 6; @@ -405,12 +405,12 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case GI_VB_PLAY_EYEDROPS_CS: case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS: case GI_VB_PLAY_DARUNIAS_JOY_CS: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; } break; case GI_VB_PLAY_ZELDAS_LULLABY_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { DemoIm* demoIm = static_cast(opt); Player* player = GET_PLAYER(gPlayState); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -421,7 +421,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* static uint32_t demoImKillHook = 0; demoImUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* actorRef) mutable { Actor* actor = static_cast(actorRef); - if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { DemoIm* demoIm = static_cast(actorRef); Player* player = GET_PLAYER(gPlayState); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -459,7 +459,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_PLAY_SARIAS_SONG_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { EnSa* enSa = static_cast(opt); enSa->actionFunc = func_80AF6B20; *should = false; @@ -473,7 +473,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_PLAY_DRAIN_WELL_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { *should = false; Flags_SetSwitch(gPlayState, 0x2); Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); @@ -482,7 +482,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case GI_VB_PLAY_SUNS_SONG_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { *should = false; Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG); // SoH [Randomizer] TODO: Increment time X amount (find out X) @@ -491,19 +491,19 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; } break; } case GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); } break; } case GI_VB_PLAY_DOOR_OF_TIME_CS: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; Flags_SetEnv(gPlayState, 2); func_80078884(NA_SE_SY_CORRECT_CHIME); @@ -526,7 +526,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case GI_VB_PLAY_BOLERO_OF_FIRE_CS: case GI_VB_PLAY_SERENADE_OF_WATER_CS: case GI_VB_PLAY_PRELUDE_OF_LIGHT_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { *should = false; } break; @@ -581,7 +581,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) { enKoUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || IS_RANDO)) { EnKo* enKo = static_cast(innerActorRef); // They haven't moved yet, wrap their update function so we check every frame if (enKo->actionFunc == func_80A995CC) { @@ -607,7 +607,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } - if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { itemOcarinaframesSinceSpawn = 0; itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); @@ -625,7 +625,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) { enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { EnMa1* enMa1 = static_cast(innerActorRef); if (enMa1->actionFunc == func_80AA106C) { enMa1->actionFunc = EnMa1_EndTeachSong; @@ -653,7 +653,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_FU) { enFuUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { EnFu* enFu = static_cast(innerActorRef); if (enFu->actionFunc == EnFu_TeachSong) { enFu->actionFunc = EnFu_EndTeachSong; @@ -676,7 +676,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { SPDLOG_INFO("Registering BG_SPOT02 hook"); bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0))) { + if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { SPDLOG_INFO("on update BG_SPOT02 hook"); BgSpot02Objects* bgSpot02 = static_cast(innerActorRef); if (bgSpot02->actionFunc == func_808ACC34) { @@ -697,7 +697,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } - if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) { + if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { EnZl4* enZl4 = static_cast(actorRef); if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; @@ -708,63 +708,63 @@ void TimeSaverOnActorInitHandler(void* actorRef) { void TimeSaverOnSceneInitHandler(int16_t sceneNum) { switch (sceneNum) { case SCENE_HYRULE_CASTLE: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); } break; case SCENE_LON_LON_RANCH: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); } break; case SCENE_DEKU_TREE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); } } break; case SCENE_DODONGOS_CAVERN_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); } } break; case SCENE_JABU_JABU_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); } } break; case SCENE_FOREST_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); } } break; case SCENE_FIRE_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); } } break; case SCENE_WATER_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); } } break; case SCENE_SPIRIT_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); @@ -773,7 +773,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { } break; case SCENE_SHADOW_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); } @@ -785,7 +785,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { - if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) return; + if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) return; switch (flagType) { case FLAG_EVENT_CHECK_INF: diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index e133a1bb0..44aa38cbe 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -576,29 +576,29 @@ void DrawEnhancementsMenu() { ImGui::Text("Speed-ups:"); UIWidgets::PaddedSeparator(); bool allChecked = - CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) && - CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) && - CVarGetInteger("gTimeSavers.NoForcedDialog", 0) && - CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) && - CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && - CVarGetInteger("gTimeSavers.DisableTitleCard", 0); + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) && + CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); bool someChecked = - CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) || - CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) || - CVarGetInteger("gTimeSavers.NoForcedDialog", 0) || - CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) || - CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) || - CVarGetInteger("gTimeSavers.DisableTitleCard", 0); + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) || + CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) || + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); ImGuiContext* g = ImGui::GetCurrentContext(); ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; @@ -632,19 +632,19 @@ void DrawEnhancementsMenu() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } g->CurrentItemFlags = backup_item_flags; - UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro"); - UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances"); - UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story"); - UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong"); - UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro"); - UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding"); + UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); - UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint"); - UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog"); + UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs"); - UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions"); - UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions"); - UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard"); + UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedText("Skip Get Item Animations", true, false); UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED); From 13a113c36233e61554b297736b3df88885e739b7 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 23 Feb 2024 12:43:27 -0600 Subject: [PATCH 109/300] Various adjustments to goron related vanilla behavior hooks --- .../game-interactor/GameInteractor.h | 14 +- .../Enhancements/randomizer/hook_handlers.cpp | 82 +++------ soh/soh/Enhancements/randomizer/location.h | 8 +- .../Enhancements/randomizer/location_list.cpp | 8 +- .../Enhancements/randomizer/randomizer_inf.h | 2 - .../Enhancements/timesaver_hook_handlers.cpp | 11 ++ soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 1 - soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 160 +++++++----------- 8 files changed, 101 insertions(+), 185 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 453055da4..380454e01 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -201,8 +201,8 @@ typedef enum { // Opt: *uint16_t // Vanilla condition: false GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, - // Opt: *EnGo2 - GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, + // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON) + GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, // Opt: *EnSyatekiMan // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, @@ -273,9 +273,7 @@ typedef enum { // Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, // Opt: *EnGo2 - GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD, - // Opt: *EnGo2 - GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT, + GI_VB_GIVE_ITEM_FROM_GORON, // Opt: *EnJs GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, // Opt: *EnGm @@ -333,16 +331,10 @@ typedef enum { GI_VB_TRADE_ODD_POTION, // Opt: *EnToryo GI_VB_TRADE_SAW, - // Opt: *EnGo2 - GI_VB_TRADE_BROKEN_SWORD, // Opt: *EnKz, GI_VB_TRADE_PRESCRIPTION, // Opt: *EnMk GI_VB_TRADE_FROG, - // Opt: *EnGo2 - GI_VB_TRADE_EYEDROPS, - // Opt: *EnGo2 - GI_VB_TRADE_CLAIM_CHECK, GI_VB_TRADE_TIMER_ODD_MUSHROOM, GI_VB_TRADE_TIMER_EYEDROPS, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 9f2e2633a..35031690e 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -34,6 +34,7 @@ extern PlayState* gPlayState; RandomizerCheck GetRandomizerCheckFromFlag(int16_t flagType, int16_t flag) { for (auto& loc : Rando::StaticData::GetLocationTable()) { if (loc.GetCollectionCheck().flag == flag && ( + (flagType == FLAG_INF_TABLE && loc.GetCollectionCheck().type == SPOILER_CHK_INF_TABLE) || (flagType == FLAG_EVENT_CHECK_INF && loc.GetCollectionCheck().type == SPOILER_CHK_EVENT_CHK_INF) || (flagType == FLAG_ITEM_GET_INF && loc.GetCollectionCheck().type == SPOILER_CHK_ITEM_GET_INF) || (flagType == FLAG_RANDOMIZER_INF && loc.GetCollectionCheck().type == SPOILER_CHK_RANDOMIZER_INF) @@ -104,6 +105,18 @@ static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE; void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { + // Consume adult trade items + if (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && flagType == FLAG_RANDOMIZER_INF) { + switch (flag) { + case RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD: + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SWORD_BROKEN); + break; + case RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS: + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_EYEDROPS); + break; + } + } + RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag); if (rc == RC_UNKNOWN_CHECK) return; @@ -453,8 +466,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void break; } case GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE: { - - *should = INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK && Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + // This being true will prevent other biggoron trades, there are already safegaurds in place to prevent + // claim check from being traded multiple times, so we don't really need the quest to ever be considered "complete" + *should = false; break; } case GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { @@ -465,46 +479,8 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); break; } - case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { - u16* textId = static_cast(optionalArg); - *should = true; - - // For rando, prioritize opening the doors in GC when Link the goron has been stopped when - // the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved - if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { - *textId = 0x3030; - } else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { - *textId = 0x3036; - } else if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { - *textId = 0x3041; - } else { - *textId = Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; - } - break; - } - case GI_VB_EN_GO2_RESET_AFTER_GET_ITEM: { - EnGo2* enGo2 = static_cast(optionalArg); - // For randomizer, handle updating the states for the gorons after receiving the item based on - // the goron type rather then the item being received - switch (enGo2->actor.params & 0x1F) { - case GORON_DMT_BIGGORON: - // Resolves #1301. unk_13EE is used to set the opacity of the HUD. The trade sequence discussion - // with Biggoron sets the HUD to transparent, and it is restored at z_message_PAL:3549, but by - // specifically watching for trade sequence items, this leaves it transparent for non-trade sequence - // items (in rando) so we fix that here - gSaveContext.unk_13EE = 0x32; - break; - case GORON_CITY_LINK: - EnGo2_GetItemAnimation(enGo2, gPlayState); - break; - case GORON_CITY_ROLLING_BIG: - EnGo2_RollingAnimation(enGo2, gPlayState); - enGo2->actionFunc = (EnGo2ActionFunc)EnGo2_GoronRollingBigContinueRolling; - break; - default: - enGo2->actionFunc = func_80A46B40; - break; - } + case GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED: { + *should = Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); break; } case GI_VB_GIVE_ITEM_FROM_ITEM_00: { @@ -589,15 +565,6 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT: { - EnGo2* enGo2 = static_cast(optionalArg); - *should = false; - if (!Flags_GetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT)) { - Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); - enGo2->interactInfo.talkState = NPC_TALK_STATE_ACTION; - } - break; - } case GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN: { *should = RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_OFF || // If the rando check has already been awarded, use vanilla behavior. @@ -695,16 +662,6 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_TRADE_BROKEN_SWORD: { - Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SWORD_BROKEN); - *should = false; - break; - } - case GI_VB_TRADE_EYEDROPS: { - Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_EYEDROPS); - *should = false; - break; - } case GI_VB_DESPAWN_HORSE_RACE_COW: { if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { break; @@ -806,12 +763,11 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = eligible; break; } - case GI_VB_TRADE_CLAIM_CHECK: case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: - case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD: + case GI_VB_GIVE_ITEM_FROM_GORON: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: case GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF: diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index fcea02eb4..ad3142cae 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -16,10 +16,10 @@ class SpoilerCollectionCheck { public: SpoilerCollectionCheckType type = SPOILER_CHK_NONE; uint8_t scene = 0; - uint8_t flag = 0; + uint16_t flag = 0; SpoilerCollectionCheck() = default; - SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint8_t flag_) + SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint16_t flag_) : type(type_), scene(scene_), flag(flag_) { } @@ -39,8 +39,8 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag); } - static auto InfTable(const uint8_t offset, const uint8_t bit) { - return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, offset, bit); + static auto InfTable(const uint16_t flag) { + return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, 0xFF, flag); } static auto Collectable(const uint8_t scene, const uint8_t flag) { diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 8deeab8c8..c375f6bea 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -651,7 +651,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_190), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // RandoTodo: Do we replace these with the RC_HIDEOUT keys or keep these? locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); @@ -671,7 +671,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_191), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); @@ -719,8 +719,8 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ROLLING_GORON_AS_CHILD), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(INFTABLE_11E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DARUNIAS_JOY), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 31ca0a805..a66827de6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -274,8 +274,6 @@ typedef enum { RAND_INF_LEARNED_EPONA_SONG, RAND_INF_DARUNIAS_JOY, RAND_INF_KING_ZORA_THAWED, - RAND_INF_ROLLING_GORON_AS_CHILD, - RAND_INF_ROLLING_GORON_AS_ADULT, // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 27d10c00e..84b619ebe 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -401,6 +401,17 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + u16* textId = static_cast(opt); + // If the doors are not open yet, prioritize opening them + if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { + *textId = 0x3036; + *should = true; + } + } + break; + } case GI_VB_PLAY_EYEDROP_CREATION_ANIM: case GI_VB_PLAY_EYEDROPS_CS: case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS: diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 7dc67f427..3ec88fb74 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -971,7 +971,6 @@ void EnGo_GetItem(EnGo* this, PlayState* play) { if ((this->actor.params & 0xF0) == 0) { getItemId = GI_TUNIC_GORON; - Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT); } yDist = fabsf(this->actor.yDistToPlayer) + 1.0f; diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 86d1b488a..783ada21a 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -142,7 +142,6 @@ typedef enum { /* 10 */ ENGO2_ANIM_10, /* 11 */ ENGO2_ANIM_11, /* 12 */ ENGO2_ANIM_12, - /* 13 */ ENGO2_ANIM_13, // Added to fix spinning goron issue for biggoron } EnGo2Animation; static AnimationInfo sAnimationInfo[] = { @@ -152,7 +151,7 @@ static AnimationInfo sAnimationInfo[] = { { &gGoronAnim_002D80, 1.0f, 0.0f, -1.0f, 0x02, -8.0f }, { &gGoronAnim_00161C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_001A00, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_0021D0, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_004930, 0.0f, 0.0f, -1.0f, 0x01, -8.0f }, { &gGoronAnim_000750, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, - { &gGoronAnim_000D5C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_004930, 0.0f, 1.0f, -1.0f, 0x01, 0.0f }, + { &gGoronAnim_000D5C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, }; static EnGo2DustEffectData sDustEffectData[2][4] = { @@ -284,15 +283,10 @@ s32 EnGo2_SpawnDust(EnGo2* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 void EnGo2_GetItem(EnGo2* this, PlayState* play, s32 getItemId) { this->getItemId = getItemId; - func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); -} - -void EnGo2_GetItemEntry(EnGo2* this, PlayState* play, GetItemEntry getItemEntry) { - this->getItemId = getItemEntry.getItemId; - this->getItemEntry = getItemEntry; - GiveItemEntryFromActor(&this->actor, play, getItemEntry, this->actor.xzDistToPlayer + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, this)) { + func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); + } } s32 EnGo2_GetDialogState(EnGo2* this, PlayState* play) { @@ -335,7 +329,7 @@ u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) { u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Flags_GetInfTable(INFTABLE_11E)) { return 0x3013; - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 2, this) + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 20, this) && this->waypoint > 7 && this->waypoint < 12) { return 0x3012; } else { @@ -351,14 +345,9 @@ s16 EnGo2_UpdateTalkStateGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Message_ShouldAdvance(play)) { if (this->actor.textId == 0x3012) { this->actionFunc = EnGo2_SetupGetItem; - if(GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD, true, this)) { - EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30); - } else { - this->actionFunc = EnGo2_SetGetItem; - } + EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30); Message_CloseTextbox(play); Flags_SetInfTable(INFTABLE_11E); - Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_CHILD); return NPC_TALK_STATE_ACTION; } else { return NPC_TALK_STATE_ACTION; @@ -511,9 +500,9 @@ u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) { return overrideTextId; } - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL)) { return Flags_GetInfTable(INFTABLE_10F) ? 0x3042 : 0x3041; - } else if (CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL)) { return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; } else if (Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { this->unk_20C = 0; @@ -529,16 +518,9 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { case TEXT_STATE_CLOSING: switch (this->actor.textId) { case 0x3036: - Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT); - this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT, true, this)) { - EnGo2_GetItem(this, play, GI_TUNIC_GORON); - this->actionFunc = EnGo2_SetupGetItem; - return NPC_TALK_STATE_ACTION; - } else { - this->actionFunc = EnGo2_SetGetItem; - return this->interactInfo.talkState; - } + EnGo2_GetItem(this, play, GI_TUNIC_GORON); + this->actionFunc = EnGo2_SetupGetItem; + return NPC_TALK_STATE_ACTION; case 0x3037: Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK); default: @@ -608,18 +590,14 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { switch (EnGo2_GetDialogState(this, play)) { case TEXT_STATE_DONE: if (this->actor.textId == 0x305E) { - if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { - return NPC_TALK_STATE_IDLE; - } - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); - if (GameInteractor_Should(GI_VB_TRADE_CLAIM_CHECK, true, this)) { + if (!GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); EnGo2_GetItem(this, play, GI_SWORD_BGS); this->actionFunc = EnGo2_SetupGetItem; + return NPC_TALK_STATE_ACTION; } else { - this->actionFunc = EnGo2_SetGetItem; + return NPC_TALK_STATE_IDLE; } - - return NPC_TALK_STATE_ACTION; } else { return NPC_TALK_STATE_IDLE; } @@ -645,12 +623,8 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) { if (play->msgCtx.choiceIndex == 0) { Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD); - if (GameInteractor_Should(GI_VB_TRADE_BROKEN_SWORD, true, this)) { - EnGo2_GetItem(this, play, GI_PRESCRIPTION); - this->actionFunc = EnGo2_SetupGetItem; - } else { - this->actionFunc = EnGo2_SetGetItem; - } + EnGo2_GetItem(this, play, GI_PRESCRIPTION); + this->actionFunc = EnGo2_SetupGetItem; return NPC_TALK_STATE_ACTION; } this->actor.textId = 0x3056; @@ -1056,7 +1030,10 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { } player->actor.textId = this->actor.textId; - } else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { + } else if ( + !GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL) && + (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) + ) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x305E; @@ -1193,8 +1170,10 @@ s32 EnGo2_IsCameraModified(EnGo2* this, PlayState* play) { (this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON || (this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) { return true; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + } else if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { return true; } else { return false; @@ -1251,8 +1230,10 @@ void EnGo2_SelectGoronWakingUp(EnGo2* this) { EnGo2_BiggoronWakingUp(this); break; case GORON_CITY_LINK: - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { EnGo2_WakingUp(this); break; } @@ -1349,25 +1330,10 @@ void EnGo2_WakeUp(EnGo2* this, PlayState* play) { } if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { OnePointCutscene_Init(play, 4200, -99, &this->actor, MAIN_CAM); - // There is an issue interpolating between ENGO2_ANIM_0 and ENGO2_ANIM_1/10, the goron - // is technically in the same position at the end of ANIM_0 and beginning of ANIM_1/10 - // but something isn't getting translated correctly causing the 360 degree spin before - // then continuing the wake up animation like normal. One solution is to use ANIM_0 - // which uses the same frame data as ANIM_1/10 but no morph frames, but only when the - // current animation frame is at 0, meaning no morphing is necessary anyway. - // ANIM_13 is ANIM_0 but with the startFrame and mode adjusted for biggoron. - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_13); - } else { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10); - } + Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10); this->skelAnime.playSpeed = 0.5f; } else { - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_0); - } else { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1); - } + Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1); this->skelAnime.playSpeed = 1.0f; } this->actionFunc = func_80A46B40; @@ -1589,14 +1555,13 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { this->unk_216 = this->actor.shape.rot.z; this->trackingMode = NPC_TRACKING_NONE; this->path = Path_GetByIndex(play, (this->actor.params & 0x3E0) >> 5, 0x1F); - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; switch (this->actor.params & 0x1F) { case GORON_CITY_ENTRANCE: case GORON_CITY_ISLAND: case GORON_CITY_LOWEST_FLOOR: case GORON_CITY_STAIRWELL: case GORON_CITY_LOST_WOODS: - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (!GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { Actor_Kill(&this->actor); } this->actionFunc = EnGo2_CurledUp; @@ -1611,8 +1576,10 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { if ((Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED))) { Path_CopyLastPoint(this->path, &this->actor.world.pos); this->actor.home.pos = this->actor.world.pos; - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { EnGo2_GetItemAnimation(this, play); } else { this->actionFunc = EnGo2_CurledUp; @@ -1828,7 +1795,7 @@ void EnGo2_ReverseRolling(EnGo2* this, PlayState* play) { } void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGo2_SetGetItem; } else { @@ -1837,30 +1804,29 @@ void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { } void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - - if (GameInteractor_Should(GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, true, this)) { - switch (this->getItemId) { - case GI_CLAIM_CHECK: - Environment_ClearBgsDayCount(); - EnGo2_GetItemAnimation(this, play); - return; - case GI_TUNIC_GORON: - Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); - EnGo2_GetItemAnimation(this, play); - return; - case GI_SWORD_BGS: + switch (this->getItemId) { + case GI_CLAIM_CHECK: + Environment_ClearBgsDayCount(); + EnGo2_GetItemAnimation(this, play); + return; + case GI_TUNIC_GORON: + Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); + EnGo2_GetItemAnimation(this, play); + return; + case GI_SWORD_BGS: + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { gSaveContext.bgsFlag = true; - break; - case GI_BOMB_BAG_30: - case GI_BOMB_BAG_40: - EnGo2_RollingAnimation(this, play); - this->actionFunc = EnGo2_GoronRollingBigContinueRolling; - return; - } - this->actionFunc = func_80A46B40; + } + break; + case GI_BOMB_BAG_30: + case GI_BOMB_BAG_40: + EnGo2_RollingAnimation(this, play); + this->actionFunc = EnGo2_GoronRollingBigContinueRolling; + return; } + this->actionFunc = func_80A46B40; } } @@ -1905,15 +1871,9 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->trackingMode = NPC_TRACKING_HEAD_AND_TORSO; this->skelAnime.playSpeed = 0.0f; this->skelAnime.curFrame = this->skelAnime.endFrame; - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS); - if(GameInteractor_Should(GI_VB_TRADE_EYEDROPS, true, this)) { - u32 getItemId = GI_CLAIM_CHECK; - EnGo2_GetItem(this, play, getItemId); - this->actionFunc = EnGo2_SetupGetItem; - } else { - this->actionFunc = EnGo2_SetGetItem; - } + EnGo2_GetItem(this, play, GI_CLAIM_CHECK); + this->actionFunc = EnGo2_SetupGetItem; this->goronState = 0; } break; From 09c967249f8c49cfae85dbafa5778e2226a9d94a Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 23 Feb 2024 14:06:27 -0600 Subject: [PATCH 110/300] More 1PC skips --- .../Enhancements/timesaver_hook_handlers.cpp | 29 +++++++++++-------- .../ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h | 3 ++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 84b619ebe..84d95d7f0 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -20,6 +20,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" +#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -88,7 +89,8 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { static int successChimeCooldown = 0; void RateLimitedSuccessChime() { if (successChimeCooldown == 0) { - func_80078884(NA_SE_SY_CORRECT_CHIME); + // Currently disabled, need to find a better way to do this, while being consistent with vanilla + // func_80078884(NA_SE_SY_CORRECT_CHIME); successChimeCooldown = 120; } } @@ -282,25 +284,31 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* RateLimitedSuccessChime(); break; } - // case ACTOR_PLAYER: // This might cause issues + case ACTOR_BG_HIDAN_KOUSI: { + BgHidanKousi* switchActor = static_cast(opt); + BgHidanKousi_SetupAction(switchActor, func_80889C18); + *should = false; + RateLimitedSuccessChime(); + break; + } + case ACTOR_BG_HIDAN_FWBIG: { + *should = false; + break; + } case ACTOR_EN_TA: case ACTOR_DOOR_SHUTTER: + case ACTOR_BG_ICE_SHUTTER: + case ACTOR_OBJ_LIGHTSWITCH: case ACTOR_EN_BOX: case ACTOR_OBJ_SYOKUDAI: case ACTOR_OBJ_TIMEBLOCK: case ACTOR_EN_PO_SISTERS: - // Prop case ACTOR_OBJ_ICE_POLY: case ACTOR_BG_YDAN_MARUTA: case ACTOR_BG_SPOT18_SHUTTER: case ACTOR_BG_SPOT05_SOKO: case ACTOR_BG_SPOT18_BASKET: - // BG - // case ACTOR_BG_YDAN_SP: - // case ACTOR_BG_YDAN_HASI: - // case ACTOR_BG_DODOAGO: - // case ACTOR_BG_DDAN_KD: - // case ACTOR_BG_DDAN_JD: + case ACTOR_BG_HIDAN_CURTAIN: *should = false; RateLimitedSuccessChime(); break; @@ -684,14 +692,11 @@ void TimeSaverOnActorInitHandler(void* actorRef) { } if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) { - SPDLOG_INFO("Registering BG_SPOT02 hook"); bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { - SPDLOG_INFO("on update BG_SPOT02 hook"); BgSpot02Objects* bgSpot02 = static_cast(innerActorRef); if (bgSpot02->actionFunc == func_808ACC34) { - SPDLOG_INFO("BGspot02 OVERRIDDEN"); bgSpot02->actionFunc = func_808AC908; GameInteractor::Instance->UnregisterGameHook(bgSpot02UpdateHook); GameInteractor::Instance->UnregisterGameHook(bgSpot02KillHook); diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h b/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h index fff8c4c53..1f3eb4161 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h @@ -14,4 +14,7 @@ typedef struct BgHidanKousi { /* 0x0168 */ s16 unk_168; } BgHidanKousi; // size = 0x016C +void BgHidanKousi_SetupAction(BgHidanKousi* bgHidanKousi, BgHidanKousiActionFunc actionFunc); +void func_80889C18(BgHidanKousi* bgHidanKousi, PlayState* play); + #endif From 416ed84bc689fecc1e1b2e62cf7b3353a9711977 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 24 Feb 2024 09:17:48 -0600 Subject: [PATCH 111/300] Migrate great fairy checks --- soh/include/z64save.h | 2 +- .../Enhancements/debugger/debugSaveEditor.h | 8 +++ .../game-interactor/GameInteractor.h | 3 + soh/soh/Enhancements/randomizer/location.h | 2 +- .../Enhancements/randomizer/location_list.cpp | 12 ++-- .../Enhancements/randomizer/randomizer_inf.h | 7 +++ .../Enhancements/timesaver_hook_handlers.cpp | 60 +++++++++++++++++++ .../ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c | 38 ++++-------- .../actors/ovl_En_Ex_Item/z_en_ex_item.h | 2 +- 9 files changed, 97 insertions(+), 37 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 0f527925d..617c2acf5 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -283,7 +283,7 @@ typedef struct { // #endregion // #region SOH [Randomizer] // Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer - /* */ u16 randomizerInf[16]; + /* */ u16 randomizerInf[17]; /* */ u8 mqDungeonCount; /* */ u16 adultTradeItems; /* */ u8 triforcePiecesCollected; diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 5a4618dac..ff9f9bf8f 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -612,6 +612,14 @@ const std::vector flagTables = { { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, { RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" }, { RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" }, + { RAND_INF_KING_ZORA_THAWED, "RAND_INF_KING_ZORA_THAWED" }, + + { RAND_INF_HC_GREAT_FAIRY_REWARD, "RAND_INF_HC_GREAT_FAIRY_REWARD" }, + { RAND_INF_DMT_GREAT_FAIRY_REWARD, "RAND_INF_DMT_GREAT_FAIRY_REWARD" }, + { RAND_INF_DMC_GREAT_FAIRY_REWARD, "RAND_INF_DMC_GREAT_FAIRY_REWARD" }, + { RAND_INF_ZF_GREAT_FAIRY_REWARD, "RAND_INF_ZF_GREAT_FAIRY_REWARD" }, + { RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, "RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD" }, + { RAND_INF_OGC_GREAT_FAIRY_REWARD, "RAND_INF_OGC_GREAT_FAIRY_REWARD" }, } }, }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 380454e01..478f82712 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -209,6 +209,9 @@ typedef enum { // Opt: *EnOkarinaTag // Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME) GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, + // Opt: *BgDyYoseizo + // Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c + GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, /*** Play Cutscenes ***/ diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index ad3142cae..a962e4501 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -79,7 +79,7 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00); } - static auto RandomizerInf(const uint8_t flag) { + static auto RandomizerInf(const uint16_t flag) { return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, 0x00, flag); } }; diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index c375f6bea..c58674bae 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1297,12 +1297,12 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::EventChkInf(0x45), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::EventChkInf(0xC4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::Chest(0x3D, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x02), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x03), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x02), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::Chest(0x3B, 0x03), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_OGC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); // Songs locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index a66827de6..67b396d74 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -274,6 +274,13 @@ typedef enum { RAND_INF_LEARNED_EPONA_SONG, RAND_INF_DARUNIAS_JOY, RAND_INF_KING_ZORA_THAWED, + + RAND_INF_HC_GREAT_FAIRY_REWARD, + RAND_INF_DMT_GREAT_FAIRY_REWARD, + RAND_INF_DMC_GREAT_FAIRY_REWARD, + RAND_INF_ZF_GREAT_FAIRY_REWARD, + RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, + RAND_INF_OGC_GREAT_FAIRY_REWARD, // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 84d95d7f0..ba432796b 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -21,6 +21,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" +#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -581,6 +582,47 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case GI_VB_BIGGORON_CONSIDER_SWORD_FORGED: *should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3); break; + case GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD: { + BgDyYoseizo* bgDyYoseizo = static_cast(opt); + RandomizerInf flag = RAND_INF_MAX; + + if (gPlayState->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS) { + switch (bgDyYoseizo->fountainType) { + case 0: + flag = RAND_INF_ZF_GREAT_FAIRY_REWARD; + break; + case 1: + flag = RAND_INF_HC_GREAT_FAIRY_REWARD; + break; + case 2: + flag = RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD; + break; + } + } else { + switch (bgDyYoseizo->fountainType) { + case 0: + flag = RAND_INF_DMT_GREAT_FAIRY_REWARD; + break; + case 1: + flag = RAND_INF_DMC_GREAT_FAIRY_REWARD; + break; + case 2: + flag = RAND_INF_OGC_GREAT_FAIRY_REWARD; + break; + } + } + + if (flag != RAND_INF_MAX && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (IS_RANDO || *should) { + Flags_SetRandomizerInf(flag); + gSaveContext.healthAccumulator = 0x140; + Magic_Fill(gPlayState); + } + *should = false; + } + + break; + } } } @@ -879,6 +921,24 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE: vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy(); break; + case RAND_INF_ZF_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FARORES_WIND).GetGIEntry_Copy(); + break; + case RAND_INF_HC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DINS_FIRE).GetGIEntry_Copy(); + break; + case RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NAYRUS_LOVE).GetGIEntry_Copy(); + break; + case RAND_INF_DMT_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_SINGLE).GetGIEntry_Copy(); + break; + case RAND_INF_DMC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_DOUBLE).GetGIEntry_Copy(); + break; + case RAND_INF_OGC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DOUBLE_DEFENSE).GetGIEntry_Copy(); + break; } break; } diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index e8b2be4df..542711f81 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -11,6 +11,7 @@ #include "scenes/indoors/yousei_izumi_yoko/yousei_izumi_yoko_scene.h" #include "scenes/indoors/daiyousei_izumi/daiyousei_izumi_scene.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -68,19 +69,6 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = { NULL, }; -void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, PlayState* play) { - Player* player = GET_PLAYER(play); - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->fountainType + 1, GI_NONE); - - if (this->actor.parent == GET_PLAYER(play) && !Flags_GetTreasure(play, this->fountainType + 1) && - !Player_InBlockingCsMode(play, GET_PLAYER(play))) { - Flags_SetTreasure(play, this->fountainType + 1); - Actor_Kill(&this->actor); - } else if (!Flags_GetTreasure(play, this->fountainType + 1)) { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f); - } -} - void BgDyYoseizo_Init(Actor* thisx, PlayState* play2) { PlayState* play = play2; BgDyYoseizo* this = (BgDyYoseizo*)thisx; @@ -196,31 +184,25 @@ void BgDyYoseizo_Bob(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { + u8 isEligible = true; if (Flags_GetSwitch(play, 0x38)) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; - if(IS_RANDO) { - gSaveContext.healthAccumulator = 0x140; - Magic_Fill(play); - if(Flags_GetTreasure(play, this->fountainType + 1)) { - Actor_Kill(&this->actor); - } else { - GivePlayerRandoRewardGreatFairy(this, play); - } - return; - } - if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { if (!gSaveContext.isMagicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) { - Actor_Kill(&this->actor); - return; + isEligible = false; } } else { if (!gSaveContext.isMagicAcquired) { - Actor_Kill(&this->actor); - return; + isEligible = false; } } + + if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) { + Actor_Kill(&this->actor); + return; + } + func_8002DF54(play, &this->actor, 1); this->actionFunc = BgDyYoseizo_ChooseType; } diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h index 34a880c22..d014e19be 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h @@ -6,7 +6,7 @@ struct EnExItem; -typedef void (*EnExItemActionFunc)(struct EnExItem* this, PlayState* play); +typedef void (*EnExItemActionFunc)(struct EnExItem* enExItem, PlayState* play); typedef void (*EnExItemLightFunc)(Actor*, PlayState*, s32); typedef struct EnExItem { From ea1ffdd041651e3cf7caca70459891ff38465156 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 28 Feb 2024 19:04:44 -0700 Subject: [PATCH 112/300] Adds messageboxes to `no_ui` handling so they don't show if you have it on. (#3977) --- soh/src/code/z_message_PAL.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 7bb3803fc..87cff43da 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -8,6 +8,7 @@ #include "textures/message_static/message_static.h" #include "textures/message_texture_static/message_texture_static.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/OTRGlobals.h" @@ -3069,7 +3070,9 @@ void Message_Draw(PlayState* play) { POLY_OPA_DISP = plusOne; } plusOne = Graph_GfxPlusOne(polyOpaP = POLY_OPA_DISP); - gSPDisplayList(OVERLAY_DISP++, plusOne); + if (!GameInteractor_NoUIActive()) { + gSPDisplayList(OVERLAY_DISP++, plusOne); + } Message_DrawMain(play, &plusOne); gSPEndDisplayList(plusOne++); Graph_BranchDlist(polyOpaP, plusOne); From 358dd47da7542efdc4fa7f768a4b1fe9be350368 Mon Sep 17 00:00:00 2001 From: Archez Date: Wed, 28 Feb 2024 22:03:08 -0500 Subject: [PATCH 113/300] remove zapd extraction from mac launch script (#3981) --- soh/macosx/soh-macos.sh.in | 234 ------------------------------------- 1 file changed, 234 deletions(-) diff --git a/soh/macosx/soh-macos.sh.in b/soh/macosx/soh-macos.sh.in index 0983f63b1..217496cf1 100755 --- a/soh/macosx/soh-macos.sh.in +++ b/soh/macosx/soh-macos.sh.in @@ -7,68 +7,6 @@ export RESPATH="${SNAME%/MacOS*}/Resources" export LIBPATH="${SNAME%/MacOS*}/Frameworks" export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH" -remap_hashes () -{ - # Remap v64 and n64 hashes to their z64 hash equivalent - # ZAPD will handle converting the data into z64 format - case "$ROMHASH" in - a9059b56e761c9034fbe02fe4c24985aaa835dac) # v64 - ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099 - ;; - 24708102dc504d3f375a37f4ae4e149c167dc515) # n64 - ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099 - ;; - 580dd0bd1b6d2c51cc20a764eece84dba558964c) # v64 - ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4 - ;; - d6342c59007e57c1194661ec6880b2f078403f4e) # n64 - ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4 - ;; - d0bdc2eb320668b4ba6893b9aefe4040a73123ff) # v64 - ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5 - ;; - 4946ab250f6ac9b32d76b21f309ebb8ebc8103d2) # n64 - ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5 - ;; - 663c34f1b2c05a09e5beffe4d0dcd440f7d49dc7) # v64 - ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012 - ;; - 24c73d378b0620a380ce5ef9f2b186c6c157a68b) # n64 - ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012 - ;; - 8ebf2e29313f44f2d49e5b4191971d09919e8e48) # v64 - ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2 - ;; - 4264bf7b875737b8fae77d52322a5099d051fc11) # n64 - ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2 - ;; - 973bc6fe56010a8d646166a1182a81b4f13b8cf9) # v64 - ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03 - ;; - d327752c46edc70ff3668b9514083dbbee08927c) # v64 - ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03 - ;; - ecdeb1747560834e079c22243febea7f6f26ba3b) # v64 - ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da - ;; - f19f8662ec7abee29484a272a6fda53e39efe0f1) # n64 - ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da - ;; - ab519ce04a33818ce2c39b3c514a751d807a494a) # v64 - ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6 - ;; - c19a34f7646305e1755249fca2071e178bd7cd00) # n64 - ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6 - ;; - 25e8ae79ea0839ca5c984473f7460d8040c36f9c) # v64 - ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f - ;; - 166c02770d67fcc3954c443eb400a6a3573d3fc0) # n64 - ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f - ;; - esac -} - if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi if [ ! -e "$SHIP_HOME"/mods ]; then @@ -76,178 +14,6 @@ if [ ! -e "$SHIP_HOME"/mods ]; then touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt fi -# If either OTR doesn't exist kick off the OTR gen process -if [ ! -e "$SHIP_HOME"/oot.otr ] || [ ! -e "$SHIP_HOME"/oot-mq.otr ]; then - - # If no ROMs exist kick off the file selection prompts - while [ ! -e "$SHIP_HOME"/*.*64 ] && [ ! -e "$SHIP_HOME"/oot*.otr ]; do - - SHOULD_PROMPT_FOR_ROM=1 - while [ $SHOULD_PROMPT_FOR_ROM -eq 1 ]; do - SHOULD_PROMPT_FOR_ROM=0 - # Use osascript to prompt the user to chose a file - DROPROM=`osascript <<-EOF - set romFile to choose file of type {"b64","n64","v64","z64"} with prompt "Please select your ROM:" - return POSIX path of romFile - EOF` - - # If no rom was selected, the user cancelled, so exit - if [[ -z $DROPROM ]] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then - echo "No ROM selected. Exiting..." - exit 1 - elif [[ -z $DROPROM ]]; then - break; - fi - - # If an invalid rom was selected, let the user know and ask to try again - ROMHASH="$(shasum "$DROPROM" | awk '{ print $1 }')" - - remap_hashes - - case "$ROMHASH" in - cee6bc3c2a634b41728f2af8da54d9bf8cc14099) - ROM_TYPE=0;; - 0227d7c0074f2d0ac935631990da8ec5914597b4) - ROM_TYPE=0;; - 328a1f1beba30ce5e178f031662019eb32c5f3b5) - ROM_TYPE=0;; - cfbb98d392e4a9d39da8285d10cbef3974c2f012) - ROM_TYPE=0;; - f46239439f59a2a594ef83cf68ef65043b1bffe2) - ROM_TYPE=1;; - 50bebedad9e0f10746a52b07239e47fa6c284d03) - ROM_TYPE=1;; - 079b855b943d6ad8bd1eb026c0ed169ecbdac7da) - ROM_TYPE=1;; - cfecfdc58d650e71a200c81f033de4e6d617a9f6) - ROM_TYPE=1;; - 517bd9714c73cb96c21e7c2ef640d7b55186102f) - ROM_TYPE=1;; - *) - TRY_AGAIN_RESULT=`osascript <<-EOF - set alertText to "Incompatible ROM hash" - set alertMessage to "Incompatible ROM provided, would you like to try again?" - return display alert alertText \ - message alertMessage \ - as critical \ - buttons {"Cancel", "Try Again"} - EOF` - if [[ "$TRY_AGAIN_RESULT" == "button returned:Try Again" ]]; then - SHOULD_PROMPT_FOR_ROM=1 - continue; - else - echo "No ROM selected. Exiting..." - exit 1 - fi - esac - - cp "$DROPROM" "$SHIP_HOME" - - # Ask user if they would also like to select the other variant (MQ/Vanilla) - if [ $ROM_TYPE -eq 0 ] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then - UPLOAD_ANOTHER_RESULT=`osascript <<-EOF - set alertText to "Success" - set alertMessage to "Would you also like to provide a Master Quest ROM?" - return display alert alertText \ - message alertMessage \ - buttons {"No", "Yes"} - EOF` - elif [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then - UPLOAD_ANOTHER_RESULT=`osascript <<-EOF - set alertText to "Success" - set alertMessage to "Would you also like to provide a Vanilla (Non Master Quest) ROM?" - return display alert alertText \ - message alertMessage \ - buttons {"No", "Yes"} - EOF` - fi - - if [[ "$UPLOAD_ANOTHER_RESULT" == "button returned:Yes" ]]; then - UPLOAD_ANOTHER_RESULT="button returned:No" - SHOULD_PROMPT_FOR_ROM=1 - continue; - fi - break - done - done - - # At this point we should now have 1 or more valid roms in $SHIP_HOME directory - - # Prepare tmp dir - for ROMPATH in "$SHIP_HOME"/*.*64 - do - ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)" - export ASSETDIR - cp -r "$RESPATH/assets" "$ASSETDIR" - mkdir -p "$ASSETDIR"/tmp - cp "$ROMPATH" "$ASSETDIR"/tmp/rom.z64 - cd "$ASSETDIR" || return - - # If an invalid rom was detected, let the user know - ROMHASH="$(shasum "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')" - - remap_hashes - - case "$ROMHASH" in - cee6bc3c2a634b41728f2af8da54d9bf8cc14099) - ROM=GC_NMQ_D - OTRNAME="oot.otr";; - 0227d7c0074f2d0ac935631990da8ec5914597b4) - ROM=GC_NMQ_PAL_F - OTRNAME="oot.otr";; - 328a1f1beba30ce5e178f031662019eb32c5f3b5) - ROM=N64_PAL_10 - OTRNAME="oot.otr";; - cfbb98d392e4a9d39da8285d10cbef3974c2f012) - ROM=N64_PAL_11 - OTRNAME="oot.otr";; - f46239439f59a2a594ef83cf68ef65043b1bffe2) - ROM=GC_MQ_PAL_F - OTRNAME="oot-mq.otr";; - 50bebedad9e0f10746a52b07239e47fa6c284d03) - ROM=GC_MQ_D - OTRNAME="oot-mq.otr";; - 079b855b943d6ad8bd1eb026c0ed169ecbdac7da) - ROM=GC_MQ_D - OTRNAME="oot-mq.otr";; - cfecfdc58d650e71a200c81f033de4e6d617a9f6) - ROM=GC_MQ_D - OTRNAME="oot-mq.otr";; - 517bd9714c73cb96c21e7c2ef640d7b55186102f) - ROM=GC_MQ_D - OTRNAME="oot-mq.otr";; - *) - osascript -e 'display notification "One or more invalid ROM provided" with title "Ship Of Harkinian"' - rm -r "$ASSETDIR" - cd "$SNAME" - continue; - esac - - # Only generate OTR if we don't have on of this type yet - if [ -e "$SHIP_HOME"/"$OTRNAME" ]; then - rm -r "$ASSETDIR" - cd "$SNAME" - continue; - fi - - osascript -e 'display notification "Generating OTR..." with title "Ship Of Harkinian"' - assets/extractor/ZAPD.out ed -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR --portVer "@CMAKE_PROJECT_VERSION@" - if [ -e "$ASSETDIR"/oot.otr ]; then - osascript -e 'display notification "OTR successfully generated" with title "Ship Of Harkinian"' - cp "$ASSETDIR"/oot.otr "$SHIP_HOME"/"$OTRNAME" - rm -r "$ASSETDIR" - cd "$SNAME" - fi - done - - if [ ! -e "$SHIP_HOME"/oot*.otr ]; then - osascript -e 'display notification "OTR failed to generate" with title "Ship Of Harkinian"' - exit 1; - fi -fi - -cd "$SNAME" - arch_name="$(uname -m)" launch_arch="arm64" if [ "${arch_name}" = "x86_64" ] && [ "$(sysctl -in sysctl.proc_translated)" != "1" ]; then From b26f2b21da3768b4caca370d5b3e6165849b4478 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 28 Feb 2024 20:12:23 -0700 Subject: [PATCH 114/300] [UX Improvement] Catch save loading errors and notify user (#3979) * Add `SohModalWindow` and `SohModal`. Runs as window, always "visible", but not drawing if no popups are registered. Adds error catching for save file corruption (malformed json) that renames the file in question to prevent future loading issues and uses `SohModalWindow` to inform the user of the error. * Apply suggestions from code review --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- soh/soh/SaveManager.cpp | 100 ++++++++++++++++++++++++---------------- soh/soh/SohGui.cpp | 9 ++++ soh/soh/SohGui.hpp | 2 + soh/soh/SohModals.cpp | 54 ++++++++++++++++++++++ soh/soh/SohModals.h | 15 ++++++ 5 files changed, 139 insertions(+), 41 deletions(-) create mode 100644 soh/soh/SohModals.cpp create mode 100644 soh/soh/SohModals.h diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index e61cf9223..10d40396f 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -9,6 +9,7 @@ #include #include "soh/Enhancements/boss-rush/BossRush.h" #include +#include "SohGui.hpp" #define NOGDI // avoid various windows defines that conflict with things in z64.h #include @@ -1023,53 +1024,70 @@ void SaveManager::SaveGlobal() { output << std::setw(4) << globalBlock << std::endl; } + void SaveManager::LoadFile(int fileNum) { SPDLOG_INFO("Load File - fileNum: {}", fileNum); - assert(std::filesystem::exists(GetFileName(fileNum))); + std::filesystem::path fileName = GetFileName(fileNum); + assert(std::filesystem::exists(fileName)); InitFile(false); - std::ifstream input(GetFileName(fileNum)); - - saveBlock = nlohmann::json::object(); - input >> saveBlock; - if (!saveBlock.contains("version")) { - SPDLOG_ERROR("Save at " + GetFileName(fileNum).string() + " contains no version"); - assert(false); - } - switch (saveBlock["version"].get()) { - case 1: - for (auto& block : saveBlock["sections"].items()) { - int sectionVersion = block.value()["version"]; - std::string sectionName = block.key(); - if (!sectionLoadHandlers.contains(sectionName)) { - // Unloadable sections aren't necessarily errors, they are probably mods that were unloaded - // TODO report in a more noticeable manner - SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " + sectionName); - continue; - } - SectionLoadHandler& handler = sectionLoadHandlers[sectionName]; - if (!handler.contains(sectionVersion)) { - // A section that has a loader without a handler for the specific version means that the user has a mod - // at an earlier version than the save has. In this case, the user probably wants to load the save. - // Report the error so that the user can rectify the error. - // TODO report in a more noticeable manner - SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName + - " with an unloadable version " + std::to_string(sectionVersion)); - assert(false); - continue; - } - currentJsonContext = &block.value()["data"]; - handler[sectionVersion](); - } - break; - default: - SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get()) + " in " + - GetFileName(fileNum).string()); + std::ifstream input(fileName); + + try { + saveBlock = nlohmann::json::object(); + input >> saveBlock; + if (!saveBlock.contains("version")) { + SPDLOG_ERROR("Save at " + fileName.string() + " contains no version"); assert(false); - break; + } + switch (saveBlock["version"].get()) { + case 1: + for (auto& block : saveBlock["sections"].items()) { + int sectionVersion = block.value()["version"]; + std::string sectionName = block.key(); + if (!sectionLoadHandlers.contains(sectionName)) { + // Unloadable sections aren't necessarily errors, they are probably mods that were unloaded + // TODO report in a more noticeable manner + SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " + + sectionName); + continue; + } + SectionLoadHandler& handler = sectionLoadHandlers[sectionName]; + if (!handler.contains(sectionVersion)) { + // A section that has a loader without a handler for the specific version means that the user + // has a mod at an earlier version than the save has. In this case, the user probably wants to + // load the save. Report the error so that the user can rectify the error. + // TODO report in a more noticeable manner + SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName + + " with an unloadable version " + std::to_string(sectionVersion)); + assert(false); + continue; + } + currentJsonContext = &block.value()["data"]; + handler[sectionVersion](); + } + break; + default: + SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get()) + " in " + + GetFileName(fileNum).string()); + assert(false); + break; + } + InitMeta(fileNum); + GameInteractor::Instance->ExecuteHooks(fileNum); + } catch (const std::exception& e) { + input.close(); + std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + ".bak")); +#if defined(__SWITCH__) || defined(__WIIU__) + copy_file(fileName.c_str(), newFile.c_str()); +#else + std::filesystem::copy_file(fileName, newFile); +#endif + + std::filesystem::remove(fileName); + SohGui::RegisterPopup("Error loading save file", "A problem occurred loading the save in slot " + std::to_string(fileNum + 1) + ".\nSave file corruption is suspected.\n" + + "The file has been renamed to prevent further issues."); } - InitMeta(fileNum); - GameInteractor::Instance->ExecuteHooks(fileNum); } void SaveManager::ThreadPoolWait() { diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 94b9e690d..90f6e59e5 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -125,6 +125,7 @@ namespace SohGui { std::shared_ptr mItemTrackerSettingsWindow; std::shared_ptr mItemTrackerWindow; std::shared_ptr mRandomizerSettingsWindow; + std::shared_ptr mModalWindow; void SetupGuiElements() { auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui(); @@ -183,9 +184,13 @@ namespace SohGui { gui->AddGuiWindow(mItemTrackerSettingsWindow); mRandomizerSettingsWindow = std::make_shared("gRandomizerSettingsEnabled", "Randomizer Settings"); gui->AddGuiWindow(mRandomizerSettingsWindow); + mModalWindow = std::make_shared("gOpenWindows.modalWindowEnabled", "Modal Window"); + gui->AddGuiWindow(mModalWindow); + mModalWindow->Show(); } void Destroy() { + mModalWindow = nullptr; mRandomizerSettingsWindow = nullptr; mItemTrackerWindow = nullptr; mItemTrackerSettingsWindow = nullptr; @@ -205,4 +210,8 @@ namespace SohGui { mConsoleWindow = nullptr; mSohMenuBar = nullptr; } + + void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function button1callback, std::function button2callback) { + mModalWindow->RegisterPopup(title, message, button1, button2, button1callback, button2callback); + } } diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp index 59333fd42..dead44b51 100644 --- a/soh/soh/SohGui.hpp +++ b/soh/soh/SohGui.hpp @@ -22,6 +22,7 @@ #include "Enhancements/randomizer/randomizer_entrance_tracker.h" #include "Enhancements/randomizer/randomizer_item_tracker.h" #include "Enhancements/randomizer/randomizer_settings_window.h" +#include "SohModals.h" #ifdef __cplusplus extern "C" { @@ -37,6 +38,7 @@ namespace SohGui { void SetupGuiElements(); void Draw(); void Destroy(); + void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function button1callback = nullptr, std::function button2callback = nullptr); } #endif /* SohGui_hpp */ diff --git a/soh/soh/SohModals.cpp b/soh/soh/SohModals.cpp new file mode 100644 index 000000000..087bc8ab1 --- /dev/null +++ b/soh/soh/SohModals.cpp @@ -0,0 +1,54 @@ +#include "SohModals.h" +#include "ImGui/imgui.h" +#include +#include +#include +#include +#include "UIWidgets.hpp" +#include "OTRGlobals.h" +#include "z64.h" + +extern "C" PlayState* gPlayState; +struct SohModal { + std::string title_; + std::string message_; + std::string button1_; + std::string button2_; + std::function button1callback_; + std::function button2callback_; +}; +std::vector modals; + +void SohModalWindow::DrawElement() { + if (modals.size() > 0) { + SohModal curModal = modals.at(0); + if (!ImGui::IsPopupOpen(curModal.title_.c_str())) { + ImGui::OpenPopup(curModal.title_.c_str()); + } + if (ImGui::BeginPopupModal(curModal.title_.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { + ImGui::Text(curModal.message_.c_str()); + if (ImGui::Button(curModal.button1_.c_str())) { + if (curModal.button1callback_ != nullptr) { + curModal.button1callback_(); + } + ImGui::CloseCurrentPopup(); + modals.erase(modals.begin()); + } + ImGui::SameLine(); + if (curModal.button2_ != "") { + if (ImGui::Button(curModal.button2_.c_str())) { + if (curModal.button2callback_ != nullptr) { + curModal.button2callback_(); + } + ImGui::CloseCurrentPopup(); + modals.erase(modals.begin()); + } + } + } + ImGui::EndPopup(); + } +} + +void SohModalWindow::RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function button1callback, std::function button2callback) { + modals.push_back({ title, message, button1, button2, button1callback, button2callback }); +} \ No newline at end of file diff --git a/soh/soh/SohModals.h b/soh/soh/SohModals.h new file mode 100644 index 000000000..6f5acb2c0 --- /dev/null +++ b/soh/soh/SohModals.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "window/gui/GuiMenuBar.h" +#include "window/gui/GuiElement.h" + +class SohModalWindow : public LUS::GuiWindow { + public: + using LUS::GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; + void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function button1callback = nullptr, std::function button2callback = nullptr); +}; \ No newline at end of file From fb6ea4256072b75e6d70a24948fd2120c47e247e Mon Sep 17 00:00:00 2001 From: Archez Date: Wed, 28 Feb 2024 22:33:51 -0500 Subject: [PATCH 115/300] prevent remember save location in dungeons/boss rooms (#3983) --- .../randomizer/randomizer_entrance.c | 5 + soh/soh/SohMenuBar.cpp | 2 +- soh/src/code/z_sram.c | 117 +++++++++--------- .../ovl_file_choose/z_file_choose.c | 6 +- 4 files changed, 67 insertions(+), 63 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index e6ec3fef3..eda976473 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -398,6 +398,11 @@ void Entrance_SetSavewarpEntrance(void) { gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0 } else if (scene == SCENE_LINKS_HOUSE) { gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); + } else if (CVarGetInteger("gRememberSaveLocation", 0) && scene != SCENE_FAIRYS_FOUNTAIN && scene != SCENE_GROTTOS && + // Use the saved entrance value with remember save location, except when in grottos/fairy fountains or if + // the entrance index is -1 (new save) + gSaveContext.entranceIndex != -1) { + return; } else if (LINK_IS_CHILD) { gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn } else { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 2f654c04f..0917b0c6d 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -558,7 +558,7 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" - "This doesn't work if the save was made in a grotto."); + "This doesn't work if the save was made in grottos/fairy fountains or dungeons."); UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 1ce20abc3..0152ecf2e 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -59,65 +59,68 @@ void Sram_OpenSave() { Save_LoadFile(); - if (!CVarGetInteger("gRememberSaveLocation", 0) || gSaveContext.savedSceneNum == SCENE_FAIRYS_FOUNTAIN || - gSaveContext.savedSceneNum == SCENE_GROTTOS) { - switch (gSaveContext.savedSceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_GANONS_TOWER: - case SCENE_GERUDO_TRAINING_GROUND: - case SCENE_THIEVES_HIDEOUT: - case SCENE_INSIDE_GANONS_CASTLE: - gSaveContext.entranceIndex = dungeonEntrances[gSaveContext.savedSceneNum]; - break; - case SCENE_DEKU_TREE_BOSS: - gSaveContext.entranceIndex = 0; - break; - case SCENE_DODONGOS_CAVERN_BOSS: - gSaveContext.entranceIndex = 4; - break; - case SCENE_JABU_JABU_BOSS: - gSaveContext.entranceIndex = 0x28; - break; - case SCENE_FOREST_TEMPLE_BOSS: - gSaveContext.entranceIndex = 0x169; - break; - case SCENE_FIRE_TEMPLE_BOSS: - gSaveContext.entranceIndex = 0x165; - break; - case SCENE_WATER_TEMPLE_BOSS: - gSaveContext.entranceIndex = 0x10; - break; - case SCENE_SPIRIT_TEMPLE_BOSS: - gSaveContext.entranceIndex = 0x82; - break; - case SCENE_SHADOW_TEMPLE_BOSS: - gSaveContext.entranceIndex = 0x37; - break; - case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: - case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: - case SCENE_GANONDORF_BOSS: - case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR: - case SCENE_GANON_BOSS: - gSaveContext.entranceIndex = 0x41B; - break; + switch (gSaveContext.savedSceneNum) { + case SCENE_DEKU_TREE: + case SCENE_DODONGOS_CAVERN: + case SCENE_JABU_JABU: + case SCENE_FOREST_TEMPLE: + case SCENE_FIRE_TEMPLE: + case SCENE_WATER_TEMPLE: + case SCENE_SPIRIT_TEMPLE: + case SCENE_SHADOW_TEMPLE: + case SCENE_BOTTOM_OF_THE_WELL: + case SCENE_ICE_CAVERN: + case SCENE_GANONS_TOWER: + case SCENE_GERUDO_TRAINING_GROUND: + case SCENE_THIEVES_HIDEOUT: + case SCENE_INSIDE_GANONS_CASTLE: + gSaveContext.entranceIndex = dungeonEntrances[gSaveContext.savedSceneNum]; + break; + case SCENE_DEKU_TREE_BOSS: + gSaveContext.entranceIndex = 0; + break; + case SCENE_DODONGOS_CAVERN_BOSS: + gSaveContext.entranceIndex = 4; + break; + case SCENE_JABU_JABU_BOSS: + gSaveContext.entranceIndex = 0x28; + break; + case SCENE_FOREST_TEMPLE_BOSS: + gSaveContext.entranceIndex = 0x169; + break; + case SCENE_FIRE_TEMPLE_BOSS: + gSaveContext.entranceIndex = 0x165; + break; + case SCENE_WATER_TEMPLE_BOSS: + gSaveContext.entranceIndex = 0x10; + break; + case SCENE_SPIRIT_TEMPLE_BOSS: + gSaveContext.entranceIndex = 0x82; + break; + case SCENE_SHADOW_TEMPLE_BOSS: + gSaveContext.entranceIndex = 0x37; + break; + case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: + case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: + case SCENE_GANONDORF_BOSS: + case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR: + case SCENE_GANON_BOSS: + gSaveContext.entranceIndex = 0x41B; + break; - default: - if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) { - gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? 0xBB : 0x5F4; - } else { - gSaveContext.entranceIndex = 0xBB; - } + default: + // Use the saved entrance value with remember save location, except when in grottos/fairy fountains + if (CVarGetInteger("gRememberSaveLocation", 0) && gSaveContext.savedSceneNum != SCENE_FAIRYS_FOUNTAIN && + gSaveContext.savedSceneNum != SCENE_GROTTOS) { break; - } + } + + if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) { + gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? 0xBB : 0x5F4; + } else { + gSaveContext.entranceIndex = 0xBB; + } + break; } osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index bb8dd14d4..59b6367f9 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3036,11 +3036,7 @@ void FileChoose_LoadGame(GameState* thisx) { Entrance_Init(); // Handle randomized spawn positions after the save context has been setup from load - // When remeber save location is on, set save warp if the save was in an a grotto, or - // the entrance index is -1 from shuffle overwarld spawn - if (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && ((!CVarGetInteger("gRememberSaveLocation", 0) || - gSaveContext.savedSceneNum == SCENE_FAIRYS_FOUNTAIN || gSaveContext.savedSceneNum == SCENE_GROTTOS) || - (CVarGetInteger("gRememberSaveLocation", 0) && Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && gSaveContext.entranceIndex == -1))) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { Entrance_SetSavewarpEntrance(); } } From ed9cb1dfd257712dda6fc304b361f2c862321788 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 28 Feb 2024 20:45:16 -0700 Subject: [PATCH 116/300] Fix CVar evaluation for scummed checks being hidden. (#3985) --- soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 39418485f..b9ca97a9b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1337,7 +1337,7 @@ void DrawLocation(RandomizerCheckObject rcObj) { CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default); extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default); } else if (status == RCSHOW_SCUMMED) { - if (!showHidden && CVarGetInteger("gCheckTrackerKnownHide", 0)) { + if (!showHidden && CVarGetInteger("gCheckTrackerScummedHide", 0)) { return; } mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default) : From 368a9015ac3610f68d9ddd4d18ac0d7573788581 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 28 Feb 2024 20:46:32 -0700 Subject: [PATCH 117/300] Add Unix timestamp to renamed corrupted file to prevent trying to copy over existing file. (#3984) --- soh/soh/SaveManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 10d40396f..d8003988f 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1024,7 +1024,6 @@ void SaveManager::SaveGlobal() { output << std::setw(4) << globalBlock << std::endl; } - void SaveManager::LoadFile(int fileNum) { SPDLOG_INFO("Load File - fileNum: {}", fileNum); std::filesystem::path fileName = GetFileName(fileNum); @@ -1077,7 +1076,7 @@ void SaveManager::LoadFile(int fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } catch (const std::exception& e) { input.close(); - std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + ".bak")); + std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak")); #if defined(__SWITCH__) || defined(__WIIU__) copy_file(fileName.c_str(), newFile.c_str()); #else From 612da023f0f9da864c2830d2539e49b660ed2ff4 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 29 Feb 2024 03:46:55 +0000 Subject: [PATCH 118/300] Bump version to MacReady Foxtrot 8.0.5 (#3982) --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3b85024b..2c8644af4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(Ship VERSION 8.0.4 LANGUAGES C CXX) -set(PROJECT_BUILD_NAME "MacReady Echo" CACHE STRING "") +project(Ship VERSION 8.0.5 LANGUAGES C CXX) +set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "") set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh) From ebde648c5976f39c8f1aabcc1d0ce1190404b6f5 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sat, 2 Mar 2024 20:51:32 -0500 Subject: [PATCH 119/300] `.o2r` support (#3955) --- .github/workflows/apt-deps.txt | 2 +- .github/workflows/generate-builds.yml | 42 ++++++++++++++++++-- .github/workflows/macports-deps.txt | 2 +- .github/workflows/test-builds-on-distros.yml | 16 ++++---- CMakeLists.txt | 2 +- docs/BUILDING.md | 16 ++++---- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 9 +++-- 8 files changed, 65 insertions(+), 26 deletions(-) diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index 43286f69e..e9f7e07e1 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool ninja-build diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 582022dbd..c449585bf 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -92,14 +92,19 @@ jobs: if [ -d /opt/local/ ]; then echo "MacPorts already installed" else - wget https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg - sudo installer -pkg ./MacPorts-2.7.2-12-Monterey.pkg -target / + wget https://github.com/macports/macports-base/releases/download/v2.9.1/MacPorts-2.9.1-12-Monterey.pkg + sudo installer -pkg ./MacPorts-2.9.1-12-Monterey.pkg -target / fi echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH + - name: Update MacPorts + if: ${{ !vars.MAC_RUNNER }} + run: | + sudo port selfupdate + sudo port upgrade outdated - name: Install dependencies if: ${{ !vars.MAC_RUNNER }} run: | - brew uninstall --ignore-dependencies libpng + brew uninstall --ignore-dependencies libpng libzip sudo port install $(cat .github/workflows/macports-deps.txt) brew install ninja - name: Download soh.otr @@ -175,6 +180,21 @@ jobs: make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ + - name: Install latest libzip + if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} + run: | + sudo apt-get remove libzip-dev zipcmp zipmerge ziptool + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + if [ ! -d "libzip-1.10.1" ]; then + wget https://libzip.org/download/libzip-1.10.1.tar.gz + tar -xzvf libzip-1.10.1.tar.gz + fi + cd libzip-1.10.1 + mkdir build + cd build + cmake .. + make + sudo make install - name: Install latest SDL_net if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | @@ -224,6 +244,14 @@ jobs: sudo apt-get remove -y cmake wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir + wget https://libzip.org/download/libzip-1.10.1.tar.gz + tar -xzvf libzip-1.10.1.tar.gz + cd libzip-1.10.1 + mkdir build + cd build + cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake + make + make install - name: Fix dubious ownership error if: ${{ vars.LINUX_RUNNER }} run: git config --global --add safe.directory '*' @@ -270,6 +298,14 @@ jobs: sudo apt-get remove -y cmake wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir + wget https://libzip.org/download/libzip-1.10.1.tar.gz + tar -xzvf libzip-1.10.1.tar.gz + cd libzip-1.10.1 + mkdir build + cd build + cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake + make + make install - uses: actions/checkout@v3 with: submodules: true diff --git a/.github/workflows/macports-deps.txt b/.github/workflows/macports-deps.txt index 6f5948557..084428d16 100644 --- a/.github/workflows/macports-deps.txt +++ b/.github/workflows/macports-deps.txt @@ -1 +1 @@ -libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal +libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal \ No newline at end of file diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index fd8b3c929..190599a44 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -23,31 +23,31 @@ jobs: if: ${{ matrix.image == 'archlinux:base' }} run: | echo arch - echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost + echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost pacman -Syu --noconfirm - pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost + pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost - name: Install dependencies (dnf) if: ${{ matrix.image == 'fedora:39' }} run: | echo fedora - echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel + echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel dnf -y upgrade - dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel + dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel - name: Install dependencies (apt) if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }} run: | echo debian based - echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev + echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev apt-get update apt-get -y full-upgrade - apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev + apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev - name: Install dependencies (zypper) if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }} run: | echo openSUSE - echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel + echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools zypper --non-interactive dup - zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel + zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools - uses: actions/checkout@v3 with: submodules: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 9669c5f0c..4f1d3b225 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") set(VCPKG_TARGET_TRIPLET x64-windows-static) vcpkg_bootstrap() - vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3) + vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3) if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) diff --git a/docs/BUILDING.md b/docs/BUILDING.md index eabc18ec8..d4ba07f3c 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -88,34 +88,34 @@ cd "build/x64" #### Debian/Ubuntu ```sh # using gcc -apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev +apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev # or using clang -apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev +apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev ``` #### Arch ```sh # using gcc -pacman -S gcc git cmake ninja lsb-release sdl2 libpng sdl2_net boost +pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost # or using clang -pacman -S clang git cmake ninja lsb-release sdl2 libpng sdl2_net boost +pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost ``` #### Fedora ```sh # using gcc -dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel +dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel # or using clang -dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel +dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel ``` #### openSUSE ```sh # using gcc -zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel boost +zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools # or using clang -zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel boost +zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools ``` ### Build diff --git a/libultraship b/libultraship index a516b66ce..be3a87eef 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit a516b66ce0c89fe4e33c55b1fbfbde845d0bf129 +Subproject commit be3a87eefc4b0637adf6fff1a3fa5cc9b8265196 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4d82de6bc..38fc5afd7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -265,7 +265,10 @@ OTRGlobals::OTRGlobals() { if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) { if (std::filesystem::is_directory(patchesPath)) { for (const auto& p : std::filesystem::recursive_directory_iterator(patchesPath, std::filesystem::directory_options::follow_directory_symlink)) { - if (StringHelper::IEquals(p.path().extension().string(), ".otr")) { + if (StringHelper::IEquals(p.path().extension().string(), ".otr") || + StringHelper::IEquals(p.path().extension().string(), ".mpq") || + StringHelper::IEquals(p.path().extension().string(), ".o2r") || + StringHelper::IEquals(p.path().extension().string(), ".zip")) { patchOTRs.push_back(p.path().generic_string()); } } @@ -866,7 +869,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { // Use a temporary archive instance to load the otr and read the version file auto archive = LUS::OtrArchive(otrPath); - if (archive.LoadRaw()) { + if (archive.Open()) { auto t = archive.LoadFileRaw("portVersion"); if (t != nullptr && t->IsLoaded) { auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); @@ -877,7 +880,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { version.minor = reader->ReadUInt16(); version.patch = reader->ReadUInt16(); } - archive.UnloadRaw(); + archive.Close(); } return version; From 375349e4f72ce4e4609dc88c6ff8e6a4d69d681c Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:36:23 -0500 Subject: [PATCH 120/300] Support font as resource LUS changes (#3993) --- libultraship | 2 +- soh/soh/GbiWrap.cpp | 2 -- soh/soh/OTRGlobals.cpp | 18 ------------------ soh/soh/OTRGlobals.h | 2 -- soh/soh/z_scene_otr.cpp | 11 ----------- 5 files changed, 1 insertion(+), 34 deletions(-) diff --git a/libultraship b/libultraship index be3a87eef..ec01bc798 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit be3a87eefc4b0637adf6fff1a3fa5cc9b8265196 +Subproject commit ec01bc79860c55fe3562dafb4b4cb0aa2ce50a21 diff --git a/soh/soh/GbiWrap.cpp b/soh/soh/GbiWrap.cpp index 46f4c877c..2399051f5 100644 --- a/soh/soh/GbiWrap.cpp +++ b/soh/soh/GbiWrap.cpp @@ -14,8 +14,6 @@ void OTRGetPixelDepthPrepare(float x, float y); uint16_t OTRGetPixelDepth(float x, float y); int32_t OTRGetLastScancode(); void ResourceMgr_LoadDirectory(const char* resName); -void ResourceMgr_LoadFile(const char* resName); -char* ResourceMgr_LoadFileFromDisk(const char* filePath); uint16_t ResourceMgr_LoadTexWidthByName(char* texPath); uint16_t ResourceMgr_LoadTexHeightByName(char* texPath); size_t ResourceGetTexSizeByName(const char* name); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 38fc5afd7..61f0e2b93 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1581,10 +1581,6 @@ extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { } } -extern "C" void ResourceMgr_LoadFile(const char* resName) { - LUS::Context::GetInstance()->GetResourceManager()->LoadResource(resName); -} - std::shared_ptr GetResourceByNameHandlingMQ(const char* path) { std::string Path = path; if (ResourceMgr_IsGameMasterQuest()) { @@ -1606,20 +1602,6 @@ extern "C" char* GetResourceDataByNameHandlingMQ(const char* path) { return (char*)res->GetRawPointer(); } -extern "C" char* ResourceMgr_LoadFileFromDisk(const char* filePath) { - FILE* file = fopen(filePath, "r"); - fseek(file, 0, SEEK_END); - int fSize = ftell(file); - fseek(file, 0, SEEK_SET); - - char* data = (char*)malloc(fSize); - fread(data, 1, fSize, file); - - fclose(file); - - return data; -} - extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) { auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(texPath)); return res->Flags & TEX_FLAG_LOAD_AS_RAW; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index db42341c2..a4af676e0 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -95,8 +95,6 @@ uint8_t ResourceMgr_FileExists(const char* resName); uint8_t ResourceMgr_FileAltExists(const char* resName); void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName); char* GetResourceDataByNameHandlingMQ(const char* path); -void ResourceMgr_LoadFile(const char* resName); -char* ResourceMgr_LoadFileFromDisk(const char* filePath); uint8_t ResourceMgr_TexIsRaw(const char* texPath); uint8_t ResourceMgr_ResourceIsBackground(char* texPath); char* ResourceMgr_LoadJPEG(char* data, size_t dataSize); diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 3d7889807..0b9ba98f9 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -39,17 +39,6 @@ extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); extern "C" RomFile sNaviMsgFiles[]; s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene); -std::shared_ptr ResourceMgr_LoadFile(const char* path) { - std::string Path = path; - if (IsGameMasterQuest()) { - size_t pos = 0; - if ((pos = Path.find("/nonmq/", 0)) != std::string::npos) { - Path.replace(pos, 7, "/mq/"); - } - } - return LUS::Context::GetInstance()->GetResourceManager()->LoadFile(Path.c_str()); -} - // Forward Declaration of function declared in OTRGlobals.cpp std::shared_ptr GetResourceByNameHandlingMQ(const char* path); From 402a4db5934d713e71c44364846e73cb0c0f0107 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:56:26 -0500 Subject: [PATCH 121/300] Bump LUS (#3996) --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index ec01bc798..d70fd7de2 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit ec01bc79860c55fe3562dafb4b4cb0aa2ce50a21 +Subproject commit d70fd7de2315388c9a99742fd6c634b2cd8be138 From 9fb2f26f1b76e0ce7f2126e8b140448506d0ca07 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 5 Mar 2024 22:21:15 -0500 Subject: [PATCH 122/300] tts: use `RawJson` resource + add `SpeechLogger` (#3998) * moved `tts.cpp` away from using `LoadFileRaw` by creating a new `RawJson` resource type * added `SpeechLogger` --- .../speechsynthesizer/SpeechLogger.cpp | 16 +++++++++ .../speechsynthesizer/SpeechLogger.h | 17 +++++++++ .../speechsynthesizer/SpeechSynthesizer.h | 2 ++ soh/soh/Enhancements/tts/tts.cpp | 35 +++++++++---------- soh/soh/OTRGlobals.cpp | 5 +++ soh/soh/resource/importer/RawJsonFactory.cpp | 19 ++++++++++ soh/soh/resource/importer/RawJsonFactory.h | 11 ++++++ soh/soh/resource/type/RawJson.cpp | 14 ++++++++ soh/soh/resource/type/RawJson.h | 20 +++++++++++ soh/soh/resource/type/SohResourceType.h | 1 + 10 files changed, 122 insertions(+), 18 deletions(-) create mode 100644 soh/soh/Enhancements/speechsynthesizer/SpeechLogger.cpp create mode 100644 soh/soh/Enhancements/speechsynthesizer/SpeechLogger.h create mode 100644 soh/soh/resource/importer/RawJsonFactory.cpp create mode 100644 soh/soh/resource/importer/RawJsonFactory.h create mode 100644 soh/soh/resource/type/RawJson.cpp create mode 100644 soh/soh/resource/type/RawJson.h diff --git a/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.cpp b/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.cpp new file mode 100644 index 000000000..a47a61d62 --- /dev/null +++ b/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.cpp @@ -0,0 +1,16 @@ +#include "SpeechLogger.h" +#include + +SpeechLogger::SpeechLogger() { +} + +void SpeechLogger::Speak(const char* text, const char* language) { + lusprintf(__FILE__, __LINE__, 2, "Spoken Text (%s): %s", language, text); +} + +bool SpeechLogger::DoInit() { + return true; +} + +void SpeechLogger::DoUninitialize() { +} diff --git a/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.h b/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.h new file mode 100644 index 000000000..3be27945f --- /dev/null +++ b/soh/soh/Enhancements/speechsynthesizer/SpeechLogger.h @@ -0,0 +1,17 @@ +#ifndef SOHSpeechLogger_h +#define SOHSpeechLogger_h + +#include "SpeechSynthesizer.h" + +class SpeechLogger : public SpeechSynthesizer { + public: + SpeechLogger(); + + void Speak(const char* text, const char* language); + + protected: + bool DoInit(void); + void DoUninitialize(void); +}; + +#endif diff --git a/soh/soh/Enhancements/speechsynthesizer/SpeechSynthesizer.h b/soh/soh/Enhancements/speechsynthesizer/SpeechSynthesizer.h index b08aab05c..29d209b5f 100644 --- a/soh/soh/Enhancements/speechsynthesizer/SpeechSynthesizer.h +++ b/soh/soh/Enhancements/speechsynthesizer/SpeechSynthesizer.h @@ -36,3 +36,5 @@ class SpeechSynthesizer { #elif defined(__APPLE__) #include "DarwinSpeechSynthesizer.h" #endif + +#include "SpeechLogger.h" diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index ff78fd0ab..f4b498815 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -11,6 +11,8 @@ #include "message_data_static.h" #include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/resource/type/SohResourceType.h" +#include "soh/resource/type/RawJson.h" extern "C" { extern MapData* gMapData; @@ -1037,25 +1039,22 @@ void InitTTSBank() { break; } - auto sceneFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/scenes" + languageSuffix); - if (sceneFile != nullptr) { - sceneMap = nlohmann::json::parse(*sceneFile->Buffer.get(), nullptr, true, true); - } + auto initData = std::make_shared(); + initData->Format = RESOURCE_FORMAT_BINARY; + initData->Type = static_cast(SOH::ResourceType::SOH_RawJson); + initData->ResourceVersion = 0; - auto miscFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/misc" + languageSuffix); - if (miscFile != nullptr) { - miscMap = nlohmann::json::parse(*miscFile->Buffer.get(), nullptr, true, true); - } - - auto kaleidoFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/kaleidoscope" + languageSuffix); - if (kaleidoFile != nullptr) { - kaleidoMap = nlohmann::json::parse(*kaleidoFile->Buffer.get(), nullptr, true, true); - } - - auto fileChooseFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/filechoose" + languageSuffix); - if (fileChooseFile != nullptr) { - fileChooseMap = nlohmann::json::parse(*fileChooseFile->Buffer.get(), nullptr, true, true); - } + sceneMap = std::static_pointer_cast( + LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; + + miscMap = std::static_pointer_cast( + LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; + + kaleidoMap = std::static_pointer_cast( + LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; + + fileChooseMap = std::static_pointer_cast( + LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; } void RegisterOnSetGameLanguageHook() { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 61f0e2b93..405335738 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -118,6 +118,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/BackgroundFactory.h" +#include "soh/resource/importer/RawJsonFactory.h" #include "soh/config/ConfigUpdaters.h" @@ -341,6 +342,7 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast(SOH::ResourceType::SOH_AudioSoundFont), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast(SOH::ResourceType::SOH_RawJson), 0); gSaveStateMgr = std::make_shared(); gRandomizer = std::make_shared(); @@ -1109,6 +1111,9 @@ extern "C" void InitOTR() { #elif defined(_WIN32) SpeechSynthesizer::Instance = new SAPISpeechSynthesizer(); SpeechSynthesizer::Instance->Init(); +#else + SpeechSynthesizer::Instance = new SpeechLogger(); + SpeechSynthesizer::Instance->Init(); #endif #ifdef ENABLE_REMOTE_CONTROL diff --git a/soh/soh/resource/importer/RawJsonFactory.cpp b/soh/soh/resource/importer/RawJsonFactory.cpp new file mode 100644 index 000000000..4978f6f96 --- /dev/null +++ b/soh/soh/resource/importer/RawJsonFactory.cpp @@ -0,0 +1,19 @@ +#include "soh/resource/importer/RawJsonFactory.h" +#include "soh/resource/type/RawJson.h" +#include "spdlog/spdlog.h" + +namespace SOH { +std::shared_ptr ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto rawJson = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + rawJson->DataSize = file->Buffer->size(); + rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true); + + return rawJson; +} +} // namespace SOH diff --git a/soh/soh/resource/importer/RawJsonFactory.h b/soh/soh/resource/importer/RawJsonFactory.h new file mode 100644 index 000000000..d5fa656b6 --- /dev/null +++ b/soh/soh/resource/importer/RawJsonFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "resource/Resource.h" +#include "resource/ResourceFactoryBinary.h" + +namespace SOH { +class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +}; // namespace SOH diff --git a/soh/soh/resource/type/RawJson.cpp b/soh/soh/resource/type/RawJson.cpp new file mode 100644 index 000000000..3022a67ef --- /dev/null +++ b/soh/soh/resource/type/RawJson.cpp @@ -0,0 +1,14 @@ +#include "RawJson.h" + +namespace SOH { +RawJson::RawJson() : Resource(std::shared_ptr()) { +} + +void* RawJson::GetPointer() { + return &Data; +} + +size_t RawJson::GetPointerSize() { + return DataSize * sizeof(char); +} +} // namespace SOH diff --git a/soh/soh/resource/type/RawJson.h b/soh/soh/resource/type/RawJson.h new file mode 100644 index 000000000..47e0323cc --- /dev/null +++ b/soh/soh/resource/type/RawJson.h @@ -0,0 +1,20 @@ +#pragma once + +#include "resource/Resource.h" +#include + +namespace SOH { + +class RawJson : public LUS::Resource { + public: + using Resource::Resource; + + RawJson(); + + void* GetPointer() override; + size_t GetPointerSize() override; + + nlohmann::json Data; + size_t DataSize; +}; +}; // namespace SOH diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index fdf39031e..3ef4163fe 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -17,5 +17,6 @@ enum class ResourceType { SOH_AudioSequence = 0x4F534551, // OSEQ SOH_Background = 0x4F424749, // OBGI SOH_SceneCommand = 0x4F52434D, // ORCM + SOH_RawJson = 0x4A534F4E, // JSON }; } // namespace SOH From ef690e2ceb7bbc8698cda7e8a4646bb76d13a350 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 5 Mar 2024 23:09:05 -0500 Subject: [PATCH 123/300] support `LUS::Archive::LoadFileRaw` no longer being exposed (#3999) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libultraship b/libultraship index d70fd7de2..f79b19a73 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit d70fd7de2315388c9a99742fd6c634b2cd8be138 +Subproject commit f79b19a73293c572867eb816377d14c3dbded6e8 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 405335738..6d025ab6f 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -872,7 +872,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { // Use a temporary archive instance to load the otr and read the version file auto archive = LUS::OtrArchive(otrPath); if (archive.Open()) { - auto t = archive.LoadFileRaw("portVersion"); + auto t = archive.LoadFile("portVersion", std::make_shared()); if (t != nullptr && t->IsLoaded) { auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); auto reader = std::make_shared(stream); From c162af818d55d7e7e75c6931dcf5b8ab1ba4734b Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 20 Mar 2024 18:24:58 -0400 Subject: [PATCH 124/300] Fix keysanity Any Dungeon setting. (#4020) Due to a typo a few months ago, it was accidentally being ignored and treated as Anywhere. Own Dungeon may have also been doing weird things, but I'm not entirely sure. --- soh/soh/Enhancements/randomizer/3drando/fill.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 7f424f758..a23636c91 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -893,7 +893,7 @@ static void RandomizeDungeonItems() { std::vector overworldItems; for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { - if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) { + if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) { auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); AddElementsToPool(anyDungeonItems, dungeonKeys); } else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { From 0334c4e35484882c09225b29a0f7dfc5642bcae8 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 3 Apr 2024 21:07:42 -0400 Subject: [PATCH 125/300] pull in docs (#97) * rename `func_8002DF54` to `Player_SetCsActionWithHaltedActors` * rename `func_8002F434` to `Actor_OfferGetItem` --- soh/include/functions.h | 6 +- .../Enhancements/timesaver_hook_handlers.cpp | 2 +- soh/src/code/z_actor.c | 7 +- soh/src/code/z_camera.c | 12 ++-- soh/src/code/z_en_item00.c | 2 +- soh/src/code/z_onepointdemo.c | 66 +++++++++---------- soh/src/code/z_parameter.c | 2 +- .../actors/ovl_Bg_Breakwall/z_bg_breakwall.c | 2 +- .../ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c | 18 ++--- .../ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c | 8 +-- .../ovl_Bg_Heavy_Block/z_bg_heavy_block.c | 2 +- .../ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c | 4 +- .../ovl_Bg_Ice_Objects/z_bg_ice_objects.c | 6 +- .../z_bg_mori_kaitenkabe.c | 4 +- .../actors/ovl_Bg_Po_Event/z_bg_po_event.c | 4 +- .../z_bg_spot00_hanebasi.c | 2 +- .../actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 12 ++-- .../overlays/actors/ovl_Boss_Fd/z_boss_fd.c | 12 ++-- .../overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c | 6 +- .../actors/ovl_Boss_Ganon/z_boss_ganon.c | 32 ++++----- .../actors/ovl_Boss_Ganon2/z_boss_ganon2.c | 54 +++++++-------- .../ovl_Boss_Ganondrof/z_boss_ganondrof.c | 4 +- .../actors/ovl_Boss_Goma/z_boss_goma.c | 14 ++-- .../overlays/actors/ovl_Boss_Mo/z_boss_mo.c | 12 ++-- .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 8 +-- .../overlays/actors/ovl_Boss_Tw/z_boss_tw.c | 18 ++--- .../overlays/actors/ovl_Boss_Va/z_boss_va.c | 20 +++--- .../overlays/actors/ovl_Demo_Im/z_demo_im.c | 2 +- .../actors/ovl_Door_Shutter/z_door_shutter.c | 4 +- .../actors/ovl_Door_Warp1/z_door_warp1.c | 6 +- soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c | 4 +- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 10 +-- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c | 12 ++-- soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c | 4 +- .../overlays/actors/ovl_En_Daiku/z_en_daiku.c | 4 +- .../ovl_En_Diving_Game/z_en_diving_game.c | 20 +++--- soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 2 +- .../actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c | 8 +-- .../actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c | 6 +- soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c | 8 +-- soh/src/overlays/actors/ovl_En_Du/z_en_du.c | 10 +-- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 2 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 6 +- .../overlays/actors/ovl_En_Fish/z_en_fish.c | 2 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 4 +- soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c | 4 +- soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 8 +-- soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c | 6 +- soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c | 6 +- .../overlays/actors/ovl_En_GeldB/z_en_geldb.c | 2 +- soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c | 4 +- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 4 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 8 +-- .../actors/ovl_En_Heishi1/z_en_heishi1.c | 4 +- .../actors/ovl_En_Heishi2/z_en_heishi2.c | 14 ++-- .../actors/ovl_En_Heishi3/z_en_heishi3.c | 4 +- .../actors/ovl_En_Heishi4/z_en_heishi4.c | 4 +- soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c | 4 +- soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c | 4 +- .../actors/ovl_En_Ice_Hono/z_en_ice_hono.c | 2 +- soh/src/overlays/actors/ovl_En_In/z_en_in.c | 4 +- .../actors/ovl_En_Insect/z_en_insect.c | 2 +- .../overlays/actors/ovl_En_Ishi/z_en_ishi.c | 4 +- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 2 +- .../actors/ovl_En_Kakasi/z_en_kakasi.c | 6 +- .../actors/ovl_En_Kakasi3/z_en_kakasi3.c | 10 +-- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c | 2 +- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 6 +- soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c | 2 +- soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c | 8 +-- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 4 +- soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c | 2 +- .../actors/ovl_En_Niw_Lady/z_en_niw_lady.c | 10 +-- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 8 +-- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c | 6 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 12 ++-- soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c | 2 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 4 +- soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 18 ++--- .../ovl_En_Takara_Man/z_en_takara_man.c | 4 +- .../overlays/actors/ovl_En_Toryo/z_en_toryo.c | 2 +- .../ovl_En_Wonder_Talk2/z_en_wonder_talk2.c | 4 +- soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c | 8 +-- soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c | 12 ++-- soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c | 8 +-- .../overlays/actors/ovl_Fishing/z_fishing.c | 14 ++-- .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 2 +- .../ovl_Item_Etcetera/z_item_etcetera.c | 4 +- .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 2 +- .../actors/ovl_Item_Shield/z_item_shield.c | 4 +- .../actors/ovl_Obj_Tsubo/z_obj_tsubo.c | 2 +- .../actors/ovl_player_actor/z_player.c | 10 +-- 92 files changed, 359 insertions(+), 360 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index a0df5ba72..13c755cfe 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -429,7 +429,7 @@ void Actor_MountHorse(PlayState* play, Player* player, Actor* horse); s32 func_8002DEEC(Player* player); void func_8002DF18(PlayState* play, Player* player); s32 func_8002DF38(PlayState* play, Actor* actor, u8 csMode); -s32 func_8002DF54(PlayState* play, Actor* actor, u8 arg2); +s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 arg2); void func_8002DF90(DynaPolyActor* dynaActor); void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2); s32 Player_IsFacingActor(Actor* actor, s16 angle, PlayState* play); @@ -457,11 +457,11 @@ u32 Actor_TextboxIsClosing(Actor* actor, PlayState* play); s8 func_8002F368(PlayState* play); void Actor_GetScreenPos(PlayState* play, Actor* actor, s16* x, s16* y); u32 Actor_HasParent(Actor* actor, PlayState* play); -// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename func_8002F434 and func_8002F554. +// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename Actor_OfferGetItem and func_8002F554. s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry); s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange); s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry); -s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange); +s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange); void func_8002F554(Actor* actor, PlayState* play, s32 getItemId); void func_8002F580(Actor* actor, PlayState* play); u32 Actor_HasNoParent(Actor* actor, PlayState* play); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index ba432796b..02decd7ba 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -464,7 +464,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* gPlayState->transitionType = TRANS_TYPE_FADE_WHITE; gPlayState->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.nextTransitionType = 2; - func_8002DF54(gPlayState, &player->actor, 8); + Player_SetCsActionWithHaltedActors(gPlayState, &player->actor, 8); } } }); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index fed5ec639..e4edcc1d3 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1462,7 +1462,7 @@ s32 func_8002DF38(PlayState* play, Actor* actor, u8 csAction) { return true; } -s32 func_8002DF54(PlayState* play, Actor* actor, u8 csAction) { +s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 csAction) { Player* player = GET_PLAYER(play); func_8002DF38(play, actor, csAction); @@ -2084,9 +2084,8 @@ s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemE return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f); } -// TODO: Rename to GiveItemIdFromActor or similar // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActor -s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { +s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { Player* player = GET_PLAYER(play); if (!(player->stateFlags1 & @@ -2116,7 +2115,7 @@ s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 // TODO: Rename to GiveItemIdFromActorWithFixedRange or similar // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActorWithFixedRange void func_8002F554(Actor* actor, PlayState* play, s32 getItemId) { - func_8002F434(actor, play, getItemId, 50.0f, 10.0f); + Actor_OfferGetItem(actor, play, getItemId, 50.0f, 10.0f); } void func_8002F580(Actor* actor, PlayState* play) { diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 90634ea31..b5719d48c 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -6184,14 +6184,14 @@ s32 Camera_Demo5(Camera* camera) { pad = camera->play->state.frames - sDemo5PrevAction12Frame; if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { // holding object over head. - func_8002DF54(camera->play, camera->target, 8); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 8); } else if (ABS(pad) > 3000) { - func_8002DF54(camera->play, camera->target, 12); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 12); } else { - func_8002DF54(camera->play, camera->target, 69); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 69); } } else { - func_8002DF54(camera->play, camera->target, 1); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 1); } } @@ -6250,7 +6250,7 @@ s32 Camera_Demo6(Camera* camera) { camera->animState++; case 1: if (stateTimers[camera->animState] < anim->animTimer) { - func_8002DF54(camera->play, &camera->player->actor, 8); + Player_SetCsActionWithHaltedActors(camera->play, &camera->player->actor, 8); Actor_GetWorld(&focusPosRot, camFocus); anim->atTarget.x = focusPosRot.pos.x; anim->atTarget.y = focusPosRot.pos.y - 20.0f; @@ -7735,7 +7735,7 @@ void Camera_Finish(Camera* camera) { player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; if (player->csAction != 0) { - func_8002DF54(camera->play, &player->actor, 7); + Player_SetCsActionWithHaltedActors(camera->play, &player->actor, 7); osSyncPrintf("camera: player demo end!!\n"); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index da7454961..873a91ec9 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -732,7 +732,7 @@ void func_8001E5C8(EnItem00* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->getItemId != GI_NONE) { if (!Actor_HasParent(&this->actor, play)) { - func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 50.0f, 80.0f); this->unk_15A++; } else { this->getItemId = GI_NONE; diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 4224066c1..24a8820af 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -268,7 +268,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 2290: { Actor* rideActor = player->rideActor; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (rideActor != NULL) { rideActor->freezeTimer = 180; } @@ -279,7 +279,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); } break; case 5120: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_80121314; csInfo->keyFrameCnt = 1; @@ -289,7 +289,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 4510: D_8012133C[0].eyeTargetInit = actor->world.pos; D_8012133C[0].eyeTargetInit.y = player->actor.world.pos.y + 40.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_8012133C; csInfo->keyFrameCnt = 3; @@ -307,7 +307,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor OnePointCutscene_AddVecSphToVec3f(&spB4, &spC0, &spD0); Play_CameraChangeSetting(play, camIdx, CAM_SET_FREE2); Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csCam->roll = 0; csCam->fov = 50.0f; if (csCam->childCamIdx != SUBCAM_FREE) { @@ -321,7 +321,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor if (Rand_ZeroOne() < 0.0f) { D_801213B4[3].eyeTargetInit.x = -D_801213B4[3].eyeTargetInit.x; } - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_801213B4; csInfo->keyFrameCnt = 5; @@ -374,10 +374,10 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); csCam->roll = 6; csCam->fov = 75.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3040: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_8012151C[0].timerInit = timer - 1; csInfo->keyFrames = D_8012151C; @@ -401,7 +401,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrameCnt = 2; func_800C0808(play, camIdx, player, CAM_SET_CS_C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3010: D_801215BC[0].timerInit = timer; @@ -429,7 +429,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3090: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_80121814; csInfo->keyFrameCnt = 4; @@ -445,14 +445,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); csCam->roll = 0; csCam->fov = 70.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3380: case 3065: csInfo->keyFrames = D_801218B4; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -464,12 +464,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121904; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3050: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); - func_8002DF54(play, &player->actor, 5); + Player_SetCsActionWithHaltedActors(play, &player->actor, 5); OnePointCutscene_SetCsCamPoints(csCam, D_80120304 | 0x2000, D_80120300, D_8012013C, D_8012021C); func_80078884(NA_SE_SY_CORRECT_CHIME); OnePointCutscene_Vec3sToVec3f(&mainCam->at, &D_8012013C[D_801202FC - 2].pos); @@ -498,14 +498,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csCam->unk_14C |= 2; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3130: csInfo->keyFrames = D_80121A44; csInfo->keyFrameCnt = 12; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); csCam->unk_14C |= 2; break; @@ -636,7 +636,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csCam->roll = 0; csCam->fov = 75.0f; player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spD0.yaw + 0x7FFF; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3240: D_80121D3C[2].timerInit = timer - 5; @@ -644,12 +644,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121D3C; csInfo->keyFrameCnt = 3; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 6001: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Actor_GetWorld(&spA0, actor); if (spA0.pos.z > -750.0f) { OnePointCutscene_SetCsCamPoints(csCam, D_801208E8, D_801208E4, D_801206A0, D_80120820); @@ -680,12 +680,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121DB4; csInfo->keyFrameCnt = 9; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3310: Play_CameraChangeSetting(play, camIdx, CAM_SET_FIRE_STAIRCASE); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Play_CopyCamera(play, camIdx, MAIN_CAM); i = Quake_Add(csCam, 1); @@ -718,7 +718,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121FBC; csInfo->keyFrameCnt = 4; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 3); @@ -745,7 +745,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor D_801220D4[1].eyeTargetInit.y = 80.0f; D_801220D4[1].eyeTargetInit.x = -D_801220D4[1].eyeTargetInit.x; } - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_801220D4; csInfo->keyFrameCnt = 5; @@ -763,7 +763,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801222B4; csInfo->keyFrameCnt = 5; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -787,7 +787,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801223CC; csInfo->keyFrameCnt = 6; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; player->actor.freezeTimer = 90; @@ -801,7 +801,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801224BC; csInfo->keyFrameCnt = 7; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -815,7 +815,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = 0x3FFC; func_800C0808(play, camIdx, player, CAM_SET_CS_C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 4110: csInfo->keyFrames = D_8012269C; @@ -825,7 +825,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 4120: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122714[1].timerInit = 80; csInfo->keyFrames = D_80122714; csInfo->keyFrameCnt = 4; @@ -843,7 +843,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801228A4; csInfo->keyFrameCnt = 5; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -851,7 +851,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_8012296C; csInfo->keyFrameCnt = 4; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -859,7 +859,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80122A0C; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -908,11 +908,11 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80122C8C; csInfo->keyFrameCnt = 1; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3260: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122CB4[1].timerInit = timer - 5; csInfo->keyFrames = D_80122CB4; @@ -921,7 +921,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3261: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122D04[1].timerInit = timer - 10; csInfo->keyFrames = D_80122D04; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 21c45a1ae..cb665999e 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -6159,7 +6159,7 @@ void Interface_Draw(PlayState* play) { gSaveContext.timer2State = 5; gSaveContext.cutsceneIndex = 0; Message_StartTextbox(play, 0x71B0, NULL); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); } else { D_8015FFE6 = 40; gSaveContext.timer2State = 6; diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index d0fc8864f..8b901339f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -305,7 +305,7 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) { if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { Cutscene_SetSegment(play, gDcOpeningCs); gSaveContext.cutsceneTrigger = 1; - func_8002DF54(play, NULL, 0x31); + Player_SetCsActionWithHaltedActors(play, NULL, 0x31); } Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index 542711f81..8e2139aed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -203,7 +203,7 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { return; } - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = BgDyYoseizo_ChooseType; } } @@ -211,7 +211,7 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) { s32 givingReward; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); // "Mode" osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ もうど ☆☆☆☆☆ %d\n" VT_RST, play->msgCtx.ocarinaMode); givingReward = false; @@ -327,12 +327,12 @@ void BgDyYoseizo_SetupSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { } Audio_PlayActorSound2(&this->actor, NA_SE_VO_FR_LAUGH_0); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = BgDyYoseizo_SpinGrow_NoReward; } void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Math_ApproachF(&this->actor.world.pos.y, this->grownHeight, this->heightFraction, 100.0f); Math_ApproachF(&this->scale, 0.035f, this->scaleFraction, 0.005f); Math_ApproachF(&this->heightFraction, 0.8f, 0.1f, 0.02f); @@ -358,7 +358,7 @@ void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { f32 curFrame = this->skelAnime.curFrame; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if ((this->frameCount * 1273.0f) <= this->bobTimer) { this->bobTimer = 0.0f; @@ -372,7 +372,7 @@ void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { this->frameCount = Animation_GetLastFrame(&gGreatFairySittingAnim); @@ -392,7 +392,7 @@ void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_GreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->bobTimer = this->skelAnime.curFrame * 1273.0f; if ((this->frameCount * 1273.0f) <= this->bobTimer) { @@ -560,7 +560,7 @@ void BgDyYoseizo_Vanish(BgDyYoseizo* this, PlayState* play) { Actor* findOcarinaSpot; if (this->vanishTimer == 0) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); play->envCtx.unk_BF = 0; findOcarinaSpot = play->actorCtx.actorLists[ACTORCAT_PROP].head; @@ -582,7 +582,7 @@ void BgDyYoseizo_SetupSpinGrow_Reward(BgDyYoseizo* this, PlayState* play) { if (play->csCtx.state != CS_STATE_IDLE) { if ((play->csCtx.npcActions[0] != NULL) && (play->csCtx.npcActions[0]->action == 2)) { this->actor.draw = BgDyYoseizo_Draw; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->finishedSpinGrow = false; if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { diff --git a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c index ae8f9cd05..37ff09efc 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c +++ b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c @@ -241,7 +241,7 @@ void BgGndIceblock_Idle(BgGndIceblock* this, PlayState* play) { if (this->dyna.unk_150 > 0.0f) { BgGndIceblock_SetNextPosition(this); if (Actor_WorldDistXZToPoint(&this->dyna.actor, &this->targetPos) > 1.0f) { - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); this->actionFunc = BgGndIceblock_Slide; } } @@ -282,7 +282,7 @@ void BgGndIceblock_Fall(BgGndIceblock* this, PlayState* play) { thisx->world.pos.y = thisx->home.pos.y - 100.0f; thisx->world.pos.z = thisx->home.pos.z; if (Player_InCsMode(play)) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgGndIceblock_Reset; } @@ -295,7 +295,7 @@ void BgGndIceblock_Hole(BgGndIceblock* this, PlayState* play) { if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 100.0f, thisx->velocity.y)) { thisx->velocity.y = 0.0f; if (Player_InCsMode(play)) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgGndIceblock_Idle; } @@ -319,7 +319,7 @@ void BgGndIceblock_Slide(BgGndIceblock* this, PlayState* play) { switch (BgGndIceblock_NextAction(this)) { case GNDICE_IDLE: this->actionFunc = BgGndIceblock_Idle; - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); break; case GNDICE_FALL: this->actionFunc = BgGndIceblock_Fall; diff --git a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c index 3b2524e79..97ed090a8 100644 --- a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c @@ -370,7 +370,7 @@ void BgHeavyBlock_LiftedUp(BgHeavyBlock* this, PlayState* play) { this->timer++; if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } // if parent is NULL, link threw it diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c index cae8037c6..3e1fd9d78 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c @@ -138,7 +138,7 @@ void BgHidanDalm_Wait(BgHidanDalm* this, PlayState* play) { this->dyna.actor.world.pos.x += 32.5f * Math_SinS(this->dyna.actor.world.rot.y); this->dyna.actor.world.pos.z += 32.5f * Math_CosS(this->dyna.actor.world.rot.y); - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); this->dyna.actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actionFunc = BgHidanDalm_Shrink; this->dyna.actor.bgCheckFlags &= ~2; @@ -159,7 +159,7 @@ void BgHidanDalm_Shrink(BgHidanDalm* this, PlayState* play) { Vec3f pos; if (Math_StepToF(&this->dyna.actor.scale.x, 0.0f, 0.004f)) { - func_8002DF54(play, &this->dyna.actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 7); Actor_Kill(&this->dyna.actor); } diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c index 1cd91d468..7193d3659 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c @@ -126,7 +126,7 @@ void BgIceObjects_CheckPits(BgIceObjects* this, PlayState* play) { thisx->world.pos.y = thisx->home.pos.y - 60.0f; thisx->world.pos.z = thisx->home.pos.z; if (thisx->params != 0) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgIceObjects_Reset; } @@ -143,7 +143,7 @@ void BgIceObjects_Idle(BgIceObjects* this, PlayState* play) { BgIceObjects_SetNextTarget(this, play); if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) { thisx->flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; - func_8002DF54(play, thisx, 8); + Player_SetCsActionWithHaltedActors(play, thisx, 8); thisx->params = 1; this->actionFunc = BgIceObjects_Slide; } @@ -173,7 +173,7 @@ void BgIceObjects_Slide(BgIceObjects* this, PlayState* play) { thisx->flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; } thisx->params = 0; - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); Audio_PlayActorSound2(thisx, NA_SE_EV_BLOCK_BOUND); if ((fabsf(thisx->world.pos.x + 1387.0f) < 1.0f) && (fabsf(thisx->world.pos.z + 260.0f) < 1.0f)) { this->actionFunc = BgIceObjects_Stuck; diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c index 8392e7224..f020a462a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c @@ -96,7 +96,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) { this->timer++; if ((this->timer > (28 - CVarGetInteger("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(play)) { BgMoriKaitenkabe_SetupRotate(this); - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos); push.x = Math_SinS(this->dyna.unk_158); push.y = 0.0f; @@ -130,7 +130,7 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) { Math_StepToF(&this->rotSpeed, 0.6f, 0.02f); if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) { BgMoriKaitenkabe_SetupWait(this); - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); if (this->rotDirection > 0.0f) { thisx->home.rot.y += 0x2000; } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c index a2fca0db7..08d4fc773 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c @@ -321,7 +321,7 @@ void BgPoEvent_BlockFall(BgPoEvent* this, PlayState* play) { if (firstFall == 0) { firstFall = 1; } else { - func_8002DF54(play, &GET_PLAYER(play)->actor, 7); + Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7); } } this->direction = 0; @@ -358,7 +358,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) { if (sBgPoEventPuzzleState == 0x10) { sBgPoEventPuzzleState = 0x40; Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_RISING); - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } } else if (this->dyna.unk_150 != 0.0f) { if (this->direction == 0) { diff --git a/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c b/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c index 0fb728661..675bbb3ed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c @@ -223,7 +223,7 @@ void BgSpot00Hanebasi_Update(Actor* thisx, PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE); Flags_SetEventChkInf(EVENTCHKINF_DRAWBRIDGE_OPENED_AFTER_ZELDA_FLED); this->actionFunc = BgSpot00Hanebasi_DoNothing; - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); play->nextEntranceIndex = ENTR_HYRULE_FIELD_0; gSaveContext.nextCutsceneIndex = 0xFFF1; play->transitionTrigger = TRANS_TRIGGER_START; diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 30455e8e5..a825f67d7 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -443,7 +443,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { break; case 1: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Play_ClearAllSubCameras(play); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 1); @@ -470,11 +470,11 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { } if (this->unk_198 == 110) { - func_8002DF54(play, &this->actor, 9); + Player_SetCsActionWithHaltedActors(play, &this->actor, 9); } if (this->unk_198 == 5) { - func_8002DF54(play, &this->actor, 12); + Player_SetCsActionWithHaltedActors(play, &this->actor, 12); } if (this->unk_198 < 6) { @@ -589,7 +589,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { func_800C08AC(play, this->cutsceneCamera, 0); this->cutsceneCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossDodongo_SetupWalk(this); this->unk_1DA = 50; this->unk_1BC = 0; @@ -1535,7 +1535,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { case 0: this->csState = 5; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_UNK3); Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE); @@ -1850,7 +1850,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { this->csState = 100; Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD); } else { diff --git a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c index 0d33533ae..72908fd2f 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c @@ -323,7 +323,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->introState = BFD_CS_START; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->introCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->introCamera, CAM_STAT_ACTIVE); @@ -399,7 +399,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { Math_ApproachF(&this->camData.shake, 2.0f, 1.0f, 0.8 * 0.01f); } if (this->timers[0] == 40) { - func_8002DF54(play, &this->actor, 0x13); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x13); } if (this->timers[0] == 0) { this->introState = BFD_CS_LOOK_GROUND; @@ -428,7 +428,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->timers[0] = 170; this->camData.speedMod = 0.0f; this->camData.accel = 0.0f; - func_8002DF54(play, &this->actor, 0x14); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x14); } break; case BFD_CS_COLLAPSE: @@ -478,7 +478,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { if (this->timers[3] == 190) { this->camData.atMaxVel.x = this->camData.atMaxVel.y = this->camData.atMaxVel.z = 0.05f; this->platformSignal = VBSIMA_KILL; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } if (this->actor.world.pos.y > 120.0f) { this->camData.nextAt = this->actor.world.pos; @@ -546,7 +546,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { func_800C08AC(play, this->introCamera, 0); this->introState = this->introFlyState = this->introCamera = BFD_CS_NONE; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = BossFd_Wait; this->handoffSignal = FD2_SIGNAL_GROUND; Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); @@ -854,7 +854,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->work[BFD_CAM_SHAKE_TIMER] = 20; Audio_PlaySoundGeneral(NA_SE_EN_VALVAISA_LAND2, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); for (i1 = 0; i1 < 15; i1++) { Vec3f sp144 = { 0.0f, 0.0f, 0.0f }; Vec3f sp138 = { 0.0f, 0.0f, 0.0f }; diff --git a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c index fb14c5ebe..2a03f1839 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c @@ -661,7 +661,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { case DEATH_START: this->deathState = DEATH_RETREAT; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->deathCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->deathCamera, CAM_STAT_ACTIVE); @@ -754,7 +754,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { this->work[FD2_ACTION_STATE]++; this->camData.speedMod = 0.0f; this->camData.accel = 0.02f; - func_8002DF54(play, &bossFd->actor, 1); + Player_SetCsActionWithHaltedActors(play, &bossFd->actor, 1); } } if ((bossFd->work[BFD_ACTION_STATE] == BOSSFD_BONES_FALL) && (bossFd->timers[0] == 5)) { @@ -788,7 +788,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { func_800C08AC(play, this->deathCamera, 0); this->deathCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 97551ca46..b1c45feed 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -564,7 +564,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { this->actor.shape.rot.y = 0; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -609,7 +609,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { BossGanon_SetIntroCsCamera(this, 1); if (this->csTimer == 10) { - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); } if (this->csTimer == 13) { @@ -642,7 +642,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { break; } - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 4; BossGanon_SetIntroCsCamera(this, 2); this->csTimer = 0; @@ -674,7 +674,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { } if (this->csTimer == 10) { - func_8002DF54(play, &this->actor, 0x4B); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4B); } if (this->csTimer == 70) { @@ -740,7 +740,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { this->csState = 9; this->csTimer = 0; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); sBossGanonZelda->unk_3C8 = 0; this->triforceType = GDF_TRIFORCE_ZELDA; this->fwork[GDF_TRIFORCE_SCALE] = 10.0f; @@ -794,7 +794,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { player->actor.world.pos.z = 20.0f; if (this->csTimer == 20) { - func_8002DF54(play, &this->actor, 0x17); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x17); Interface_ChangeAlpha(11); // show hearts only } @@ -1031,7 +1031,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { } if (this->csTimer == 30) { - func_8002DF54(play, &this->actor, 0x4A); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4A); } if (this->csTimer <= 50) { @@ -1154,7 +1154,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { func_800C08AC(play, this->csCamIndex, 0); this->csState = this->csCamIndex = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossGanon_SetupWait(this, play); } @@ -1267,7 +1267,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { switch (this->csState) { case 0: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -1510,7 +1510,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_BODY_SPARK - SFX_FLAG); if (this->csTimer == 2) { - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } if (this->csTimer > 50) { @@ -1552,7 +1552,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { case 100: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -1651,11 +1651,11 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csCamAt.z = -135.0f; if (this->csTimer == 5) { - func_8002DF54(play, &this->actor, 0x4C); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4C); } if (this->csTimer == 70) { - func_8002DF54(play, &this->actor, 0x4D); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4D); } if (this->csTimer == 90) { @@ -1754,7 +1754,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { if (this->csTimer == 20) { sBossGanonZelda->unk_3C8 = 5; - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } if (this->csTimer == 40) { @@ -1821,7 +1821,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csState = 107; this->csTimer = 0; Message_StartTextbox(play, 0x70D2, NULL); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } break; @@ -1863,7 +1863,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csState = 109; this->csCamIndex = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Flags_SetSwitch(play, 0x37); } break; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index ba4a4fbc6..28febacd4 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -228,7 +228,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { objectIdx = Object_GetIndex(&play->objectCtx, OBJECT_GANON_ANIME3); if (Object_IsLoaded(&play->objectCtx, objectIdx)) { func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); @@ -306,11 +306,11 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 40) { sBossGanon2Zelda->unk_3C8 = 1; - func_8002DF54(play, &this->actor, 0x4E); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4E); } if (this->csTimer == 85) { sBossGanon2Zelda->unk_3C8 = 2; - func_8002DF54(play, &this->actor, 0x4F); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4F); } this->unk_3A4.x = 930.0f; this->unk_3A4.y = 1129.0f; @@ -339,14 +339,14 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 20) { sBossGanon2Zelda->unk_3C8 = 3; - func_8002DF54(play, &this->actor, 0x50); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50); } if (this->csTimer == 55) { this->csState = 4; this->csTimer = 0; this->unk_410.x = 0.0f; sBossGanon2Zelda->unk_3C8 = 4; - func_8002DF54(play, &this->actor, 0x50); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50); } break; case 4: @@ -363,7 +363,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 5; this->csTimer = 0; } @@ -409,7 +409,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 30) { sBossGanon2Zelda->unk_3C8 = 5; - func_8002DF54(play, &this->actor, 0x51); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x51); } if (this->csTimer == 50) { this->csTimer = 0; @@ -440,7 +440,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_80078884(NA_SE_EV_STONE_BOUND); } if (this->csTimer == 30) { - func_8002DF54(play, &this->actor, 0x52); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x52); } if (this->csTimer == 50) { this->csTimer = 0; @@ -505,7 +505,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->unk_3B0.y = player->actor.world.pos.y; this->unk_3B0.z = player->actor.world.pos.z - 200.0f; if (this->csTimer == 20) { - func_8002DF54(play, &this->actor, 0x1E); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x1E); } if (this->csTimer == 60) { this->unk_3A4.x = (this->actor.world.pos.x + 200.0f) - 154.0f; @@ -593,7 +593,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { SkelAnime_Free(&this->skelAnime, play); SkelAnime_InitFlex(play, &this->skelAnime, &gGanonSkel, NULL, NULL, NULL, 0); BossGanon2_SetObjectSegment(this, play, OBJECT_GANON_ANIME3, false); - func_8002DF54(play, &this->actor, 0x54); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x54); this->unk_314 = 3; // At this point, the actor has Ganon's skeleton but is still playing an animation for Ganondorf. This @@ -657,7 +657,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->actor.world.pos.x += 250; this->actor.world.pos.y = 1886.0f; this->unk_394 = 0.0f; - func_8002DF54(play, &this->actor, 0x53); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x53); this->unk_30C = 5.0f; this->unk_228 = 1.0f; } @@ -742,7 +742,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { if (this->csTimer == 215) { this->csState = 23; this->unk_224 = 0.0f; - func_8002DF54(play, &this->actor, 0x55); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x55); } break; case 23: @@ -762,7 +762,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->unk_3B0.z = player->actor.world.pos.z; if (this->csTimer == 228) { func_80078884(NA_SE_IT_SHIELD_REFLECT_SW); - func_8002DF54(play, &this->actor, 0x56); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x56); func_800A9F6C(0.0f, 0xFF, 0xA, 0x32); } if (this->csTimer >= 229) { @@ -799,7 +799,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_80078884(NA_SE_IT_SWORD_SWING); } if (this->csTimer == 25) { - func_8002DF54(play, &this->actor, 0x57); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x57); this->csState = 25; this->csTimer = 0; } @@ -846,7 +846,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { case 27: this->unk_3BC.z = 0.0f; if (this->csTimer == 4) { - func_8002DF54(play, &this->actor, 0x58); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x58); } this->unk_3A4.x = player->actor.world.pos.x - 20.0f; this->unk_3A4.y = player->actor.world.pos.y + 50.0f; @@ -919,7 +919,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 0; this->unk_337 = 1; func_808FFDB0(this, play); @@ -1340,7 +1340,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 1; this->unk_3A4 = sp4C->eye; this->unk_3B0 = sp4C->at; @@ -1388,7 +1388,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 3; } break; @@ -1399,7 +1399,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); this->csState = 11; this->unk_334 = 1; - func_8002DF54(play, &this->actor, 0x60); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x60); this->csTimer = 0; case 11: player->actor.world.pos.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f; @@ -1420,7 +1420,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1536,7 +1536,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 1; this->csTimer = 0; sBossGanon2Zelda->unk_3C8 = 9; @@ -1572,7 +1572,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->skelAnime.playSpeed = 3.0f; } if (this->csTimer == 120) { - func_8002DF54(play, &this->actor, 0x63); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x63); } this->actor.world.rot.y = 0x4000; this->actor.world.pos.x = this->actor.world.pos.z = 0.0f; @@ -1640,7 +1640,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->csState = 5; this->csTimer = 40; this->skelAnime.playSpeed = 1.0f; - func_8002DF54(play, &this->actor, 0x64); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x64); } break; case 5: @@ -1654,10 +1654,10 @@ void func_8090120C(BossGanon2* this, PlayState* play) { Math_ApproachZeroF(&this->unk_38C, 1.0f, 8.0f); } if (this->csTimer == 70) { - func_8002DF54(play, &this->actor, 0x65); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x65); } if (this->csTimer == 150) { - func_8002DF54(play, &this->actor, 0x66); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x66); } this->unk_30C = 10.0f; player->actor.world.pos.x = 250.0f; @@ -1676,7 +1676,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 6; } break; @@ -1764,7 +1764,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { if (this->csTimer == 55) { Animation_MorphToPlayOnce(&this->skelAnime, &gGanonDeadStartAnim, 0.0f); this->unk_194 = Animation_GetLastFrame(&gGanonDeadStartAnim); - func_8002DF54(play, &this->actor, 0x62); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x62); this->csState = 8; this->csTimer = 1000; } diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 111380f0b..82fe2c131 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -926,7 +926,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { switch (this->deathState) { case DEATH_START: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->deathCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); osSyncPrintf("7\n"); @@ -1104,7 +1104,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { func_800C08AC(play, this->deathCamera, 0); this->deathCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true); diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 6de72fd2d..489350ad0 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -628,7 +628,7 @@ void BossGoma_SetupEncounterState4(BossGoma* this, PlayState* play) { this->actionState = 4; this->actor.flags |= ACTOR_FLAG_TARGETABLE; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->subCameraId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, this->subCameraId, 7); @@ -685,7 +685,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_SHUTTER, 164.72f, -480.0f, 397.68002f, 0, -0x705C, 0, 0x180); } else { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->actionState = 1; } } @@ -756,7 +756,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { } if (this->frameCount == 190) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); } if (this->frameCount >= 228) { @@ -767,7 +767,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { func_800C08AC(play, this->subCameraId, 0); this->subCameraId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionState = 3; } break; @@ -964,7 +964,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { this->disableGameplayLogic = false; this->patienceTimer = 200; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1054,7 +1054,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) { case 0: this->actionState = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->subCameraId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, this->subCameraId, 7); @@ -1189,7 +1189,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) { func_800C08AC(play, this->subCameraId, 0); this->subCameraId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Actor_Kill(&this->actor); } diff --git a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c index 74684df71..7d82b93a4 100644 --- a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c +++ b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c @@ -1249,7 +1249,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { (fabsf(player->actor.world.pos.x - -180.0f) < 40.0f))) { // checks if Link is on one of the four platforms func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); @@ -1357,11 +1357,11 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { Math_ApproachF(&this->actor.speedXZ, sp80, 1.0f, sp78); Math_ApproachF(&this->cameraYawRate, sp7C, 1.0f, 128.0f); if (this->work[MO_TENT_MOVE_TIMER] == 525) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); } if (this->work[MO_TENT_MOVE_TIMER] > 540) { this->csState = MO_INTRO_REVEAL; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sMorphaTent1->drawActor = true; player->actor.world.pos.x = 180.0f; player->actor.world.pos.z = -210.0f; @@ -1468,7 +1468,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { func_800C08AC(play, this->csCamera, 0); this->csState = this->csCamera = MO_BATTLE; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1533,7 +1533,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) { switch (this->csState) { case MO_DEATH_START: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); @@ -1700,7 +1700,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) { func_800C08AC(play, this->csCamera, 0); this->csCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sMorphaTent1->actor.world.pos.y = -1000.0f; } } else { diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index b9f5c6f2c..5b8eef344 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -390,7 +390,7 @@ void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); sCutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); @@ -423,7 +423,7 @@ void BossSst_HeadIntro(BossSst* this, PlayState* play) { sHands[LEFT]->actor.flags |= ACTOR_FLAG_TARGETABLE; player->stateFlags1 &= ~PLAYER_STATE1_INPUT_DISABLED; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCameraAt.y += 30.0f; sCameraAt.z += 300.0f; Play_CameraSetAtEye(play, sCutsceneCamera, &sCameraAt, &sCameraEye); @@ -1032,7 +1032,7 @@ void BossSst_HeadSetupDeath(BossSst* this, PlayState* play) { Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); Play_CopyCamera(play, sCutsceneCamera, MAIN_CAM); - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); func_80064520(play, &play->csCtx); Math_Vec3f_Copy(&sCameraEye, &GET_ACTIVE_CAM(play)->eye); this->actionFunc = BossSst_HeadDeath; @@ -1194,7 +1194,7 @@ void BossSst_HeadFinish(BossSst* this, PlayState* play) { Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Play_ClearCamera(play, sCutsceneCamera); - func_8002DF54(play, &GET_PLAYER(play)->actor, 7); + Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7); func_80064534(play, &play->csCtx); Actor_Kill(&this->actor); Actor_Kill(&sHands[LEFT]->actor); diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 9d0a68c38..40f8127cd 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -1466,7 +1466,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { case 0: this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -1606,7 +1606,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { Animation_MorphToPlayOnce(&this->skelAnime, &gTwinrovaIntroAnim, 0.0f); this->workf[ANIM_SW_TGT] = Animation_GetLastFrame(&gTwinrovaIntroAnim); this->timers[0] = 50; - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_TRANSFORM); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); } @@ -1649,7 +1649,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { } if (this->timers[3] == 19) { - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); } if (this->timers[3] == 16) { @@ -1682,7 +1682,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { this->subCamId = 0; this->csState2 = this->subCamId; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->work[TW_PLLR_IDX] = 0; this->targetPos = sTwinrovaPillarPos[0]; BossTw_TwinrovaSetupFly(this, play); @@ -1762,7 +1762,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) { player->actor.world.pos.x = player->actor.world.pos.z = .0f; this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -2245,7 +2245,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) { this->subCamId = 0; this->csState2 = this->subCamId; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossTw_SetupWait(this, play); } break; @@ -2666,7 +2666,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { case 0: this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -2705,7 +2705,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { sKoumePtr->actor.world.pos.z = sKotakePtr->actor.world.pos.z; sKoumePtr->work[YAW_TGT] = sKotakePtr->work[YAW_TGT] = sKoumePtr->actor.shape.rot.x = sKotakePtr->actor.shape.rot.x = sKoumePtr->actor.shape.rot.y = sKotakePtr->actor.shape.rot.y = 0; - func_8002DF54(play, &sKoumePtr->actor, 1); + Player_SetCsActionWithHaltedActors(play, &sKoumePtr->actor, 1); sKoumePtr->actor.flags |= ACTOR_FLAG_TARGETABLE; } break; @@ -2793,7 +2793,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { this->csState2 = 4; this->subCamId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index 0e5a95608..77a497e7a 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -657,7 +657,7 @@ void BossVa_Init(Actor* thisx, PlayState* play2) { } else { sCsState = INTRO_CALL_BARI; sDoorState = 100; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); play->envCtx.screenFillColor[0] = 0xDC; play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[2] = 0xBE; @@ -799,7 +799,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[2] = 0xBE; play->envCtx.screenFillColor[3] = 0xD2; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); player->actor.world.rot.y = player->actor.shape.rot.y = 0x7FFF; sCsState++; break; @@ -827,7 +827,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { case INTRO_CLOSE_DOOR: this->timer--; if (this->timer == 0) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); sCsState++; this->timer = 30; } @@ -842,7 +842,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { } break; case INTRO_CRACKLE: - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sCsState++; break; case INTRO_SPAWN_BARI: @@ -973,7 +973,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { sCameraAtMaxVel = sCameraEyeMaxVel; if (this->timer >= 45000) { play->envCtx.unk_BF = 1; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } else if (this->timer >= 35000) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); } @@ -1030,7 +1030,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { sCsCamera = 0; func_80064534(play, &play->csCtx); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCsState++; Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); player->actor.shape.rot.y = player->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000; @@ -1550,7 +1550,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { switch (sCsState) { case DEATH_START: - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); func_80064520(play, &play->csCtx); sCsCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); @@ -1613,7 +1613,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { 0x28); this->onCeiling = 2; // Not used by body BossVa_SetDeathEnv(play); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } break; case DEATH_CORE_BURST: @@ -1654,7 +1654,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { camera->at = sCameraAt; - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCsState++; if (!IS_BOSS_RUSH) { @@ -2444,7 +2444,7 @@ void BossVa_BariIntro(BossVa* this, PlayState* play) { switch (sCsState) { case INTRO_LOOK_BARI: if (this->actor.params == BOSSVA_BARI_UPPER_1) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if (Math_SmoothStepToF(&this->actor.world.pos.y, 60.0f, 0.3f, 1.0f, 0.15f) == 0.0f) { this->timer--; if (this->timer == 0) { diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index a06786b2d..1df2325e8 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -880,7 +880,7 @@ void func_80986B2C(PlayState* play) { } play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST); play->transitionTrigger = TRANS_TRIGGER_START; - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } } diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index b43089d9e..34c0a0f20 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -560,7 +560,7 @@ void func_80997220(DoorShutter* this, PlayState* play) { this->dyna.actor.velocity.y = 0.0f; if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { DoorShutter_SetupAction(this, func_80997568); - func_8002DF54(play, NULL, 2); + Player_SetCsActionWithHaltedActors(play, NULL, 2); } } @@ -594,7 +594,7 @@ void func_80997528(DoorShutter* this, PlayState* play) { void func_80997568(DoorShutter* this, PlayState* play) { if (this->unk_16F++ > 30) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); DoorShutter_SetupDoor(this, play); } } diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index bdb154a92..710c138e2 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -499,7 +499,7 @@ void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); player->unk_450.x = this->actor.world.pos.x; player->unk_450.z = this->actor.world.pos.z; @@ -584,7 +584,7 @@ void DoorWarp1_RutoWarpIdle(DoorWarp1* this, PlayState* play) { if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) { this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); this->unk_1B2 = 1; DoorWarp1_SetupAction(this, func_80999EE0); } @@ -706,7 +706,7 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) { player = GET_PLAYER(play); OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); player->unk_450.x = this->actor.world.pos.x; player->unk_450.z = this->actor.world.pos.z; this->unk_1B2 = 20; diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 3fe4e2a22..57cb6045e 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -130,7 +130,7 @@ void func_809B0558(EnAni* this, PlayState* play) { Flags_SetItemGetInf(ITEMGETINF_15); } else { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } } @@ -141,7 +141,7 @@ void func_809B05F0(EnAni* this, PlayState* play) { } if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 76c0feac3..2110383a4 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -295,7 +295,7 @@ void EnBomBowMan_RunGame(EnBomBowlMan* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); if (this->gameResult == 2) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); } this->actionFunc = EnBomBowlMan_HandlePlayChoice; } else { @@ -345,7 +345,7 @@ void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) { Message_ContinueTextbox(play, this->actor.textId); this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowMan_SetupChooseShowPrize; } } else { @@ -381,11 +381,11 @@ void func_809C41FC(EnBomBowlMan* this, PlayState* play) { Message_ContinueTextbox(play, this->actor.textId); this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowMan_SetupChooseShowPrize; } else { if (this->gameResult == 2) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); } this->actionFunc = EnBomBowMan_SetupRunGame; } @@ -509,7 +509,7 @@ void EnBomBowlMan_BeginPlayGame(EnBomBowlMan* this, PlayState* play) { // "Wow" osSyncPrintf(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = EnBomBowMan_SetupRunGame; } } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 5c18c52fa..232b096f9 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -68,7 +68,7 @@ void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { if (((fabsf(chuPosDiff.x) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.y) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.z) < 40.0f) || (BREG(2)))) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); chu->timer = 1; this->camId = Play_CreateSubCamera(play); @@ -107,7 +107,7 @@ void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->unk_154 = TEXT_STATE_EVENT; func_80078884(NA_SE_EV_HIT_SOUND); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->status = 1; this->actionFunc = EnBomBowlPit_CameraDollyIn; break; @@ -167,7 +167,7 @@ void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { Play_ClearCamera(play, this->camId); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowlPit_GivePrize; } } @@ -175,7 +175,7 @@ void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { Player* player = GET_PLAYER(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->getItemId = sGetItemIds[this->prizeIndex]; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; @@ -203,7 +203,7 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; this->actor.parent = NULL; if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } @@ -216,7 +216,7 @@ void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play) { this->actionFunc = EnBomBowlPit_Reset; } else { if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index b2bd6d65c..9869a0621 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -214,7 +214,7 @@ void func_809DF778(EnCow* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_809DF730; } else { - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f); } } @@ -223,7 +223,7 @@ void func_809DF7D8(EnCow* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; Message_CloseTextbox(play); this->actionFunc = func_809DF778; - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c index 8df2f8c0b..715a48c37 100644 --- a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c +++ b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c @@ -470,7 +470,7 @@ void EnDaiku_InitSubCamera(EnDaiku* this, PlayState* play) { Play_CameraSetAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); Play_CameraSetFov(play, this->subCamId, play->mainCamera.fov); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } void EnDaiku_UpdateSubCamera(EnDaiku* this, PlayState* play) { @@ -507,7 +507,7 @@ void EnDaiku_EscapeSuccess(EnDaiku* this, PlayState* play) { Actor_Kill(&this->actor); } } else { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } } diff --git a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c index df00c3cf5..84ac2749d 100644 --- a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c +++ b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c @@ -138,7 +138,7 @@ s32 EnDivingGame_HasMinigameFinished(EnDivingGame* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->unk_292 = TEXT_STATE_EVENT; this->allRupeesThrown = this->state = this->phase = this->unk_2A2 = this->grabbedRupeesCounter = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE048; return true; } else { @@ -163,7 +163,7 @@ s32 EnDivingGame_HasMinigameFinished(EnDivingGame* this, PlayState* play) { this->unk_292 = TEXT_STATE_EVENT; func_800F5B58(); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_SILVER_SCALE)) { this->actionFunc = func_809EE96C; } else { @@ -191,7 +191,7 @@ void EnDivingGame_Talk(EnDivingGame* this, PlayState* play) { if (this->unk_292 != TEXT_STATE_DONE) { switch (this->state) { case ENDIVINGGAME_STATE_NOTPLAYING: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDivingGame_HandlePlayChoice; break; case ENDIVINGGAME_STATE_AWARDPRIZE: @@ -258,7 +258,7 @@ void EnDivingGame_HandlePlayChoice(EnDivingGame* this, PlayState* play) { this->actionFunc = func_809EE048; } else { play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE0FC; } } @@ -270,11 +270,11 @@ void func_809EE048(EnDivingGame* this, PlayState* play) { if (this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { if (this->phase == ENDIVINGGAME_PHASE_ENDED) { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_809EDCB0; } else { play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE0FC; } } @@ -419,7 +419,7 @@ void func_809EE800(EnDivingGame* this, PlayState* play) { func_80088B34(BREG(2) + 50); } func_800F5ACC(NA_BGM_TIMED_MINI_GAME); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.textId = 0x405B; this->unk_292 = TEXT_STATE_EVENT; this->state = ENDIVINGGAME_STATE_PLAYING; @@ -442,7 +442,7 @@ void func_809EE96C(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play))) { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.textId = 0x4056; this->unk_292 = TEXT_STATE_EVENT; this->state = ENDIVINGGAME_STATE_AWARDPRIZE; @@ -456,7 +456,7 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { Message_CloseTextbox(play); this->actor.parent = NULL; if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); @@ -471,7 +471,7 @@ void func_809EEA90(EnDivingGame* this, PlayState* play) { this->actionFunc = func_809EEAF8; } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 933f5be2e..6ea9c26e1 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -391,7 +391,7 @@ void func_809EFDD0(EnDns* this, PlayState* play) { GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } void func_809EFEE8(EnDns* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c index 2864544c5..401ffbef4 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c @@ -126,7 +126,7 @@ void EnDntJiji_Wait(EnDntJiji* this, PlayState* play) { !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { OnePointCutscene_Init(play, 2230, -99, &this->actor, MAIN_CAM); this->timer = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDntJiji_SetupUnburrow; } } @@ -260,9 +260,9 @@ void EnDntJiji_Talk(EnDntJiji* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { func_8005B1A4(GET_ACTIVE_CAM(play)); Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; - func_8002F434(&this->actor, play, this->getItemId, 400.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 400.0f, 200.0f); this->actionFunc = EnDntJiji_SetupGivePrize; } } @@ -272,7 +272,7 @@ void EnDntJiji_SetupGivePrize(EnDntJiji* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = EnDntJiji_GivePrize; } else { - func_8002F434(&this->actor, play, this->getItemId, 400.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 400.0f, 200.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c index f3dff79fe..f96c93695 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c @@ -256,7 +256,7 @@ void EnDntNomal_TargetWait(EnDntNomal* this, PlayState* play) { this->actionFunc = EnDntNomal_TargetGivePrize; } else { OnePointCutscene_Init(play, 4140, -99, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->timer4 = 50; this->actionFunc = EnDntNomal_SetupTargetUnburrow; } @@ -346,7 +346,7 @@ void EnDntNomal_TargetTalk(EnDntNomal* this, PlayState* play) { Message_CloseTextbox(play); func_8005B1A4(GET_ACTIVE_CAM(play)); GET_ACTIVE_CAM(play)->csId = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDntNomal_SetupTargetGivePrize; } } @@ -368,7 +368,7 @@ void EnDntNomal_TargetGivePrize(EnDntNomal* this, PlayState* play) { if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, itemX, itemY, itemZ, 0, 0, 0, EXITEM_BULLET_BAG) == NULL) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); Actor_Kill(&this->actor); } this->spawnedItem = true; diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index d3a0eadea..e94ff9039 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -95,7 +95,7 @@ void EnDs_GiveOddPotion(EnDs* this, PlayState* play) { this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; } else { - func_8002F434(&this->actor, play, GI_ODD_POTION, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_ODD_POTION, 10000.0f, 50.0f); } } @@ -105,7 +105,7 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, PlayState* play) { this->actionFunc = EnDs_GiveOddPotion; u32 itemId = GI_ODD_POTION; if (GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, itemId, 10000.0f, 50.0f); } } } @@ -178,7 +178,7 @@ void EnDs_GiveBluePotion(EnDs* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnDs_Talk; } else { - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); } } @@ -200,7 +200,7 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { GetItemEntry itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; } diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index 9f5ba2b0a..781c09f79 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -362,7 +362,7 @@ void func_809FE3C0(EnDu* this, PlayState* play) { return; } if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } if (this->actor.xzDistToPlayer < 116.0f + this->collider.dim.radius) { @@ -476,7 +476,7 @@ void func_809FE890(EnDu* this, PlayState* play) { CsCmdActorAction* csAction; if (play->csCtx.state == CS_STATE_IDLE) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); EnDu_SetupAction(this, func_809FEB08); return; } @@ -549,7 +549,7 @@ void func_809FEB08(EnDu* this, PlayState* play) { this->unk_1EE = 0; if (this->unk_1E8 == 1) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENDU_ANIM_1); EnDu_SetupAction(this, func_809FE3C0); return; @@ -569,7 +569,7 @@ void func_809FEB08(EnDu* this, PlayState* play) { void func_809FEC14(EnDu* this, PlayState* play) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); EnDu_SetupAction(this, func_809FEC70); func_809FEC70(this, play); } @@ -582,7 +582,7 @@ void func_809FEC70(EnDu* this, PlayState* play) { } else { f32 xzRange = this->actor.xzDistToPlayer + 1.0f; - func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); + Actor_OfferGetItem(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index f996fe6c1..e08e794a3 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -677,7 +677,7 @@ void func_80A0329C(EnElf* this, PlayState* play) { if (!(this->fairyFlags & FAIRY_FLAG_BIG)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 80.0f, 60.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 80.0f, 60.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index a3a196e31..03b343527 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -400,7 +400,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { s32 getItemId; this->actor.draw = NULL; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; if (IS_RANDO) { GET_PLAYER(play)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); @@ -415,7 +415,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { } if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); } @@ -429,7 +429,7 @@ void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { } else { if (!IS_RANDO) { s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); diff --git a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c index e777d993f..1bd8e3202 100644 --- a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c +++ b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c @@ -716,7 +716,7 @@ void EnFish_OrdinaryUpdate(EnFish* this, PlayState* play) { EnFish_BeginRespawn(this); } else if (EnFish_InBottleRange(this, play)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 80.0f, 20.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 80.0f, 20.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index d8ef93a6e..646fc5668 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -1020,7 +1020,7 @@ void EnFr_Deactivate(EnFr* this, PlayState* play) { } else { this->actionFunc = EnFr_GiveReward; if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { - func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, this->reward, 30.0f, 100.0f); } } } @@ -1030,7 +1030,7 @@ void EnFr_GiveReward(EnFr* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnFr_SetIdle; } else { - func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, this->reward, 30.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c index 53c149026..fb37cf0af 100644 --- a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c +++ b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c @@ -360,7 +360,7 @@ void func_80A2FA50(EnGb* this, PlayState* play) { void func_80A2FB40(EnGb* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { if (!IS_RANDO) { - func_8002F434(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); + Actor_OfferGetItem(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE); GiveItemEntryFromActor(&this->dyna.actor, play, getItemEntry, 100.0f, 10.0f); @@ -375,7 +375,7 @@ void func_80A2FBB0(EnGb* this, PlayState* play) { this->actionFunc = func_80A2FC0C; } else { if (!IS_RANDO) { - func_8002F434(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); + Actor_OfferGetItem(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE); GiveItemEntryFromActor(&this->dyna.actor, play, getItemEntry, 100.0f, 10.0f); diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 92a768205..c72205b8f 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -281,7 +281,7 @@ void EnGe1_KickPlayer(EnGe1* this, PlayState* play) { void EnGe1_SpotPlayer(EnGe1* this, PlayState* play) { this->cutsceneTimer = 30; this->actionFunc = EnGe1_KickPlayer; - func_8002DF54(play, &this->actor, 0x5F); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x5F); func_80078884(NA_SE_SY_FOUND); Message_StartTextbox(play, 0x6000, &this->actor); } @@ -573,7 +573,7 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { } if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } @@ -614,7 +614,7 @@ void EnGe1_BeginGiveItem_Archery(EnGe1* this, PlayState* play) { } if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } @@ -662,7 +662,7 @@ void EnGe1_BeginGame_Archery(EnGe1* this, PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY); if (!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } else { horse = Actor_FindNearby(play, &player->actor, ACTOR_EN_HORSE, ACTORCAT_BG, 1200.0f); player->actor.freezeTimer = 1200; diff --git a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 01e0e0176..5602dd883 100644 --- a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -472,7 +472,7 @@ void EnGe2_WaitTillCardGiven(EnGe2* this, PlayState* play) { this->actionFunc = EnGe2_SetActionAfterTalk; } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -486,7 +486,7 @@ void EnGe2_GiveCard(EnGe2* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe2_WaitTillCardGiven; if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -510,7 +510,7 @@ void EnGe2_SetupCapturePlayer(EnGe2* this, PlayState* play) { this->stateFlags |= GE2_STATE_CAPTURING; this->actor.speedXZ = 0.0f; EnGe2_ChangeAction(this, GE2_ACTION_CAPTURETURN); - func_8002DF54(play, &this->actor, 95); + Player_SetCsActionWithHaltedActors(play, &this->actor, 95); func_80078884(NA_SE_SY_FOUND); Message_StartTextbox(play, 0x6000, &this->actor); } diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index 90d2981f0..aaa198060 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -145,7 +145,7 @@ void EnGe3_WaitTillCardGiven(EnGe3* this, PlayState* play) { this->actionFunc = EnGe3_Wait; } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -159,7 +159,7 @@ void EnGe3_GiveCard(EnGe3* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe3_WaitTillCardGiven; if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -172,7 +172,7 @@ void EnGe3_ForceTalk(EnGe3* this, PlayState* play) { this->actionFunc = EnGe3_GiveCard; } else { if (!(this->unk_30C & 4)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->unk_30C |= 4; } this->actor.textId = 0x6004; diff --git a/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c b/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c index 4ed0e52ee..293f19669 100644 --- a/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c +++ b/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c @@ -918,7 +918,7 @@ void EnGeldB_SpinAttack(EnGeldB* this, PlayState* play) { if (&player->actor == this->swordCollider.base.at) { func_8002F71C(play, &this->actor, 6.0f, this->actor.yawTowardsPlayer, 6.0f); this->spinAttackState = 2; - func_8002DF54(play, &this->actor, 0x18); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x18); Message_StartTextbox(play, 0x6003, &this->actor); this->timer = 30; this->actor.speedXZ = 0.0f; diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 22754a87a..7174a63f1 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -250,7 +250,7 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { this->actionFunc = func_80A3DD7C; } else { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } this->actionFunc = func_80A3DF00; @@ -270,7 +270,7 @@ void func_80A3DF00(EnGm* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_80A3DF60; } else { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 3ec88fb74..20d1c5326 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -229,7 +229,7 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { talkState = NPC_TALK_STATE_IDLE; break; case 0x3036: - func_8002F434(thisx, play, GI_TUNIC_GORON, xzRange, yRange); + Actor_OfferGetItem(thisx, play, GI_TUNIC_GORON, xzRange, yRange); Flags_SetInfTable(INFTABLE_10D); // EnGo exclusive flag talkState = NPC_TALK_STATE_ACTION; break; @@ -975,7 +975,7 @@ void EnGo_GetItem(EnGo* this, PlayState* play) { yDist = fabsf(this->actor.yDistToPlayer) + 1.0f; xzDist = this->actor.xzDistToPlayer + 1.0f; - func_8002F434(&this->actor, play, getItemId, xzDist, yDist); + Actor_OfferGetItem(&this->actor, play, getItemId, xzDist, yDist); } } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 783ada21a..47d1d7b0d 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -284,7 +284,7 @@ s32 EnGo2_SpawnDust(EnGo2* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 void EnGo2_GetItem(EnGo2* this, PlayState* play, s32 getItemId) { this->getItemId = getItemId; if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, this)) { - func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, + Actor_OfferGetItem(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } } @@ -1799,7 +1799,7 @@ void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnGo2_SetGetItem; } else { - func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } } @@ -1936,7 +1936,7 @@ void EnGo2_GoronFireGenericAction(EnGo2* this, PlayState* play) { (f32)((Math_SinS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.x); player->actor.world.pos.z = (f32)((Math_CosS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.z); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Audio_PlayFanfare(NA_BGM_APPEAR); } break; @@ -1973,7 +1973,7 @@ void EnGo2_GoronFireGenericAction(EnGo2* this, PlayState* play) { case 4: // Finalize walking away Message_CloseTextbox(play); EnGo2_GoronFireClearCamera(this, play); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Actor_Kill(&this->actor); break; case 1: diff --git a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c index ed924dd3c..5b5a97a08 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c +++ b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c @@ -391,7 +391,7 @@ void EnHeishi1_WaitNight(EnHeishi1* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi1_SetupKick; } } @@ -475,7 +475,7 @@ void EnHeishi1_Update(Actor* thisx, PlayState* play) { func_80078884(NA_SE_SY_FOUND); // "Discovered!" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sHeishi1PlayerIsCaught = true; this->actionFunc = EnHeishi1_SetupMoveToLink; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c index 379ce2893..89dcc6808 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c +++ b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c @@ -112,7 +112,7 @@ void EnHeishi2_Init(Actor* thisx, PlayState* play) { this->actor.world.pos.z += 90.0f; this->actor.shape.rot.y = this->actor.world.rot.y; Collider_DestroyCylinder(play, &this->collider); - func_8002DF54(play, 0, 8); + Player_SetCsActionWithHaltedActors(play, 0, 8); this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actionFunc = func_80A544AC; } @@ -265,7 +265,7 @@ void func_80A5344C(EnHeishi2* this, PlayState* play) { void func_80A53538(EnHeishi2* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (this->unk_300 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); play->msgCtx.msgMode = MSGMODE_PAUSED; this->actionFunc = func_80A535BC; } @@ -337,7 +337,7 @@ void func_80A53850(EnHeishi2* this, PlayState* play) { Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Message_CloseTextbox(play); this->unk_30C = 1; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A531E4; } } @@ -426,7 +426,7 @@ void func_80A53AD4(EnHeishi2* this, PlayState* play) { void func_80A53C0C(EnHeishi2* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->unk_300 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { - func_8002DF54(play, 0, 8); + Player_SetCsActionWithHaltedActors(play, 0, 8); play->msgCtx.msgMode = MSGMODE_PAUSED; this->actionFunc = func_80A53C90; } @@ -510,7 +510,7 @@ void func_80A53F30(EnHeishi2* this, PlayState* play) { this->actionFunc = func_80A54038; } else { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A53908; } } else { @@ -528,7 +528,7 @@ void func_80A54038(EnHeishi2* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); Message_CloseTextbox(play); - func_8002DF54(play, 0, 7); + Player_SetCsActionWithHaltedActors(play, 0, 7); this->actionFunc = func_80A53908; } } @@ -653,7 +653,7 @@ void func_80A5455C(EnHeishi2* this, PlayState* play) { EnBom* bomb; if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); Message_CloseTextbox(play); pos.x = Rand_CenteredFloat(20.0f) + this->unk_274.x; diff --git a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c index 3ccc932ca..665a06470 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c +++ b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c @@ -137,7 +137,7 @@ void EnHeishi3_StandSentinelInGrounds(EnHeishi3* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi3_CatchStart; } } @@ -165,7 +165,7 @@ void EnHeishi3_StandSentinelInCastle(EnHeishi3* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi3_CatchStart; } } diff --git a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c index 391d7dc5d..d3b81c3d2 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c +++ b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c @@ -270,7 +270,7 @@ void func_80A56994(EnHeishi4* this, PlayState* play) { if ((this->unk_282 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); Flags_SetInfTable(INFTABLE_6C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A56A50; } } @@ -288,7 +288,7 @@ void func_80A56ACC(EnHeishi4* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (this->unk_288 <= currentFrame) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A5673C; } } diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index c8d70fe1f..eb3556a6e 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -162,7 +162,7 @@ void func_80A6E740(EnHs* this, PlayState* play) { Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); func_80A6E3A0(this, func_80A6E630); } else { - func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } this->unk_2A8 |= 1; @@ -174,7 +174,7 @@ void func_80A6E7BC(EnHs* this, PlayState* play) { case 0: func_80A6E3A0(this, func_80A6E740); if (GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { - func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } break; case 1: diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index e0ff7470d..6d8640f3f 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -411,7 +411,7 @@ s32 EnHy_IsOsAnimeObjectLoaded(EnHy* this, PlayState* play) { void func_80A6F7CC(EnHy* this, PlayState* play, s32 getItemId) { this->unkGetItemId = getItemId; - func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, + Actor_OfferGetItem(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } @@ -1069,7 +1069,7 @@ void func_80A714C4(EnHy* this, PlayState* play) { this->actionFunc = func_80A71530; } else { if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); + Actor_OfferGetItem(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } else { GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } diff --git a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c index f412e7398..3503aef08 100644 --- a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c +++ b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c @@ -216,7 +216,7 @@ void EnIceHono_CapturableFlame(EnIceHono* this, PlayState* play) { this->actor.parent = NULL; } else if (EnIceHono_InBottleRange(this, play)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 60.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 60.0f, 100.0f); } if (this->actor.xzDistToPlayer < 200.0f) { diff --git a/soh/src/overlays/actors/ovl_En_In/z_en_in.c b/soh/src/overlays/actors/ovl_En_In/z_en_in.c index 1d0866e6d..6edf01333 100644 --- a/soh/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/soh/src/overlays/actors/ovl_En_In/z_en_in.c @@ -434,7 +434,7 @@ void func_80A79BAC(EnIn* this, PlayState* play, s32 index, u32 transitionType) { } play->transitionType = transitionType; play->transitionTrigger = TRANS_TRIGGER_START; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Interface_ChangeAlpha(1); if (index == 0) { AREG(6) = 0; @@ -856,7 +856,7 @@ void func_80A7ABD4(EnIn* this, PlayState* play) { void func_80A7AE84(EnIn* this, PlayState* play) { Play_ChangeCameraStatus(play, this->activeCamId, CAM_STAT_ACTIVE); Play_ClearCamera(play, this->camId); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Interface_ChangeAlpha(0x32); this->actionFunc = func_80A7AEF0; } diff --git a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c index 393e10a91..862b6f92b 100644 --- a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c +++ b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c @@ -786,7 +786,7 @@ void EnInsect_Update(Actor* thisx, PlayState* play) { if (!(this->unk_314 & 8) && D_80A7DEB4 < 4 && EnInsect_InBottleRange(this, play) && // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 60.0f, 30.0f)) { + Actor_OfferGetItem(&this->actor, play, GI_MAX, 60.0f, 30.0f)) { D_80A7DEB4++; } } diff --git a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index af10aa086..c79033250 100644 --- a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -379,9 +379,9 @@ void EnIshi_Wait(EnIshi* this, PlayState* play) { if (this->actor.xzDistToPlayer < 90.0f) { // GI_NONE in these cases allows the player to lift the actor if (type == ROCK_LARGE) { - func_8002F434(&this->actor, play, GI_NONE, 80.0f, 20.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 80.0f, 20.0f); } else { - func_8002F434(&this->actor, play, GI_NONE, 50.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 50.0f, 10.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index 793017d3d..1baf3413a 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -136,7 +136,7 @@ void func_80A89160(EnJs* this, PlayState* play) { GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c index cf2f4499b..99cc81540 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c @@ -260,7 +260,7 @@ void func_80A8F8D0(EnKakasi* this, PlayState* play) { void func_80A8F9C8(EnKakasi* this, PlayState* play) { func_80A8F28C(this); SkelAnime_Update(&this->skelanime); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (this->unk_196 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { @@ -269,7 +269,7 @@ void func_80A8F9C8(EnKakasi* this, PlayState* play) { } this->camId = OnePointCutscene_Init(play, 2270, -99, &this->actor, MAIN_CAM); play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_8010BD58(play, OCARINA_ACTION_SCARECROW_LONG_PLAYBACK); this->actionFunc = func_80A8FAA4; } @@ -308,7 +308,7 @@ void func_80A8FBB8(EnKakasi* this, PlayState* play) { if (this->unk_196 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { func_8005B1A4(play->cameraPtrs[this->camId]); Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A8F660; } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c index 37b6236a5..9cb4e5de5 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c @@ -296,7 +296,7 @@ void func_80A91620(EnKakasi3* this, PlayState* play) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_03 && play->msgCtx.msgMode == MSGMODE_NONE) { this->dialogState = TEXT_STATE_EVENT; Message_StartTextbox(play, 0x40A5, NULL); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -354,7 +354,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_EndCutscene(play, this->camId); this->camId = SUBCAM_NONE; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -370,7 +370,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { this->unk_195 = true; Message_StartTextbox(play, 0x40A7, NULL); this->dialogState = TEXT_STATE_EVENT; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -384,7 +384,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { void func_80A91A90(EnKakasi3* this, PlayState* play) { func_80A90E28(this); SkelAnime_Update(&this->skelAnime); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (this->dialogState == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { if (this->unk_195) { @@ -400,7 +400,7 @@ void func_80A91A90(EnKakasi3* this, PlayState* play) { } Message_CloseTextbox(play); play->msgCtx.ocarinaMode = OCARINA_MODE_04; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A911F0; } } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index c801356c9..4e83742c3 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1215,7 +1215,7 @@ void func_80A99504(EnKo* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { - func_8002F434(&this->actor, play, GI_SAW, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SAW, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index 3d5c2c354..9ee9f6d0a 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -396,7 +396,7 @@ void EnKz_SetupMweep(EnKz* this, PlayState* play) { initPos.y += -100.0f; initPos.z += 260.0f; Play_CameraSetAtEye(play, this->cutsceneCamera, &pos, &initPos); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->actor.speedXZ = 0.1f * CVarGetInteger("gMweepSpeed", 1); this->actionFunc = EnKz_Mweep; } @@ -428,7 +428,7 @@ void EnKz_Mweep(EnKz* this, PlayState* play) { void EnKz_StopMweep(EnKz* this, PlayState* play) { Play_ChangeCameraStatus(play, this->gameplayCamera, CAM_STAT_ACTIVE); Play_ClearCamera(play, this->cutsceneCamera); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = EnKz_Wait; } @@ -463,7 +463,7 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; yRange = fabsf(this->actor.yDistToPlayer) + 1.0f; xzRange = this->actor.xzDistToPlayer + 1.0f; - func_8002F434(&this->actor, play, getItemId, xzRange, yRange); + Actor_OfferGetItem(&this->actor, play, getItemId, xzRange, yRange); } } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 3edae9858..267a49bcd 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -335,7 +335,7 @@ void func_80AA0EA0(EnMa1* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_80AA0EFC; } else { - func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index eac914089..64510807c 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -102,7 +102,7 @@ void func_80AACA94(EnMk* this, PlayState* play) { gSaveContext.eventInf[1] &= ~1; } } else { - func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } @@ -110,7 +110,7 @@ void func_80AACB14(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACA94; if (GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { - func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } } @@ -205,7 +205,7 @@ void func_80AACFA0(EnMk* this, PlayState* play) { this->actionFunc = func_80AACA40; Flags_SetItemGetInf(ITEMGETINF_10); } else { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } @@ -213,7 +213,7 @@ void func_80AAD014(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACFA0; if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index 72b84db3b..244be5cde 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -134,7 +134,7 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) { - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_BEAN, 90.0f, 10.0f); this->actionFunc = EnMs_Sell; } return; @@ -152,7 +152,7 @@ void EnMs_Sell(EnMs* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnMs_TalkAfterPurchase; } else { - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_BEAN, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c index 91730e5bf..0497b82e9 100644 --- a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c +++ b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c @@ -467,7 +467,7 @@ void func_80AB6450(EnNiw* this, PlayState* play) { this->actionFunc = func_80AB6BF8; } else { // GI_NONE in this case allows the player to lift the actor - func_8002F434(&this->actor, play, GI_NONE, 25.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 25.0f, 10.0f); func_80AB5BF8(this, play, 1); } } diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index b4e6d8892..612abcf0e 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -314,7 +314,7 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) { this->getItemId = GI_BOTTLE; - func_8002F434(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); } else { // Circumvent the item offer action this->actionFunc = func_80ABAC84; @@ -327,7 +327,7 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) { } if (this->unk_26C == 1) { this->getItemId = GI_RUPEE_PURPLE; - func_8002F434(&this->actor, play, GI_RUPEE_PURPLE, 100.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_RUPEE_PURPLE, 100.0f, 50.0f); this->actionFunc = func_80ABAC00; } this->actionFunc = func_80ABA244; @@ -405,7 +405,7 @@ void func_80ABA9B8(EnNiwLady* this, PlayState* play) { this->actor.parent = NULL; if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) { - func_8002F434(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); this->actionFunc = func_80ABAC00; } else { // Circumvent the item offer action @@ -440,7 +440,7 @@ void func_80ABAB08(EnNiwLady* this, PlayState* play) { Message_CloseTextbox(play); this->actor.parent = NULL; if (GameInteractor_Should(GI_VB_TRADE_POCKET_CUCCO, true, this)) { - func_8002F434(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); this->actionFunc = func_80ABAC00; } else { // Circumvent the item offer action @@ -471,7 +471,7 @@ void func_80ABAC00(EnNiwLady* this, PlayState* play) { if (LINK_IS_ADULT) { getItemId = !Flags_GetItemGetInf(ITEMGETINF_2C) ? GI_POCKET_EGG : GI_COJIRO; } - func_8002F434(&this->actor, play, getItemId, 200.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 200.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 34ef24e40..a2c1f5f9a 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -1389,7 +1389,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) { osSyncPrintf("\n" VT_FGCOL(YELLOW) "初めて手にいれた!!" VT_RST "\n\n"); if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } else { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items @@ -1398,7 +1398,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 120.0f); } else { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } } play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; @@ -1736,7 +1736,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p return; } if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } else { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items @@ -1746,7 +1746,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 120.0f); } else { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 4ae7d366f..d46424b0b 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -345,7 +345,7 @@ void func_80ACA71C(EnOwl* this) { } void func_80ACA76C(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); @@ -355,7 +355,7 @@ void func_80ACA76C(EnOwl* this, PlayState* play) { } void func_80ACA7E0(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); @@ -565,7 +565,7 @@ void EnOwl_WaitLakeHylia(EnOwl* this, PlayState* play) { } void func_80ACB03C(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 5bbeb8efe..344a09f19 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1040,7 +1040,7 @@ void EnSkj_SariaSongTalk(EnSkj* this, PlayState* play) { } else { func_80AFFE24(this); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1056,7 +1056,7 @@ void func_80AFFE44(EnSkj* this, PlayState* play) { EnSkj_SetupPostSariasSong(this); } else { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1080,7 +1080,7 @@ void EnSkj_SetupMaskTrade(EnSkj* this) { void EnSkj_StartMaskTrade(EnSkj* this, PlayState* play) { u8 sp1F = Message_GetState(&play->msgCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if ((sp1F == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { EnSkj_JumpFromStump(this); } @@ -1178,7 +1178,7 @@ void EnSkj_SetupWaitForMaskTextClear(EnSkj* this) { void EnSkj_WaitForMaskTextClear(EnSkj* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->backflipFlag = 1; EnSkj_Backflip(this); } @@ -1553,7 +1553,7 @@ void EnSkj_WaitToGiveReward(EnSkj* this, PlayState* play) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); } else { - func_8002F434(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); + Actor_OfferGetItem(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); } this->actionFunc = EnSkj_GiveOcarinaGameReward; @@ -1569,7 +1569,7 @@ void EnSkj_GiveOcarinaGameReward(EnSkj* this, PlayState* play) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); } else { - func_8002F434(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); + Actor_OfferGetItem(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index 908a1af96..7a0332910 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -302,7 +302,7 @@ void EnSth_GivePlayerItem(EnSth* this, PlayState* play) { } if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index d84298800..a406049a9 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -387,7 +387,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { } } if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } this->actionFunc = EnSyatekiMan_GivePrize; break; @@ -421,7 +421,7 @@ void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { this->actionFunc = EnSyatekiMan_FinishPrize; } else { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index d62e6ddfc..85f5053d1 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -707,7 +707,7 @@ void func_80B154FC(EnTa* this, PlayState* play) { switch (EnTa_GetSuperCuccosCount(this, play)) { case 1: gSaveContext.timer1State = 0; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Message_StartTextbox(play, 0x2084, &this->actor); this->actionFunc = func_80B15424; @@ -749,7 +749,7 @@ void func_80B154FC(EnTa* this, PlayState* play) { this->unk_2E0 &= ~0x200; func_80078884(NA_SE_SY_FOUND); gSaveContext.timer1State = 0; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Message_StartTextbox(play, 0x2081, &this->actor); this->actionFunc = func_80B15424; func_80B14E28(this, play); @@ -802,7 +802,7 @@ void func_80B1585C(EnTa* this, PlayState* play) { Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim) - 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, 10.0f); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } } @@ -817,7 +817,7 @@ void func_80B15AD4(EnTa* this, PlayState* play) { func_800F5ACC(NA_BGM_TIMED_MINI_GAME); this->unk_2E0 |= 0x200; Message_CloseTextbox(play); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { @@ -877,10 +877,10 @@ void func_80B15E80(EnTa* this, PlayState* play) { } this->unk_2E0 &= ~0x2; } else if (this->unk_2E0 & 2) { - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -895,7 +895,7 @@ void func_80B15F54(EnTa* this, PlayState* play) { this->unk_2E0 &= ~0x2; func_80B13AA0(this, func_80B15E80, func_80B16938); if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); @@ -923,7 +923,7 @@ void func_80B15FE8(EnTa* this, PlayState* play) { GetItemEntry itemEntry = ItemTable_Retrieve(GI_MILK); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); break; } break; @@ -1014,7 +1014,7 @@ void func_80B1642C(EnTa* this, PlayState* play) { Message_CloseTextbox(play); this->unk_2E0 |= 2; func_80B13AA0(this, func_80B15E80, func_80B16938); - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { Message_ContinueTextbox(play, 0x208A); func_80B13AA0(this, func_80B15E28, func_80B16938); diff --git a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c index f614e0f4c..e15d481fd 100644 --- a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c +++ b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c @@ -147,7 +147,7 @@ void func_80B17934(EnTakaraMan* this, PlayState* play) { Rupees_ChangeBy(-10); this->unk_214 = 1; this->actor.parent = NULL; - func_8002F434(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); this->actionFunc = func_80B17A6C; } else { Message_CloseTextbox(play); @@ -172,7 +172,7 @@ void func_80B17A6C(EnTakaraMan* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80B17AC4; } else { - func_8002F434(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index c2ac2861b..275b62ba1 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -317,7 +317,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { this->unk_1E4 = 5; Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); } else { - func_8002F434(&this->actor, play, GI_SWORD_BROKEN, 100.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_SWORD_BROKEN, 100.0f, 10.0f); } return; } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index 658dd63f8..5aeb0a86b 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -196,7 +196,7 @@ void func_80B3A3D4(EnWonderTalk2* this, PlayState* play) { } this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED); if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); } this->unk_156 = true; this->actionFunc = func_80B3A4F8; @@ -257,7 +257,7 @@ void func_80B3A4F8(EnWonderTalk2* this, PlayState* play) { if (!this->unk_156) { if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { Message_StartTextbox(play, this->actor.textId, NULL); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); } this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actionFunc = func_80B3A3D4; diff --git a/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c b/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c index 133556f52..7234ed57f 100644 --- a/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c +++ b/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c @@ -421,7 +421,7 @@ void func_80B4BBC4(EnZl1* this, PlayState* play) { Player* player = GET_PLAYER(play); Animation_Change(&this->skelAnime, &gChildZelda1Anim_00438, 1.0f, 0.0f, frameCount, ANIMMODE_LOOP, 0.0f); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Player_PlaySfx(&player->actor, NA_SE_VO_LI_SURPRISE_KID); this->actor.textId = 0x7039; Message_StartTextbox(play, this->actor.textId, NULL); @@ -510,7 +510,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { if ((Message_GetState(msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { this->actor.textId = 0xFFFF; play->talkWithPlayer(play, &this->actor); - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.stateTimer = 4; this->unk_1E2++; @@ -525,7 +525,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { this->actor.parent = NULL; this->unk_1E2++; } else { - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); } break; case 3: @@ -554,7 +554,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { break; case 6: if (Actor_TextboxIsClosing(&this->actor, play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Interface_ChangeAlpha(50); this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO; this->unk_1E2 = 4; diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index f805e2fb5..f2abefd97 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -325,7 +325,7 @@ s32 EnZl4_SetupFromLegendCs(EnZl4* this, PlayState* play) { Actor* playerx = &GET_PLAYER(play)->actor; s16 rotY; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); playerx->world.pos = this->actor.world.pos; rotY = this->actor.shape.rot.y; playerx->world.pos.x += 56.0f * Math_SinS(rotY); @@ -911,7 +911,7 @@ s32 EnZl4_CsLookWindow(EnZl4* this, PlayState* play) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardGanonCs); gSaveContext.cutsceneTrigger = 1; this->talkState++; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } break; case 2: @@ -921,7 +921,7 @@ s32 EnZl4_CsLookWindow(EnZl4* this, PlayState* play) { } } else { func_800AA000(0.0f, 0xA0, 0xA, 0x28); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_30); EnZl4_SetCsCameraAngle(play, 11); Message_StartTextbox(play, 0x7039, NULL); @@ -1109,7 +1109,7 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { this->talkState = 7; play->talkWithPlayer(play, &this->actor); if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } play->msgCtx.stateTimer = 4; @@ -1121,7 +1121,7 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->talkState++; } else { - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } // no break here is required for matching @@ -1189,7 +1189,7 @@ void EnZl4_Cutscene(EnZl4* this, PlayState* play) { break; case ZL4_CS_PLAN: if (EnZl4_CsMakePlan(this, play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); gSaveContext.unk_13EE = 0x32; Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); this->actionFunc = EnZl4_Idle; diff --git a/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c b/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c index 9212362d6..0601a7f5b 100644 --- a/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c +++ b/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c @@ -153,7 +153,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { break; } func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE); @@ -193,7 +193,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_GROAN); } if (this->timers[0] == 20) { - func_8002DF54(play, &this->actor, 9); + Player_SetCsActionWithHaltedActors(play, &this->actor, 9); } if (this->timers[0] == 1) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_OPENING_GANON); @@ -354,7 +354,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { this->bossGndSignal = FHG_FINISH; } if (this->timers[0] == 170) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC2); } Math_ApproachF(&this->cameraEye.z, this->cameraPanZ + (GND_BOSSROOM_CENTER_Z + 100.0f), 0.1f, @@ -401,7 +401,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { func_800C08AC(play, this->cutsceneCamera, 0); this->cutsceneCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = EnfHG_Retreat; } break; diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 48d85723e..8b7c77aca 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -5160,7 +5160,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { this->actor.parent = NULL; if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); } @@ -5215,7 +5215,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { this->stateAndTimer = 24; } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_GOLD, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_SCALE_GOLD, 2000.0f, 1000.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); @@ -5572,7 +5572,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { sSubCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); mainCam = Play_GetCamera(play, MAIN_CAM); sCameraEye.x = mainCam->eye.x; sCameraEye.y = mainCam->eye.y; @@ -5604,7 +5604,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { mainCam->at = sCameraAt; func_800C08AC(play, sSubCamId, 0); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sFishingPlayerCinematicState = 0; sSubCamId = 0; sFishingCinematicTimer = 30; @@ -5620,7 +5620,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { sSubCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); mainCam = Play_GetCamera(play, MAIN_CAM); sCameraEye.x = mainCam->eye.x; sCameraEye.y = mainCam->eye.y; @@ -5639,7 +5639,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { if ((sFishingCinematicTimer == 0) && Message_ShouldAdvance(play)) { sFishingPlayerCinematicState = 22; sFishingCinematicTimer = 40; - func_8002DF54(play, &this->actor, 0x1C); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x1C); sSinkingLureHeldY = 0.0f; } break; @@ -5708,7 +5708,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { mainCam->at = sCameraAt; func_800C08AC(play, sSubCamId, 0); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sFishingPlayerCinematicState = 0; sSubCamId = 0; player->unk_860 = -5; diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index f511d5bbf..5015a3908 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -59,7 +59,7 @@ void ItemBHeart_Update(Actor* thisx, PlayState* play) { Flags_SetCollectible(play, 0x1F); Actor_Kill(&this->actor); } else { - func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); + Actor_OfferGetItem(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); } } diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index b12d7b4b0..6fdf162db 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -134,7 +134,7 @@ void func_80B85824(ItemEtcetera* this, PlayState* play) { Actor_Kill(&this->actor); } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); @@ -157,7 +157,7 @@ void func_80B858B4(ItemEtcetera* this, PlayState* play) { if (0) {} // Necessary to match if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index dba879115..d14862553 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -190,7 +190,7 @@ void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) { this->actor.draw = NULL; } else { if (GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) { - func_8002F434(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); } if ((play->gameplayFrames & 13) == 0) { diff --git a/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c b/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c index e54b343fc..beecbf759 100644 --- a/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c +++ b/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c @@ -103,7 +103,7 @@ void func_80B86AC8(ItemShield* this, PlayState* play) { Actor_Kill(&this->actor); return; } - func_8002F434(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); Actor_UpdateBgCheckInfo(play, &this->actor, 10.0f, 10.0f, 0.0f, 5); if (this->actor.bgCheckFlags & 1) { this->timer--; @@ -125,7 +125,7 @@ void func_80B86BC8(ItemShield* this, PlayState* play) { Actor_Kill(&this->actor); return; } - func_8002F434(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); if (this->collider.base.acFlags & AC_HIT) { ItemShield_SetupAction(this, func_80B86AC8); this->actor.velocity.y = 4.0f; diff --git a/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c b/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c index 2346b34ff..0dd03a5be 100644 --- a/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c +++ b/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c @@ -274,7 +274,7 @@ void ObjTsubo_Idle(ObjTsubo* this, PlayState* play) { phi_v1 = ABS(temp_v0); if (phi_v1 >= 0x5556) { // GI_NONE in this case allows the player to lift the actor - func_8002F434(&this->actor, play, GI_NONE, 30.0f, 30.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 30.0f, 30.0f); } } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 2bb2b04fd..7125500f7 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11477,11 +11477,11 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { CsCmdActorAction* linkActionCsCmd = play->csCtx.linkAction; if ((linkActionCsCmd != NULL) && (D_808547C4[linkActionCsCmd->action] != 0)) { - func_8002DF54(play, NULL, 6); + Player_SetCsActionWithHaltedActors(play, NULL, 6); Player_ZeroSpeedXZ(this); } else if ((this->csAction == 0) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER) && (play->csCtx.state != CS_STATE_UNSKIPPABLE_INIT)) { - func_8002DF54(play, NULL, 0x31); + Player_SetCsActionWithHaltedActors(play, NULL, 0x31); Player_ZeroSpeedXZ(this); } } @@ -15342,7 +15342,7 @@ void func_808515A4(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80851688(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (func_8084B3CC(play, this) == 0) { if ((this->csAction == 0x31) && (play->csCtx.state == CS_STATE_IDLE)) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); return; } @@ -15923,7 +15923,7 @@ void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) { s32 sp24; if (play->csCtx.state == CS_STATE_UNSKIPPABLE_INIT) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->cueId = 0; Player_ZeroSpeedXZ(this); return; @@ -16065,7 +16065,7 @@ void Player_StartTalking(PlayState* play, Actor* actor) { this->exchangeItemId = EXCH_ITEM_NONE; if (actor->textId == 0xFFFF) { - func_8002DF54(play, actor, 1); + Player_SetCsActionWithHaltedActors(play, actor, 1); actor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO; func_80832528(play, this); } else { From d6c512904bee3563dd559682febc8c8a16ba98cc Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 3 Apr 2024 21:11:13 -0400 Subject: [PATCH 126/300] vb target in woods (#95) * do some target in woods VB stuff * skip deku scrub hopping out animation * replace a couple IS_RANDOs * cleanup --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 1 + .../Enhancements/timesaver_hook_handlers.cpp | 8 ++++ .../actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c | 3 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 40 ++++++++----------- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 478f82712..c61a82760 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -290,6 +290,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, // Opt: *EnSyatekiMan GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, + // Opt: *EnExItem + GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 35031690e..ea3755a69 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -767,6 +767,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: + case GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: case GI_VB_GIVE_ITEM_FROM_GORON: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 02decd7ba..8e733b427 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -296,6 +296,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = false; break; } + case ACTOR_EN_EX_ITEM: { + *should = false; + break; + } + case ACTOR_EN_DNT_NOMAL: { + *should = false; + break; + } case ACTOR_EN_TA: case ACTOR_DOOR_SHUTTER: case ACTOR_BG_ICE_SHUTTER: diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c index f96c93695..102a904cf 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c @@ -12,6 +12,7 @@ #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "objects/object_hintnuts/object_hintnuts.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -252,7 +253,7 @@ void EnDntNomal_TargetWait(EnDntNomal* this, PlayState* play) { if (!LINK_IS_ADULT && !Flags_GetItemGetInf(ITEMGETINF_1D)) { this->hitCounter++; if (this->hitCounter >= 3) { - if(IS_RANDO) { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { this->actionFunc = EnDntNomal_TargetGivePrize; } else { OnePointCutscene_Init(play, 4140, -99, &this->actor, MAIN_CAM); diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 03b343527..32f50d9e1 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -8,6 +8,7 @@ #include "overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -376,7 +377,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { Math_SmoothStepToS(&this->actor.shape.rot.y, -0x4000, 5, 0x1000, 0); } - if (!IS_RANDO && this->timer != 0) { + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor) && this->timer != 0) { if (this->prizeRotateTimer != 0) { tmpf1 = play->view.lookAt.x - play->view.eye.x; tmpf2 = play->view.lookAt.y - 10.0f - play->view.eye.y; @@ -396,50 +397,41 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { this->actor.world.pos.z += (tmpf3 / tmpf4) * 5.0f; } } else { - GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; s32 getItemId; this->actor.draw = NULL; Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; - if (IS_RANDO) { + + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { GET_PLAYER(play)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - getItemId = getItemEntry.getItemId; - } else { - if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { - getItemId = GI_BULLET_BAG_40; - } else { - getItemId = GI_BULLET_BAG_50; - } } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); + if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { + getItemId = GI_BULLET_BAG_40; } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); + getItemId = GI_BULLET_BAG_50; } + + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); + } + this->actionFunc = EnExItem_TargetPrizeGive; } } void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { this->actionFunc = EnExItem_TargetPrizeFinish; } else { - if (!IS_RANDO) { - s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; - Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); - } - + s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } } void EnExItem_TargetPrizeFinish(EnExItem* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor) || (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); Flags_SetItemGetInf(ITEMGETINF_1D); From 2339a729eea09c71d066070e01f6de77a496d510 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:10:18 -0400 Subject: [PATCH 127/300] vb deku theater (#96) --- .../Enhancements/randomizer/location_list.cpp | 4 +- .../Enhancements/timesaver_hook_handlers.cpp | 52 ++++++++++++++++++- .../actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c | 23 -------- .../actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h | 2 + 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index c58674bae..0ff2837db 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -618,8 +618,8 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1E), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); // Sacred Forest Meadow locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 8e733b427..18249e0bf 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -22,6 +22,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" +#include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -87,6 +88,36 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { } } +void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { + // todo: figure out a better way to handle toggling so we don't + // need to double check cvars like this + if(!(IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnDntDemo_Judge(enDntDemo, play); + return; + } + + if (enDntDemo->actor.xzDistToPlayer > 30.0f) { + EnDntDemo_Judge(enDntDemo, play); + return; + } + + Player* player = GET_PLAYER(play); + switch (Player_GetMask(play)) { + case PLAYER_MASK_SKULL: { + Flags_SetItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE); + return; + } + case PLAYER_MASK_TRUTH: { + Flags_SetItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE); + return; + } + default: { + EnDntDemo_Judge(enDntDemo, play); + return; + } + } +} + static int successChimeCooldown = 0; void RateLimitedSuccessChime() { if (successChimeCooldown == 0) { @@ -304,6 +335,10 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = false; break; } + case ACTOR_EN_DNT_DEMO: { + *should = false; + break; + } case ACTOR_EN_TA: case ACTOR_DOOR_SHUTTER: case ACTOR_BG_ICE_SHUTTER: @@ -769,6 +804,11 @@ void TimeSaverOnActorInitHandler(void* actorRef) { enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; } + + if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnDntDemo* enDntDemo = static_cast(actorRef); + enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; + } } void TimeSaverOnSceneInitHandler(int16_t sceneNum) { @@ -949,6 +989,16 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { break; } break; + case FLAG_ITEM_GET_INF: + switch (flag) { + case ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_STICK_CAPACITY_30).GetGIEntry_Copy(); + break; + case ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_NUT_CAPACITY_40).GetGIEntry_Copy(); + break; + } + break; } } @@ -1016,4 +1066,4 @@ void TimeSaverRegisterHooks() { onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnPlayerUpdateHandler); onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnItemReceiveHandler); }); -} \ No newline at end of file +} diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c index eb9942fba..d63cb14c8 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c @@ -135,29 +135,6 @@ void EnDntDemo_Judge(EnDntDemo* this, PlayState* play) { this->judgeTimer = 0; } } else { - if (IS_RANDO) { - Player* player = GET_PLAYER(play); - switch (Player_GetMask(play)) { - case PLAYER_MASK_SKULL: - if (!Flags_GetTreasure(play, 0x1F) && !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - break; - case PLAYER_MASK_TRUTH: - if (!Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1E; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - break; - } - return; - } - if ((Player_GetMask(play) != 0) && (this->subCamera == SUBCAM_FREE)) { this->subCamera = OnePointCutscene_Init(play, 2220, -99, &this->scrubs[3]->actor, MAIN_CAM); } diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h index 9093d451c..c6b9a7efb 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h +++ b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h @@ -64,4 +64,6 @@ typedef enum { /* 5 */ DNT_ACTION_PRIZE } EnDntAction; +void EnDntDemo_Judge(EnDntDemo* enDntDemo, PlayState* play); + #endif From 0f43d5de2d5535d941f2239e71470826360d9479 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:16:17 -0400 Subject: [PATCH 128/300] bump lus (gfx refactor) (#4031) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libultraship b/libultraship index f79b19a73..c3a699403 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit f79b19a73293c572867eb816377d14c3dbded6e8 +Subproject commit c3a699403793c9ac97733179fe078d2e2f271ee1 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6d025ab6f..c9cb36130 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -306,6 +306,7 @@ OTRGlobals::OTRGlobals() { context = LUS::Context::CreateUninitializedInstance("Ship of Harkinian", appShortName, "shipofharkinian.json"); context->InitLogging(); + context->InitGfxDebugger(); context->InitConfiguration(); context->InitConsoleVariables(); From fb29c827adf965016186e1919e62882624ac50bd Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:17:32 -0400 Subject: [PATCH 129/300] Update BUILDING.md (#4029) --- docs/BUILDING.md | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/BUILDING.md b/docs/BUILDING.md index d4ba07f3c..6c9222242 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -123,34 +123,27 @@ zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip _Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._ ```bash -# Clone the repo +# Clone the repo and enter the directory git clone https://github.com/HarbourMasters/Shipwright.git cd Shipwright + # Clone the submodules git submodule update --init -# Copy the baserom to the OTRExporter folder -cp OTRExporter + # Generate Ninja project cmake -H. -Bbuild-cmake -GNinja # -DCMAKE_BUILD_TYPE:STRING=Release (if you're packaging) -DPython3_EXECUTABLE=$(which python3) (if you are using non-standard Python installations such as PyEnv) -# Extract assets & generate OTR (run this anytime you need to regenerate OTR) -cmake --build build-cmake --target ExtractAssets + +# Generate soh.otr +cmake --build build-cmake --target GenerateSohOtr + # Compile the project cmake --build build-cmake # --config Release (if you're packaging) # Now you can run the executable in ./build-cmake/soh/soh.elf # To develop the project open the repository in VSCode (or your preferred editor) - -# If you need to clean the project you can run -cmake --build build-cmake --target clean - -# If you need to regenerate the asset headers to check them into source -cmake --build build-cmake --target ExtractAssetHeaders - -# If you need a newer soh.otr only -cmake --build build-cmake --target GenerateSohOtr ``` -### Generating a distributable +### Generate a distributable After compiling the project you can generate a distributable by running of the following: ```bash # Go to build folder @@ -161,6 +154,20 @@ cpack -G ZIP cpack -G External (creates appimage) ``` +### Additional CMake Targets +#### Clean +```bash +# If you need to clean the project you can run +cmake --build build-cmake --target clean +``` + +#### Regenerate Asset Headers +```bash +# If you need to regenerate the asset headers to check them into source +cp OTRExporter +cmake --build build-cmake --target ExtractAssetHeaders +``` + ## macOS Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake` (can be installed via homebrew, macports, etc) From 86c6013888459b381d86aef9472215fe2efa4c58 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 4 Apr 2024 11:23:18 -0400 Subject: [PATCH 130/300] Remove macports upgrading (#4035) --- .github/workflows/generate-builds.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index c449585bf..34f5c21c0 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -96,11 +96,6 @@ jobs: sudo installer -pkg ./MacPorts-2.9.1-12-Monterey.pkg -target / fi echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH - - name: Update MacPorts - if: ${{ !vars.MAC_RUNNER }} - run: | - sudo port selfupdate - sudo port upgrade outdated - name: Install dependencies if: ${{ !vars.MAC_RUNNER }} run: | From 249490909f8e8f2a675cd43464f3628bdf3966d7 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:26:48 -0400 Subject: [PATCH 131/300] pull docs: talon function names (#98) --- soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 192 ++++++++++---------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 85f5053d1..d8a0ff554 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -16,21 +16,21 @@ void EnTa_Destroy(Actor* thisx, PlayState* play); void EnTa_Update(Actor* thisx, PlayState* play); void EnTa_Draw(Actor* thisx, PlayState* play); -void func_80B14634(EnTa* this, PlayState* play); -void func_80B146F8(EnTa* this, PlayState* play); -void func_80B14754(EnTa* this, PlayState* play); -void func_80B14C18(EnTa* this, PlayState* play); -void func_80B14CAC(EnTa* this, PlayState* play); -void func_80B14D98(EnTa* this, PlayState* play); -void func_80B154FC(EnTa* this, PlayState* play); -void func_80B16504(EnTa* this, PlayState* play); -void func_80B16608(EnTa* this, PlayState* play); -void func_80B166CC(EnTa* this); -void func_80B16700(EnTa* this); -void func_80B167C0(EnTa* this); -void func_80B167FC(EnTa* this); -void func_80B16854(EnTa* this); -void func_80B16938(EnTa* this); +void EnTa_IdleAsleepInCastle(EnTa* this, PlayState* play); +void EnTa_IdleAsleepInLonLonHouse(EnTa* this, PlayState* play); +void EnTa_IdleAsleepInKakariko(EnTa* this, PlayState* play); +void EnTa_IdleAwakeInCastle(EnTa* this, PlayState* play); +void EnTa_IdleAwakeInKakariko(EnTa* this, PlayState* play); +void EnTa_IdleAtRanch(EnTa* this, PlayState* play); +void EnTa_RunCuccoGame(EnTa* this, PlayState* play); +void EnTa_IdleSittingInLonLonHouse(EnTa* this, PlayState* play); +void EnTa_IdleAfterCuccoGameFinished(EnTa* this, PlayState* play); +void EnTa_BlinkWaitUntilNext(EnTa* this); +void EnTa_BlinkAdvanceState(EnTa* this); +void EnTa_AnimRepeatCurrent(EnTa* this); +void EnTa_AnimSleeping(EnTa* this); +void EnTa_AnimSitSleeping(EnTa* this); +void EnTa_AnimRunToEnd(EnTa* this); const ActorInit En_Ta_InitVars = { ACTOR_EN_TA, @@ -65,7 +65,7 @@ static ColliderCylinderInit sCylinderInit = { { 30, 40, 0, { 0, 0, 0 } }, }; -void func_80B13AA0(EnTa* this, EnTaActionFunc arg1, EnTaUnkFunc arg2) { +void EnTa_SetupAction(EnTa* this, EnTaActionFunc arg1, EnTaUnkFunc arg2) { this->actionFunc = arg1; this->unk_260 = arg2; } @@ -114,7 +114,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { this->unk_2CE = 0; this->unk_2E2 = 0; this->blinkTimer = 20; - this->unk_2B0 = func_80B166CC; + this->unk_2B0 = EnTa_BlinkWaitUntilNext; Actor_SetScale(&this->actor, 0.01f); this->actor.targetMode = 6; this->actor.velocity.y = -4.0f; @@ -129,12 +129,12 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { } else if (!LINK_IS_ADULT) { Actor_Kill(&this->actor); } else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_KAKARIKO)) { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; } else { - func_80B13AA0(this, func_80B14754, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInKakariko, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -151,7 +151,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { Actor_Kill(&this->actor); osSyncPrintf(VT_FGCOL(CYAN) " 夜はいない \n" VT_RST); } else { - func_80B13AA0(this, func_80B14D98, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAtRanch, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; @@ -163,12 +163,12 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { Actor_Kill(&this->actor); } else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE)) { - func_80B13AA0(this, func_80B14C18, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInCastle, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; } else { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -196,19 +196,19 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { func_80B13AAC(this, play); if (gSaveContext.eventInf[0] & 0x400) { - func_80B13AA0(this, func_80B16608, func_80B16938); + EnTa_SetupAction(this, EnTa_IdleAfterCuccoGameFinished, EnTa_AnimRunToEnd); Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim) - 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, 0.0f); gSaveContext.eventInf[0] &= ~0x400; } else { - func_80B13AA0(this, func_80B16504, func_80B16854); + EnTa_SetupAction(this, EnTa_IdleSittingInLonLonHouse, EnTa_AnimSitSleeping); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonSitSleepingAnim); this->currentAnimation = &gTalonSitSleepingAnim; } } else { - func_80B13AA0(this, func_80B146F8, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInLonLonHouse, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -216,7 +216,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { } } } else { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -265,22 +265,22 @@ s32 func_80B142F4(EnTa* this, PlayState* play, u16 textId) { void func_80B14398(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14754, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInKakariko, EnTa_AnimSleeping); } } void func_80B143D4(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B146F8, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInLonLonHouse, EnTa_AnimSleeping); } } void func_80B14410(EnTa* this) { if (!LINK_IS_ADULT) { - func_80B13AA0(this, func_80B14C18, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInCastle, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE); } else { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_KAKARIKO); } } @@ -297,12 +297,12 @@ void func_80B144D8(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { func_80B14410(this); this->blinkTimer = 1; - this->unk_2B0 = func_80B16700; + this->unk_2B0 = EnTa_BlinkAdvanceState; } if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) { this->eyeIndex = 1; - func_80B13AA0(this, func_80B1448C, func_80B167C0); + EnTa_SetupAction(this, func_80B1448C, EnTa_AnimRepeatCurrent); } func_80B14248(this); this->unk_2E0 |= 4; @@ -312,7 +312,7 @@ void func_80B14570(EnTa* this, PlayState* play) { this->unk_2E0 |= 4; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B144D8, func_80B167C0); + EnTa_SetupAction(this, func_80B144D8, EnTa_AnimRepeatCurrent); this->unk_2CE = 3; this->unk_2CC = 60; Animation_PlayOnce(&this->skelAnime, &gTalonWakeUpAnim); @@ -323,11 +323,11 @@ void func_80B14570(EnTa* this, PlayState* play) { void func_80B145F8(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); } } -void func_80B14634(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInCastle(EnTa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Actor_ProcessTalkRequest(&this->actor, play)) { @@ -336,14 +336,14 @@ void func_80B14634(EnTa* this, PlayState* play) { switch (exchangeItemId) { case EXCH_ITEM_CHICKEN: player->actor.textId = 0x702B; - func_80B13AA0(this, func_80B14570, func_80B167C0); + EnTa_SetupAction(this, func_80B14570, EnTa_AnimRepeatCurrent); this->unk_2CC = 40; break; default: if (exchangeItemId != EXCH_ITEM_NONE) { player->actor.textId = 0x702A; } - func_80B13AA0(this, func_80B145F8, func_80B167FC); + EnTa_SetupAction(this, func_80B145F8, EnTa_AnimSleeping); break; } } else { @@ -352,15 +352,15 @@ void func_80B14634(EnTa* this, PlayState* play) { } } -void func_80B146F8(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInLonLonHouse(EnTa* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, play)) { - func_80B13AA0(this, func_80B143D4, func_80B167FC); + EnTa_SetupAction(this, func_80B143D4, EnTa_AnimSleeping); } this->actor.textId = 0x204B; func_8002F2CC(&this->actor, play, 100.0f); } -void func_80B14754(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInKakariko(EnTa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Actor_ProcessTalkRequest(&this->actor, play)) { @@ -369,14 +369,14 @@ void func_80B14754(EnTa* this, PlayState* play) { switch (exchangeItemId) { case EXCH_ITEM_POCKET_CUCCO: player->actor.textId = 0x702B; - func_80B13AA0(this, func_80B14570, func_80B167C0); + EnTa_SetupAction(this, func_80B14570, EnTa_AnimRepeatCurrent); this->unk_2CC = 40; break; default: if (exchangeItemId != EXCH_ITEM_NONE) { player->actor.textId = 0x5015; } - func_80B13AA0(this, func_80B14398, func_80B167FC); + EnTa_SetupAction(this, func_80B14398, EnTa_AnimSleeping); break; } } else { @@ -411,7 +411,7 @@ void func_80B1490C(EnTa* this, PlayState* play) { this->actor.shape.rot.y += 0xC00; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B14898, func_80B167C0); + EnTa_SetupAction(this, func_80B14898, EnTa_AnimRepeatCurrent); this->unk_2CC = 60; } } @@ -421,7 +421,7 @@ void func_80B1496C(EnTa* this, PlayState* play) { func_80B14818(this, play); if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B1490C, func_80B167C0); + EnTa_SetupAction(this, func_80B1490C, EnTa_AnimRepeatCurrent); this->unk_2CC = 5; } } @@ -431,7 +431,7 @@ void func_80B149F4(EnTa* this, PlayState* play) { this->actor.shape.rot.y -= 0xD00; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B1496C, func_80B167C0); + EnTa_SetupAction(this, func_80B1496C, EnTa_AnimRepeatCurrent); this->unk_2CC = 65; } } @@ -445,7 +445,7 @@ void func_80B14A54(EnTa* this, PlayState* play) { } if (this->unk_2CC == 0) { this->unk_2CC = 5; - func_80B13AA0(this, func_80B149F4, func_80B167C0); + EnTa_SetupAction(this, func_80B149F4, EnTa_AnimRepeatCurrent); } } @@ -455,7 +455,7 @@ void func_80B14AF4(EnTa* this, PlayState* play) { if (this->unk_2CC == 0) { Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_CRY_1); - func_80B13AA0(this, func_80B14A54, func_80B167C0); + EnTa_SetupAction(this, func_80B14A54, EnTa_AnimRepeatCurrent); this->unk_2CC = 65; this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; } @@ -464,7 +464,7 @@ void func_80B14AF4(EnTa* this, PlayState* play) { void func_80B14B6C(EnTa* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) { s16 csCamIdx = OnePointCutscene_Init(play, 4175, -99, &this->actor, MAIN_CAM); - func_80B13AA0(this, func_80B14AF4, func_80B167C0); + EnTa_SetupAction(this, func_80B14AF4, EnTa_AnimRepeatCurrent); this->unk_2CC = 5; Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { @@ -476,42 +476,42 @@ void func_80B14B6C(EnTa* this, PlayState* play) { this->unk_2E0 |= 1; } -void func_80B14C18(EnTa* this, PlayState* play) { +void EnTa_IdleAwakeInCastle(EnTa* this, PlayState* play) { if (func_80B142F4(this, play, 0x702C)) { - func_80B13AA0(this, func_80B14B6C, func_80B167C0); + EnTa_SetupAction(this, func_80B14B6C, EnTa_AnimRepeatCurrent); } func_80B14248(this); } void func_80B14C60(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); } this->unk_2E0 |= 1; } -void func_80B14CAC(EnTa* this, PlayState* play) { +void EnTa_IdleAwakeInKakariko(EnTa* this, PlayState* play) { if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) { if (func_80B142F4(this, play, 0x5017)) { - func_80B13AA0(this, func_80B14C60, func_80B167C0); + EnTa_SetupAction(this, func_80B14C60, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO); } } else if (func_80B142F4(this, play, 0x5016)) { - func_80B13AA0(this, func_80B14C60, func_80B167C0); + EnTa_SetupAction(this, func_80B14C60, EnTa_AnimRepeatCurrent); } func_80B14248(this); } void func_80B14D4C(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14D98, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAtRanch, EnTa_AnimRepeatCurrent); } this->unk_2E0 |= 1; } -void func_80B14D98(EnTa* this, PlayState* play) { +void EnTa_IdleAtRanch(EnTa* this, PlayState* play) { if (func_80B142F4(this, play, 0x2055)) { - func_80B13AA0(this, func_80B14D4C, func_80B167C0); + EnTa_SetupAction(this, func_80B14D4C, EnTa_AnimRepeatCurrent); } } @@ -551,7 +551,7 @@ void func_80B14EDC(EnTa* this, PlayState* play) { } void func_80B14F20(EnTa* this, EnTaActionFunc arg1) { - func_80B13AA0(this, arg1, func_80B16854); + EnTa_SetupAction(this, arg1, EnTa_AnimSitSleeping); this->eyeIndex = 2; Animation_Change(&this->skelAnime, &gTalonSitSleepingAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gTalonSitSleepingAnim), ANIMMODE_ONCE, -5.0f); @@ -561,7 +561,7 @@ void func_80B14F20(EnTa* this, EnTaActionFunc arg1) { void func_80B14FAC(EnTa* this, EnTaActionFunc arg1) { this->eyeIndex = 1; - func_80B13AA0(this, arg1, func_80B16938); + EnTa_SetupAction(this, arg1, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, -5.0f); @@ -570,7 +570,7 @@ void func_80B14FAC(EnTa* this, EnTaActionFunc arg1) { void func_80B15034(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); } this->unk_2E0 |= 1; @@ -602,7 +602,7 @@ void func_80B15100(EnTa* this, PlayState* play) { this->unk_2E0 &= ~0x10; Message_CloseTextbox(play); unk_2CA = this->unk_2CA; - this->actionFunc = func_80B154FC; + this->actionFunc = EnTa_RunCuccoGame; this->superCuccos[unk_2CA]->actor.gravity = 0.1f; this->superCuccos[unk_2CA]->actor.velocity.y = 0.0f; this->superCuccos[unk_2CA]->actor.speedXZ = 0.0f; @@ -687,7 +687,7 @@ void func_80B15424(EnTa* this, PlayState* play) { } } -void func_80B154FC(EnTa* this, PlayState* play) { +void EnTa_RunCuccoGame(EnTa* this, PlayState* play) { s32 i; for (i = 0; i < ARRAY_COUNT(this->superCuccos); i++) { @@ -797,7 +797,7 @@ void func_80B1585C(EnTa* this, PlayState* play) { } if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B154FC, func_80B16938); + EnTa_SetupAction(this, EnTa_RunCuccoGame, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim) - 1.0f, @@ -808,7 +808,7 @@ void func_80B1585C(EnTa* this, PlayState* play) { void func_80B15AD4(EnTa* this, PlayState* play) { if (this->unk_2CC == 0 && this->unk_2E0 & 0x20) { - func_80B13AA0(this, func_80B1585C, func_80B16938); + EnTa_SetupAction(this, func_80B1585C, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 1.0f, Animation_GetLastFrame(&gTalonSitHandsUpAnim), ANIMMODE_ONCE, 0.0f); @@ -829,7 +829,7 @@ void func_80B15AD4(EnTa* this, PlayState* play) { void func_80B15BF8(EnTa* this, PlayState* play) { if (this->unk_2E0 & 0x10) { - func_80B13AA0(this, func_80B15AD4, func_80B16938); + EnTa_SetupAction(this, func_80B15AD4, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 0.0f, 1.0f, ANIMMODE_ONCE, 0.0f); this->unk_2CC = 5; @@ -842,7 +842,7 @@ void func_80B15BF8(EnTa* this, PlayState* play) { void func_80B15CC8(EnTa* this, PlayState* play) { if (this->unk_2E0 & 0x10) { - func_80B13AA0(this, func_80B15BF8, func_80B16938); + EnTa_SetupAction(this, func_80B15BF8, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, -1.0f, 29.0f, 0.0f, ANIMMODE_ONCE, 10.0f); } @@ -853,25 +853,25 @@ void func_80B15CC8(EnTa* this, PlayState* play) { } void func_80B15D90(EnTa* this, PlayState* play) { - func_80B13AA0(this, func_80B15CC8, func_80B16938); + EnTa_SetupAction(this, func_80B15CC8, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 8.0f, 29.0f, ANIMMODE_ONCE, -10.0f); Message_ContinueTextbox(play, 0x2080); this->unk_2E0 &= ~0x20; } -void func_80B15E28(EnTa* this, PlayState* play) { +void EnTa_TalkGeneralInLonLonHouse(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); } this->unk_2E0 |= 1; } -void func_80B15E80(EnTa* this, PlayState* play) { +void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; - this->actionFunc = func_80B15E28; + this->actionFunc = EnTa_TalkGeneralInLonLonHouse; if (!(this->unk_2E0 & 0x2)) { Flags_SetItemGetInf(ITEMGETINF_TALON_BOTTLE); } @@ -889,11 +889,11 @@ void func_80B15E80(EnTa* this, PlayState* play) { this->unk_2E0 |= 1; } -void func_80B15F54(EnTa* this, PlayState* play) { +void EnTa_TalkAfterCuccoGameFirstWon(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); this->unk_2E0 &= ~0x2; - func_80B13AA0(this, func_80B15E80, func_80B16938); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); if (!IS_RANDO) { Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } else { @@ -910,15 +910,15 @@ void func_80B15FE8(EnTa* this, PlayState* play) { switch (func_80B14DD8()) { case 0: Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); break; case 1: Message_ContinueTextbox(play, 0x208A); - func_80B13AA0(this, func_80B15E28, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkGeneralInLonLonHouse, EnTa_AnimRunToEnd); break; case 2: this->unk_2E0 |= 2; - func_80B13AA0(this, func_80B15E80, func_80B16938); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); Rupees_ChangeBy(-30); GetItemEntry itemEntry = ItemTable_Retrieve(GI_MILK); gSaveContext.pendingSale = itemEntry.itemId; @@ -930,14 +930,14 @@ void func_80B15FE8(EnTa* this, PlayState* play) { case 1: if (gSaveContext.rupees < 10) { Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); } else { Rupees_ChangeBy(-10); func_80B15D90(this, play); } break; case 2: - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); break; } @@ -962,14 +962,14 @@ void func_80B161C0(EnTa* this, PlayState* play) { case 0: if (gSaveContext.rupees < price) { Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); } else { Rupees_ChangeBy(-price); func_80B15D90(this, play); } break; case 1: - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); break; } @@ -983,7 +983,7 @@ void func_80B161C0(EnTa* this, PlayState* play) { void func_80B162E8(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { Message_ContinueTextbox(play, 0x2087); - func_80B13AA0(this, func_80B15F54, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkAfterCuccoGameFirstWon, EnTa_AnimRunToEnd); } if (this->unk_2E0 & 0x10) { @@ -996,10 +996,10 @@ void func_80B16364(EnTa* this, PlayState* play) { Flags_SetInfTable(INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE); if (Flags_GetItemGetInf(ITEMGETINF_TALON_BOTTLE)) { Message_ContinueTextbox(play, 0x208B); - func_80B13AA0(this, func_80B15FE8, func_80B16938); + EnTa_SetupAction(this, func_80B15FE8, EnTa_AnimRunToEnd); } else { Message_ContinueTextbox(play, 0x207F); - func_80B13AA0(this, func_80B161C0, func_80B16938); + EnTa_SetupAction(this, func_80B161C0, EnTa_AnimRunToEnd); } } @@ -1013,16 +1013,16 @@ void func_80B1642C(EnTa* this, PlayState* play) { if (Inventory_HasEmptyBottle()) { Message_CloseTextbox(play); this->unk_2E0 |= 2; - func_80B13AA0(this, func_80B15E80, func_80B16938); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { Message_ContinueTextbox(play, 0x208A); - func_80B13AA0(this, func_80B15E28, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkGeneralInLonLonHouse, EnTa_AnimRunToEnd); } } } -void func_80B16504(EnTa* this, PlayState* play) { +void EnTa_IdleSittingInLonLonHouse(EnTa* this, PlayState* play) { u16 faceReaction = Text_GetFaceReaction(play, 0x18); func_80B13AAC(this, play); @@ -1031,7 +1031,7 @@ void func_80B16504(EnTa* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_SURPRISE); if (faceReaction != 0) { - func_80B14FAC(this, func_80B15E28); + func_80B14FAC(this, EnTa_TalkGeneralInLonLonHouse); } else { Flags_SetInfTable(INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE); @@ -1052,7 +1052,7 @@ void func_80B16504(EnTa* this, PlayState* play) { this->unk_2E0 &= ~1; } -void func_80B16608(EnTa* this, PlayState* play) { +void EnTa_IdleAfterCuccoGameFinished(EnTa* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, play)) { switch (this->actor.textId) { case 0x2085: @@ -1073,17 +1073,17 @@ void func_80B16608(EnTa* this, PlayState* play) { this->unk_2E0 |= 1; } -void func_80B166CC(EnTa* this) { +void EnTa_BlinkWaitUntilNext(EnTa* this) { s16 temp_v0 = this->blinkTimer - 1; if (temp_v0 != 0) { this->blinkTimer = temp_v0; } else { - this->unk_2B0 = func_80B16700; + this->unk_2B0 = EnTa_BlinkAdvanceState; } } -void func_80B16700(EnTa* this) { +void EnTa_BlinkAdvanceState(EnTa* this) { s16 blinkTimer = this->blinkTimer - 1; if (blinkTimer != 0) { @@ -1101,7 +1101,7 @@ void func_80B16700(EnTa* this) { blinkTimer = (s32)(Rand_ZeroOne() * 60.0f) + 20; } this->blinkTimer = blinkTimer; - this->unk_2B0 = func_80B166CC; + this->unk_2B0 = EnTa_BlinkWaitUntilNext; } else { this->eyeIndex = nextEyeIndex; this->blinkTimer = 1; @@ -1109,13 +1109,13 @@ void func_80B16700(EnTa* this) { } } -void func_80B167C0(EnTa* this) { +void EnTa_AnimRepeatCurrent(EnTa* this) { if (SkelAnime_Update(&this->skelAnime)) { Animation_PlayOnce(&this->skelAnime, this->currentAnimation); } } -void func_80B167FC(EnTa* this) { +void EnTa_AnimSleeping(EnTa* this) { if (SkelAnime_Update(&this->skelAnime)) { Animation_PlayOnce(&this->skelAnime, this->currentAnimation); Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_SLEEP); @@ -1123,7 +1123,7 @@ void func_80B167FC(EnTa* this) { this->unk_2E0 |= 0xC; } -void func_80B16854(EnTa* this) { +void EnTa_AnimSitSleeping(EnTa* this) { if (this->unk_2E2 > 0) { this->unk_2E2--; } else { @@ -1142,7 +1142,7 @@ void func_80B16854(EnTa* this) { this->unk_2E0 |= 4; } -void func_80B16938(EnTa* this) { +void EnTa_AnimRunToEnd(EnTa* this) { if (!(this->unk_2E0 & 0x10)) { if (SkelAnime_Update(&this->skelAnime)) { this->unk_2E0 |= 0x10; From 1e9cba1d616615234079e414f6d8b354be2c9efb Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:30:45 -0400 Subject: [PATCH 132/300] vb diving game (#100) --- .../game-interactor/GameInteractor.h | 2 ++ .../Enhancements/randomizer/hook_handlers.cpp | 1 + .../actors/ovl_En_Diving_Game/z_en_diving_game.c | 16 ++++++---------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index c61a82760..08f1fe0be 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -292,6 +292,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, // Opt: *EnExItem GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, + // Opt: *EnDivingGame + GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index ea3755a69..f1cc89102 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -768,6 +768,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_TRADE_TIMER_FROG: case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: case GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: + case GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME: case GI_VB_GIVE_ITEM_FROM_GORON: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: diff --git a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c index 84ac2749d..b411c1427 100644 --- a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c +++ b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c @@ -8,6 +8,7 @@ #include "overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.h" #include "objects/object_zo/object_zo.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -455,11 +456,8 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { if ((this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play))) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); } this->actionFunc = func_809EEA90; } @@ -467,14 +465,11 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { void func_809EEA90(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { this->actionFunc = func_809EEAF8; } else { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); } } } @@ -482,7 +477,8 @@ void func_809EEA90(EnDivingGame* this, PlayState* play) { // Award the scale? void func_809EEAF8(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) || + !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); this->allRupeesThrown = this->state = this->phase = this->unk_2A2 = this->grabbedRupeesCounter = 0; From 307e1060381bebd338b4769af3e606eecb898c00 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:55:07 -0400 Subject: [PATCH 133/300] vb talon's chickens (#99) --- .../Enhancements/game-interactor/GameInteractor.h | 2 ++ soh/soh/Enhancements/randomizer/hook_handlers.cpp | 1 + soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 12 +++--------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 08f1fe0be..f5e70da16 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -292,6 +292,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, // Opt: *EnExItem GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, + // Opt: *EnTa + GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, // Opt: *EnDivingGame GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f1cc89102..772ce16aa 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -768,6 +768,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_TRADE_TIMER_FROG: case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: case GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: + case GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS: case GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME: case GI_VB_GIVE_ITEM_FROM_GORON: case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index d8a0ff554..cdec042bc 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -869,7 +869,7 @@ void EnTa_TalkGeneralInLonLonHouse(EnTa* this, PlayState* play) { } void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { this->actor.parent = NULL; this->actionFunc = EnTa_TalkGeneralInLonLonHouse; if (!(this->unk_2E0 & 0x2)) { @@ -879,11 +879,8 @@ void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { } else if (this->unk_2E0 & 2) { Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } this->unk_2E0 |= 1; @@ -894,11 +891,8 @@ void EnTa_TalkAfterCuccoGameFirstWon(EnTa* this, PlayState* play) { Message_CloseTextbox(play); this->unk_2E0 &= ~0x2; EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } } From fd7dfd8b6f557909c84b88e35df37bc27673fa1e Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 4 Apr 2024 12:26:14 -0400 Subject: [PATCH 134/300] Support for new ucode loading patterns (#4038) --- soh/include/functions.h | 8 +- soh/src/code/sys_ucode.c | 21 ++-- soh/src/code/z_room.c | 108 +++++++++--------- .../ovl_kaleido_scope/z_kaleido_map_PAL.c | 17 ++- 4 files changed, 80 insertions(+), 74 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 2c4fe9b15..08179b341 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1230,8 +1230,8 @@ Gfx* Gfx_EnvColor(GraphicsContext* gfxCtx, s32 r, s32 g, s32 b, s32 a); void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b); void func_80095974(GraphicsContext* gfxCtx); void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3); -void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0, - u16 tlutCount, f32 frameX, f32 frameY); +void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode, + u16 tlutCount, f32 offsetX, f32 offsetY); void func_80096FD4(PlayState* play, Room* room); u32 func_80096FE8(PlayState* play, RoomContext* roomCtx); s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum); @@ -1828,8 +1828,8 @@ MtxF* Matrix_CheckFloats(MtxF* mf, char* file, s32 line); void Matrix_SetTranslateScaleMtx2(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY, f32 translateZ); uintptr_t SysUcode_GetUCodeBoot(void); -uintptr_t SysUcode_GetUCodeBootSize(void); -uintptr_t SysUcode_GetUCode(void); +size_t SysUcode_GetUCodeBootSize(void); +uint32_t SysUcode_GetUCode(void); uintptr_t SysUcode_GetUCodeData(void); void func_800D2E30(UnkRumbleStruct* arg0); void func_800D3140(UnkRumbleStruct* arg0); diff --git a/soh/src/code/sys_ucode.c b/soh/src/code/sys_ucode.c index b2a5ef108..39bbe3531 100644 --- a/soh/src/code/sys_ucode.c +++ b/soh/src/code/sys_ucode.c @@ -1,20 +1,25 @@ #include "global.h" -//uintptr_t D_8012DBA0 = (uintptr_t)&D_80155F50; -//uintptr_t D_8012DBA4 = (uintptr_t)&D_80157580; +#include "public/bridge/gfxbridge.h" + +UcodeHandlers sDefaultGSPUCodeText = ucode_f3dex2; +// u64* sDefaultGSPUCodeData = gspF3DZEX2_NoN_PosLight_fifoDataStart; uintptr_t SysUcode_GetUCodeBoot(void) { - //return &D_80009320; + // return rspbootTextStart; + return (uintptr_t)NULL; } -uintptr_t SysUcode_GetUCodeBootSize(void) { - //return (uintptr_t)&D_800093F0 - (uintptr_t)&D_80009320; +size_t SysUcode_GetUCodeBootSize(void) { + // return (ptrdiff_t)((uintptr_t)rspbootTextEnd - (uintptr_t)rspbootTextStart); + return 0; } -uintptr_t SysUcode_GetUCode(void) { - //return D_8012DBA0; +uint32_t SysUcode_GetUCode(void) { + return sDefaultGSPUCodeText; } uintptr_t SysUcode_GetUCodeData(void) { - //return D_8012DBA4; + // return sDefaultGSPUCodeData; + return (uintptr_t)NULL; } diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index e92925c6a..de068ae6c 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -8,6 +8,8 @@ #include #include +#include "public/bridge/gfxbridge.h" + void func_80095AB4(PlayState* play, Room* room, u32 flags); void func_80095D04(PlayState* play, Room* room, u32 flags); void func_80096F6C(PlayState* play, Room* room, u32 flags); @@ -254,23 +256,21 @@ s32 swapAndConvertJPEG(void* data) { } -void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0, - u16 tlutCount, f32 frameX, f32 frameY) { - Gfx* displayListHead; +void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode, + u16 tlutCount, f32 offsetX, f32 offsetY) { + Gfx* gfx = *gfxP; uObjBg* bg; - s32 temp; - displayListHead = *displayList; + bg = (uObjBg*)(gfx + 1); + gSPBranchList(gfx, (Gfx*)(bg + 1)); - bg = (uObjBg*)(displayListHead + 1); - gSPBranchList(displayListHead, (u8*)bg + sizeof(uObjBg)); bg->b.imageX = 0; - bg->b.imageW = width * 4; - bg->b.frameX = frameX * 4; + bg->b.imageW = width * (1 << 2); + bg->b.frameX = offsetX * (1 << 2); bg->b.imageY = 0; - bg->b.imageH = height * 4; - bg->b.frameY = frameY * 4; - bg->b.imagePtr = source; + bg->b.imageH = height * (1 << 2); + bg->b.frameY = offsetY * (1 << 2); + bg->b.imagePtr = tex; bg->b.imageLoad = G_BGLT_LOADTILE; bg->b.imageFmt = fmt; bg->b.imageSiz = siz; @@ -280,62 +280,68 @@ void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 h // When an alt resource exists for the background, we need to unload the original asset // to clear the cache so the alt asset will be loaded instead // OTRTODO: If Alt loading over original cache is fixed, this line can most likely be removed - ResourceMgr_UnloadOriginalWhenAltExists((char*) source); + ResourceMgr_UnloadOriginalWhenAltExists((char*)tex); - if (ResourceMgr_ResourceIsBackground((char*) source)) { - char* blob = (char*) ResourceGetDataByName((char *) source); + if (ResourceMgr_ResourceIsBackground((char*)tex)) { + char* blob = (char*)ResourceGetDataByName((char *)tex); swapAndConvertJPEG(blob); - bg->b.imagePtr = (uintptr_t) blob; + bg->b.imagePtr = (uintptr_t)blob; } - displayListHead = (void*)(bg + 1); + gfx = (Gfx*)(bg + 1); + if (fmt == G_IM_FMT_CI) { - gDPLoadTLUT(displayListHead++, tlutCount, 256, tlut); + gDPLoadTLUT(gfx++, tlutCount, 256, tlut); } else { - gDPPipeSync(displayListHead++); + gDPPipeSync(gfx++); } if ((fmt == G_IM_FMT_RGBA) && (SREG(26) == 0)) { - bg->b.frameW = width * 4; - bg->b.frameH = height * 4; + bg->b.frameW = width * (1 << 2); + bg->b.frameH = height * (1 << 2); guS2DInitBg(bg); - gDPSetOtherMode(displayListHead++, mode0 | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, + // #region SOH [Port][Widescreen] + // When larger than 4:3 we want to render an additional black rectangle behind the 2d image + // to simulate black bars on the side that cover up the world + s16 newX = OTRGetRectDimensionFromLeftEdge(0); + if (newX < 0) { + gDPSetOtherMode(gfx++, tlutMode | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, + G_AC_THRESHOLD | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); + gDPSetFillColor(gfx++, GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)); + gDPFillWideRectangle(gfx++, newX, 0, OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH), SCREEN_HEIGHT); + } + // #endregion + + gDPSetOtherMode(gfx++, tlutMode | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_COPY | G_PM_NPRIMITIVE, G_AC_THRESHOLD | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); - gDPSetFillColor(displayListHead++, GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)); - gDPFillWideRectangle(displayListHead++, OTRGetRectDimensionFromLeftEdge(0), 0, - OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH), SCREEN_HEIGHT); - - gDPSetOtherMode(displayListHead++, mode0 | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_COPY | G_PM_NPRIMITIVE, - G_AC_THRESHOLD | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); - - gDPLoadMultiTile(displayListHead++, bg->b.imagePtr, 0, + gDPLoadMultiTile(gfx++, bg->b.imagePtr, 0, G_TX_RENDERTILE, G_IM_FMT_RGBA, G_IM_SIZ_16b, 320, 0, 0, 0, 0 + 31, 0 + 31, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD); - gSPBgRectCopy(displayListHead++, bg); - + gSPBgRectCopy(gfx++, bg); } else { - bg->s.frameW = width * 4; - bg->s.frameH = height * 4; - bg->s.scaleW = 1024; - bg->s.scaleH = 1024; + bg->s.frameW = width * (1 << 2); + bg->s.frameH = height * (1 << 2); + bg->s.scaleW = 1 << 10; + bg->s.scaleH = 1 << 10; bg->s.imageYorig = bg->b.imageY; - gDPSetOtherMode(displayListHead++, - mode0 | G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | + gDPSetOtherMode(gfx++, + tlutMode | G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_THRESHOLD | G_ZS_PIXEL | AA_EN | CVG_DST_CLAMP | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA) | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA)); - gDPSetCombineLERP(displayListHead++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); - gSPObjRenderMode(displayListHead++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); - gSPBgRect1Cyc(displayListHead++, bg); + gDPSetCombineLERP(gfx++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); + gSPObjRenderMode(gfx++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); + gSPBgRect1Cyc(gfx++, bg); } - gDPPipeSync(displayListHead++); - *displayList = displayListHead; + gDPPipeSync(gfx++); + + *gfxP = gfx; } // Room Draw Polygon Type 1 - Single Format @@ -369,22 +375,20 @@ void func_80096680(PlayState* play, Room* room, u32 flags) { } if (sp98) { - // gSPLoadUcodeL(POLY_OPA_DISP++, rspS2DEX)? - //gSPLoadUcodeEx(POLY_OPA_DISP++, OS_K0_TO_PHYSICAL(D_80113070), OS_K0_TO_PHYSICAL(D_801579A0), 0x800); + gSPLoadUcodeL(POLY_OPA_DISP++, ucode_s2dex); { Vec3f sp60; spA8 = POLY_OPA_DISP; Camera_GetSkyboxOffset(&sp60, camera); - func_8009638C(&spA8, polygon1->single.source, polygon1->single.tlut, polygon1->single.width, + Room_DrawBackground2D(&spA8, polygon1->single.source, polygon1->single.tlut, polygon1->single.width, polygon1->single.height, polygon1->single.fmt, polygon1->single.siz, polygon1->single.mode0, polygon1->single.tlutCount, (sp60.x + sp60.z) * 1.2f + sp60.y * 0.6f, sp60.y * 2.4f + (sp60.x + sp60.z) * 0.3f); POLY_OPA_DISP = spA8; } - // gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData())? - gSPLoadUcodeEx(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData(), 0x800); + gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode()); } } @@ -472,21 +476,19 @@ void func_80096B6C(PlayState* play, Room* room, u32 flags) { } if (sp94) { - // gSPLoadUcodeL(POLY_OPA_DISP++, rspS2DEX)? - //gSPLoadUcodeEx(POLY_OPA_DISP++, OS_K0_TO_PHYSICAL(D_80113070), OS_K0_TO_PHYSICAL(D_801579A0), 0x800); + gSPLoadUcodeL(POLY_OPA_DISP++, ucode_s2dex); { Vec3f sp5C; spA8 = POLY_OPA_DISP; Camera_GetSkyboxOffset(&sp5C, camera); - func_8009638C(&spA8, bgImage->source, bgImage->tlut, bgImage->width, bgImage->height, bgImage->fmt, + Room_DrawBackground2D(&spA8, bgImage->source, bgImage->tlut, bgImage->width, bgImage->height, bgImage->fmt, bgImage->siz, bgImage->mode0, bgImage->tlutCount, (sp5C.x + sp5C.z) * 1.2f + sp5C.y * 0.6f, sp5C.y * 2.4f + (sp5C.x + sp5C.z) * 0.3f); POLY_OPA_DISP = spA8; } - // gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData())? - gSPLoadUcodeEx(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData(), 0x800); + gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode()); } } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index 34dc47aa9..dc574532c 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -7,6 +7,8 @@ #include "textures/icon_item_dungeon_static/icon_item_dungeon_static.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h" +#include "public/bridge/gfxbridge.h" + void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { static void* dungeonItemTexs[] = { gQuestIconDungeonBossKeyTex, @@ -592,19 +594,16 @@ void KaleidoScope_DrawWorldMap(PlayState* play, GraphicsContext* gfxCtx) { gSP1Quadrangle(POLY_KAL_DISP++, j, j + 2, j + 3, j + 1, 0); } else if (HREG(15) == 1) { - Gfx* sp1CC = POLY_KAL_DISP; - void* mapImage = gWorldMapImageTex; + Gfx* gfx = POLY_KAL_DISP; - // gSPLoadUcodeL(sp1CC++, rspS2DEX)? - //gSPLoadUcodeEx(sp1CC++, OS_K0_TO_PHYSICAL(D_80113070), OS_K0_TO_PHYSICAL(D_801579A0), 0x800); + gSPLoadUcodeL(gfx++, ucode_s2dex); - func_8009638C(&sp1CC, mapImage, gWorldMapImageTLUT, 216, 128, G_IM_FMT_CI, G_IM_SIZ_8b, 0x8000, 256, - HREG(13) / 100.0f, HREG(14) / 100.0f); + Room_DrawBackground2D(&gfx, gWorldMapImageTex, gWorldMapImageTLUT, 216, 128, G_IM_FMT_CI, G_IM_SIZ_8b, + G_TT_RGBA16, 256, HREG(13) / 100.0f, HREG(14) / 100.0f); - // gSPLoadUcode(sp1CC++, SysUcode_GetUCode(), SysUcode_GetUCodeData())? - gSPLoadUcodeEx(sp1CC++, SysUcode_GetUCode(), SysUcode_GetUCodeData(), 0x800); + gSPLoadUcode(gfx++, SysUcode_GetUCode()); - POLY_KAL_DISP = sp1CC; + POLY_KAL_DISP = gfx; } if (HREG(15) == 2) { From 168323ebc901ce97adc86d2e280864c44a14d802 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 7 Apr 2024 14:27:50 -0400 Subject: [PATCH 135/300] bump LUS (#4042) --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index c3a699403..d795e6ac7 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit c3a699403793c9ac97733179fe078d2e2f271ee1 +Subproject commit d795e6ac7837be79dd14f18f4567f3330c74a423 From 897d3efbd01532e861765c8d968093556ce0aa14 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 7 Apr 2024 17:02:57 -0400 Subject: [PATCH 136/300] rip out unused types (#4041) --- ZAPDTR | 2 +- libultraship | 2 +- soh/soh/resource/type/Cutscene.h | 3 --- soh/soh/resource/type/PlayerAnimation.h | 3 --- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/ZAPDTR b/ZAPDTR index eff290361..9f9d0be3c 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit eff29036118349e142ee8efca80fd975a2a2b6ff +Subproject commit 9f9d0be3c914354ecabab3695581f1123c13ac20 diff --git a/libultraship b/libultraship index d795e6ac7..b135db823 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit d795e6ac7837be79dd14f18f4567f3330c74a423 +Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968 diff --git a/soh/soh/resource/type/Cutscene.h b/soh/soh/resource/type/Cutscene.h index 3ca8b3d50..c4d5fb0d5 100644 --- a/soh/soh/resource/type/Cutscene.h +++ b/soh/soh/resource/type/Cutscene.h @@ -3,9 +3,6 @@ #include #include #include "Resource.h" -#include "Vec2f.h" -#include "Vec3f.h" -#include "Color3b.h" namespace SOH { diff --git a/soh/soh/resource/type/PlayerAnimation.h b/soh/soh/resource/type/PlayerAnimation.h index d8c47a5f6..416b3928c 100644 --- a/soh/soh/resource/type/PlayerAnimation.h +++ b/soh/soh/resource/type/PlayerAnimation.h @@ -3,9 +3,6 @@ #include #include #include "Resource.h" -#include "Vec2f.h" -#include "Vec3f.h" -#include "Color3b.h" namespace SOH { class PlayerAnimation : public LUS::Resource { From e163d5bc3d1e3a7978bf204a4d554f51f6324fb0 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:28:20 +0100 Subject: [PATCH 137/300] Fix switch puzzle locking issues (#4027) --- soh/src/code/z_bgcheck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 7c99e7ca2..064d59860 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -398,7 +398,7 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V (poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC + plane.originDist; -#ifdef __WIIU__ +#if defined(__SWITCH__) || defined(__WIIU__) // on some platforms this ends up as very small numbers due to rounding issues if (IS_ZERO(planeDistA)) { planeDistA = 0.0f; From 6d77bbd4a975c56a89d9011e4fcb3f73c8d25b65 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:55:16 -0400 Subject: [PATCH 138/300] vb skull rewards (#101) --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 28 ++++++++ soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c | 68 ++++++------------- soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h | 2 + 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index f5e70da16..1f0da656f 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -296,6 +296,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, // Opt: *EnDivingGame GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, + // Opt: *EnSth + GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 772ce16aa..933b27e5a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -24,6 +24,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Ms/z_en_ms.h" #include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" #include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" +#include "src/overlays/actors/ovl_En_Sth/z_en_sth.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -763,6 +764,33 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = eligible; break; } + case GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD: { + // In z_en_sth.c the rewards are stored in sGetItemIds, the first entry + // in that array is GI_RUPEE_GOLD, and the reward is picked in EnSth_GivePlayerItem + // via sGetItemIds[this->actor.params]. This means if actor.params == 0 we're looking + // at the 100 GS reward + EnSth* enSth = static_cast(optionalArg); + if (enSth->actor.params == 0) { + // if nothing is shuffled onto 100 GS, + // or we already got the 100 GS reward, + // let the player farm + if (!RAND_GET_OPTION(RSK_SHUFFLE_100_GS_REWARD) || + Flags_GetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD)) { + *should = true; + break; + } + + // we're giving the 100 GS rando reward! set the rando inf + Flags_SetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD); + + // also set the actionfunc so this doesn't immediately get + // called again (and lead to a vanilla+rando item give + // because the flag check will pass next time) + enSth->actionFunc = (EnSthActionFunc)EnSth_RewardObtainedTalk; + } + *should = false; + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index 7a0332910..f8b50d823 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -257,66 +257,34 @@ void EnSth_ParentRewardObtainedWait(EnSth* this, PlayState* play) { void EnSth_GivePlayerItem(EnSth* this, PlayState* play) { u16 getItemId = sGetItemIds[this->actor.params]; - GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; - - if (IS_RANDO) { - switch (getItemId) { - case GI_RUPEE_GOLD: - if (!Flags_GetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD)) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_100_GOLD_SKULLTULA_REWARD, GI_RUPEE_GOLD); - Flags_SetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD); - } - break; - case GI_WALLET_ADULT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_10_GOLD_SKULLTULA_REWARD, GI_WALLET_ADULT); - break; - case GI_STONE_OF_AGONY: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_20_GOLD_SKULLTULA_REWARD, GI_STONE_OF_AGONY); - break; - case GI_WALLET_GIANT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_30_GOLD_SKULLTULA_REWARD, GI_WALLET_GIANT); - break; - case GI_BOMBCHUS_10: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_40_GOLD_SKULLTULA_REWARD, GI_BOMBCHUS_10); - break; - case GI_HEART_PIECE: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_50_GOLD_SKULLTULA_REWARD, GI_HEART_PIECE); - break; - } - getItemId = getItemEntry.getItemId; - } else { - switch (this->actor.params) { - case 1: - case 3: - switch (CUR_UPG_VALUE(UPG_WALLET)) { - case 0: - getItemId = GI_WALLET_ADULT; - break; - case 1: - getItemId = GI_WALLET_GIANT; - break; - } - break; - } + switch (this->actor.params) { + case 1: + case 3: + switch (CUR_UPG_VALUE(UPG_WALLET)) { + case 0: + getItemId = GI_WALLET_ADULT; + break; + + case 1: + getItemId = GI_WALLET_GIANT; + break; + } + break; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } void EnSth_GiveReward(EnSth* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { this->actor.parent = NULL; EnSth_SetupAction(this, EnSth_RewardObtainedTalk); gSaveContext.eventChkInf[EVENTCHKINF_SKULLTULA_REWARD_INDEX] |= this->eventFlag; if (this->eventFlag != 0) { GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SKULLTULA_REWARD_INDEX << 4) + sEventFlagsShift[this->actor.params]); } - } else { + } else if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { EnSth_GivePlayerItem(this, play); } EnSth_FacePlayer(this, play); @@ -326,7 +294,9 @@ void EnSth_RewardUnobtainedTalk(EnSth* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); EnSth_SetupAction(this, EnSth_GiveReward); - EnSth_GivePlayerItem(this, play); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { + EnSth_GivePlayerItem(this, play); + } } EnSth_FacePlayer(this, play); } diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h index 9391496ae..c0001f955 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h @@ -25,4 +25,6 @@ typedef struct EnSth { /* 0x02B8 */ EnSthActionFunc actionFunc; } EnSth; // size = 0x02BC +void EnSth_RewardObtainedTalk(EnSth* enSth, PlayState* play); + #endif From 9c9fc49d32847a7cce24336a12ce43fd57958574 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:59:48 -0400 Subject: [PATCH 139/300] vb horseback archery (#102) * vb horseback archery * Update soh/soh/Enhancements/randomizer/hook_handlers.cpp --------- Co-authored-by: Garrett Cox --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 8 ++ soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 77 ++++++------------- 3 files changed, 33 insertions(+), 54 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 1f0da656f..ad3ff9d6f 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -296,6 +296,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, // Opt: *EnDivingGame GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, + // Opt: *EnGe1 + GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, // Opt: *EnSth GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 933b27e5a..788701b9c 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -764,6 +764,14 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = eligible; break; } + case GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY: { + // give both rewards at the same time + if (gSaveContext.minigameScore >= 1500) { + Flags_SetItemGetInf(ITEMGETINF_0F); + } + *should = false; + break; + } case GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD: { // In z_en_sth.c the rewards are stored in sGetItemIds, the first entry // in that array is GI_RUPEE_GOLD, and the reward is picked in EnSth_GivePlayerItem diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index c72205b8f..995e3d5fd 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_ge1/object_ge1.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -531,16 +532,8 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; s32 getItemId; - if (Actor_HasParent(&this->actor, play)) { - if (IS_RANDO && gSaveContext.minigameScore >= 1500 && !Flags_GetInfTable(INFTABLE_190)) { - Flags_SetItemGetInf(ITEMGETINF_0F); - Flags_SetInfTable(INFTABLE_190); - this->stateFlags |= GE1_STATE_GIVE_QUIVER; - this->actor.parent = NULL; - return; - } else { - this->actionFunc = EnGe1_SetupWait_Archery; - } + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + this->actionFunc = EnGe1_SetupWait_Archery; if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { Flags_SetItemGetInf(ITEMGETINF_0F); @@ -549,33 +542,21 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { } } else { if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { - if (!IS_RANDO) { - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - //! @bug Asschest. See next function for details - case 1: - getItemId = GI_QUIVER_40; - break; - case 2: - getItemId = GI_QUIVER_50; - break; - } - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); - getItemId = getItemEntry.getItemId; + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + //! @bug Asschest. See next function for details + case 1: + getItemId = GI_QUIVER_40; + break; + case 2: + getItemId = GI_QUIVER_50; + break; } } else { - if (!IS_RANDO) { - getItemId = GI_HEART_PIECE; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_HEART_PIECE; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } } @@ -590,33 +571,21 @@ void EnGe1_BeginGiveItem_Archery(EnGe1* this, PlayState* play) { } if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { - if (!IS_RANDO) { - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - //! @bug Asschest. See next function for details - case 1: - getItemId = GI_QUIVER_40; - break; - case 2: - getItemId = GI_QUIVER_50; - break; - } - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); - getItemId = getItemEntry.getItemId; + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + //! @bug Asschest. See next function for details + case 1: + getItemId = GI_QUIVER_40; + break; + case 2: + getItemId = GI_QUIVER_50; + break; } } else { - if (!IS_RANDO) { - getItemId = GI_HEART_PIECE; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_HEART_PIECE; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } From fe231147d5b1942c2b700640f25d5faddc672dad Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:46:11 -0400 Subject: [PATCH 140/300] vb underwater item (#104) * underwater working pre func_80B858B4 replacement * underwater item update handled by hookhandlers * remove commented out code * remove unused should --- .../Enhancements/randomizer/hook_handlers.cpp | 39 +++++++++++++++++++ .../ovl_Item_Etcetera/z_item_etcetera.c | 35 ++--------------- .../ovl_Item_Etcetera/z_item_etcetera.h | 3 ++ 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 788701b9c..31ba23427 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -25,6 +25,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" #include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" #include "src/overlays/actors/ovl_En_Sth/z_en_sth.h" +#include "src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -274,6 +275,27 @@ void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { } } +void ItemEtcetera_DrawRandomizedItem(ItemEtcetera* itemEtcetera, PlayState* play) { + EnItem00_CustomItemsParticles(&itemEtcetera->actor, play, itemEtcetera->sohItemEntry); + GetItemEntry_Draw(play, itemEtcetera->sohItemEntry); +} + +void ItemEtcetera_func_80B858B4_Randomized(ItemEtcetera* itemEtcetera, PlayState* play) { + if (itemEtcetera->actor.xzDistToPlayer < 30.0f && + fabsf(itemEtcetera->actor.yDistToPlayer) < 50.0f) { + if ((itemEtcetera->actor.params & 0xFF) == 1) { + Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); + Flags_SetSwitch(play, 0xB); + } + + Actor_Kill(&itemEtcetera->actor); + } else { + if ((play->gameplayFrames & 0xD) == 0) { + EffectSsBubble_Spawn(play, &itemEtcetera->actor.world.pos, 0.0f, 0.0f, 10.0f, 0.13f); + } + } +} + void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) { bool moved = false; @@ -954,6 +976,23 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } } + + if (actor->id == ACTOR_ITEM_ETCETERA) { + ItemEtcetera* itemEtcetera = static_cast(actorRef); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(itemEtcetera->actor.id, gPlayState->sceneNum, itemEtcetera->actor.params); + if (rc != RC_UNKNOWN_CHECK) { + itemEtcetera->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + itemEtcetera->drawFunc = (ActorFunc)ItemEtcetera_DrawRandomizedItem; + } + + int32_t type = itemEtcetera->actor.params & 0xFF; + switch (type) { + case ITEM_ETC_LETTER: { + itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_func_80B858B4_Randomized; + break; + } + } + } } void RandomizerRegisterHooks() { diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index 6fdf162db..db42bc15b 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -83,8 +83,7 @@ void ItemEtcetera_Init(Actor* thisx, PlayState* play) { case ITEM_ETC_LETTER: Actor_SetScale(&this->actor, 0.5f); this->futureActionFunc = func_80B858B4; - if ((Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER) && !IS_RANDO) || - (IS_RANDO && Flags_GetTreasure(play, 0x1E))) { + if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER)) { Actor_Kill(&this->actor); } break; @@ -147,21 +146,11 @@ void func_80B858B4(ItemEtcetera* this, PlayState* play) { if ((this->actor.params & 0xFF) == 1) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); Flags_SetSwitch(play, 0xB); - - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1E); - } } + Actor_Kill(&this->actor); } else { - if (0) {} // Necessary to match - - if (!IS_RANDO) { - Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); if ((play->gameplayFrames & 0xD) == 0) { EffectSsBubble_Spawn(play, &this->actor.world.pos, 0.0f, 0.0f, 10.0f, 0.13f); @@ -246,24 +235,6 @@ void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; s32 type = this->actor.params & 0xFF; - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); - } else if (type == ITEM_ETC_LETTER) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); - } - - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - - if (randoGetItem.itemId != ITEM_NONE) { - func_8002EBCC(&this->actor, play, 0); - func_8002ED80(&this->actor, play, 0); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); GetItem_Draw(play, this->giDrawId); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h index 3ec33b926..ceec9c8b1 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h @@ -16,6 +16,9 @@ typedef struct ItemEtcetera { /* 0x0154 */ u8 objBankIndex; /* 0x0158 */ ActorFunc drawFunc; /* 0x015C */ ItemEtceteraActionFunc actionFunc; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } ItemEtcetera; // size = 0x0160 typedef enum { From bbbd2520b1611f18da2df7ba13751d9da2694636 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:57:07 -0400 Subject: [PATCH 141/300] vb lh sun (#106) * underwater working pre func_80B858B4 replacement * underwater item update handled by hookhandlers * vb lh sun * remove unused should --- .../Enhancements/randomizer/hook_handlers.cpp | 44 +++++++++++++++++++ .../ovl_Item_Etcetera/z_item_etcetera.c | 14 +----- .../ovl_Item_Etcetera/z_item_etcetera.h | 2 + 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 31ba23427..ce24e11d9 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -277,6 +277,8 @@ void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { void ItemEtcetera_DrawRandomizedItem(ItemEtcetera* itemEtcetera, PlayState* play) { EnItem00_CustomItemsParticles(&itemEtcetera->actor, play, itemEtcetera->sohItemEntry); + func_8002EBCC(&itemEtcetera->actor, play, 0); + func_8002ED80(&itemEtcetera->actor, play, 0); GetItemEntry_Draw(play, itemEtcetera->sohItemEntry); } @@ -296,6 +298,44 @@ void ItemEtcetera_func_80B858B4_Randomized(ItemEtcetera* itemEtcetera, PlayState } } +void ItemEtcetera_func_80B85824_Randomized(ItemEtcetera* itemEtcetera, PlayState* play) { + if ((itemEtcetera->actor.params & 0xFF) != 7) { + return; + } + + if (itemEtcetera->actor.xzDistToPlayer < 30.0f && + fabsf(itemEtcetera->actor.yDistToPlayer) < 50.0f) { + + Flags_SetTreasure(play, 0x1F); + Actor_Kill(&itemEtcetera->actor); + } +} + +void ItemEtcetera_MoveRandomizedFireArrowDown(ItemEtcetera* itemEtcetera, PlayState* play) { + Actor_UpdateBgCheckInfo(play, &itemEtcetera->actor, 10.0f, 10.0f, 0.0f, 5); + Actor_MoveForward(&itemEtcetera->actor); + if (!(itemEtcetera->actor.bgCheckFlags & 1)) { + ItemEtcetera_SpawnSparkles(itemEtcetera, play); + } + itemEtcetera->actor.shape.rot.y += 0x400; + ItemEtcetera_func_80B85824_Randomized(itemEtcetera, play); +} + +void ItemEtcetera_UpdateRandomizedFireArrow(ItemEtcetera* itemEtcetera, PlayState* play) { + if ((play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[0] != NULL)) { + if (play->csCtx.npcActions[0]->action == 2) { + itemEtcetera->actor.draw = (ActorFunc)ItemEtcetera_DrawRandomizedItem; + itemEtcetera->actor.gravity = -0.1f; + itemEtcetera->actor.minVelocityY = -4.0f; + itemEtcetera->actionFunc = ItemEtcetera_MoveRandomizedFireArrowDown; + } + } else { + itemEtcetera->actor.gravity = -0.1f; + itemEtcetera->actor.minVelocityY = -4.0f; + itemEtcetera->actionFunc = ItemEtcetera_MoveRandomizedFireArrowDown; + } +} + void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) { bool moved = false; @@ -991,6 +1031,10 @@ void RandomizerOnActorInitHandler(void* actorRef) { itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_func_80B858B4_Randomized; break; } + case ITEM_ETC_ARROW_FIRE: { + itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_UpdateRandomizedFireArrow; + break; + } } } } diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index db42bc15b..8a26860f7 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -120,24 +120,13 @@ void func_80B857D0(ItemEtcetera* this, PlayState* play) { void func_80B85824(ItemEtcetera* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { - if ((this->actor.params & 0xFF) == 7) { - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1F); - } - } - if ((this->actor.params & 0xFF) == 1) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); Flags_SetSwitch(play, 0xB); } Actor_Kill(&this->actor); } else { - if (!IS_RANDO) { - Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); } } @@ -233,7 +222,6 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; - s32 type = this->actor.params & 0xFF; func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h index ceec9c8b1..5293292a4 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h @@ -38,4 +38,6 @@ typedef enum { /* 0x0D */ ITEM_ETC_KEY_SMALL_CHEST_GAME } ItemEtceteraType; +void ItemEtcetera_SpawnSparkles(ItemEtcetera* ItemEtcetera, PlayState* play); + #endif From f3273e76273ae38306412ddf324be21511a80de9 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:31:45 -0400 Subject: [PATCH 142/300] vb treasure chest game (#103) --- soh/include/functions.h | 2 - .../game-interactor/GameInteractor.h | 1 + .../randomizer/3drando/item_pool.cpp | 15 ++-- .../location_access/locacc_castle_town.cpp | 10 +-- .../Enhancements/randomizer/hook_handlers.cpp | 85 +++++++++++++++++++ .../Enhancements/randomizer/location_list.cpp | 20 +++-- .../Enhancements/randomizer/randomizer.cpp | 31 ++++--- .../Enhancements/randomizer/randomizerTypes.h | 10 +++ .../Enhancements/randomizer/randomizer_inf.h | 11 +++ soh/src/code/z_actor.c | 55 ------------ .../overlays/actors/ovl_Door_Ana/z_door_ana.c | 1 - .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 32 +++---- .../ovl_Item_Etcetera/z_item_etcetera.c | 10 --- .../actors/ovl_player_actor/z_player.c | 2 +- 14 files changed, 170 insertions(+), 115 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 8efad485a..8ee00ed8d 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -575,8 +575,6 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag); u16 func_80037C30(PlayState* play, s16 arg1); s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3); s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4); -GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play); -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play); // ? func_80038600(?); u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index ad3ff9d6f..3790545fd 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -254,6 +254,7 @@ typedef enum { /*** Give Items ***/ + // Opt: *EnBox GI_VB_GIVE_ITEM_FROM_CHEST, GI_VB_GIVE_ITEM_FROM_BLUE_WARP, // Opt: *EnItem00 diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index a54f522aa..e3e0aa322 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -904,11 +904,16 @@ void GenerateItemPool() { } else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) { AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6 } else { - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, false, true); }; if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index 874cc76c1..f48a2bb53 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -234,11 +234,11 @@ void AreaTable_Init_CastleTown() { //Locations LocationAccess(RC_GREG_HINT, {[]{return true;}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index ce24e11d9..ae6beb869 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -26,6 +26,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" #include "src/overlays/actors/ovl_En_Sth/z_en_sth.h" #include "src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h" +#include "src/overlays/actors/ovl_En_Box/z_en_box.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -282,6 +283,12 @@ void ItemEtcetera_DrawRandomizedItem(ItemEtcetera* itemEtcetera, PlayState* play GetItemEntry_Draw(play, itemEtcetera->sohItemEntry); } +void ItemEtcetera_DrawRandomizedItemThroughLens(ItemEtcetera* itemEtcetera, PlayState* play) { + if (play->actorCtx.lensActive) { + ItemEtcetera_DrawRandomizedItem(itemEtcetera, play); + } +} + void ItemEtcetera_func_80B858B4_Randomized(ItemEtcetera* itemEtcetera, PlayState* play) { if (itemEtcetera->actor.xzDistToPlayer < 30.0f && fabsf(itemEtcetera->actor.yDistToPlayer) < 50.0f) { @@ -394,9 +401,50 @@ RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) { } } +void RandomizerSetChestGameRandomizerInf(RandomizerCheck rc) { + switch (rc) { + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_1: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_2: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_3: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_4: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_5: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_1: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_2: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_3: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_4: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_5: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5); + break; + } +} + void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) { switch (id) { case GI_VB_GIVE_ITEM_FROM_CHEST: { + EnBox* chest = static_cast(optionalArg); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(chest->dyna.actor.id, gPlayState->sceneNum, chest->dyna.actor.params); + + // if this is a treasure chest game chest then set the appropriate rando inf + RandomizerSetChestGameRandomizerInf(rc); + Player* player = GET_PLAYER(gPlayState); player->av2.actionVar2 = 1; player->getItemId = GI_NONE; @@ -895,6 +943,32 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } void RandomizerOnSceneInitHandler(int16_t sceneNum) { + // Treasure Chest Game + // todo: for now we're just unsetting all of them, we will + // probably need to do something different when we implement shuffle + if (sceneNum == SCENE_TREASURE_BOX_SHOP) { + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_1)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_2)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_3)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_4)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_5)->MarkAsNotObtained(); + } + // LACs & Prelude checks static uint32_t updateHook = 0; @@ -1035,6 +1109,17 @@ void RandomizerOnActorInitHandler(void* actorRef) { itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_UpdateRandomizedFireArrow; break; } + case ITEM_ETC_RUPEE_GREEN_CHEST_GAME: + case ITEM_ETC_RUPEE_BLUE_CHEST_GAME: + case ITEM_ETC_RUPEE_RED_CHEST_GAME: + case ITEM_ETC_RUPEE_PURPLE_CHEST_GAME: + case ITEM_ETC_HEART_PIECE_CHEST_GAME: + case ITEM_ETC_KEY_SMALL_CHEST_GAME: { + if (rc != RC_UNKNOWN_CHECK) { + itemEtcetera->drawFunc = (ActorFunc)ItemEtcetera_DrawRandomizedItemThroughLens; + } + break; + } } } } diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 0ff2837db..39f9b7477 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -207,6 +207,11 @@ std::vector Rando::StaticData::overworldLocations = { RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RC_MARKET_TREASURE_CHEST_GAME_KEY_1, + RC_MARKET_TREASURE_CHEST_GAME_KEY_2, + RC_MARKET_TREASURE_CHEST_GAME_KEY_3, + RC_MARKET_TREASURE_CHEST_GAME_KEY_4, + RC_MARKET_TREASURE_CHEST_GAME_KEY_5, // Market Shops RC_MARKET_BOMBCHU_SHOP_ITEM_1, @@ -674,11 +679,16 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_191), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x05, "Chest Game Third Room Chest", "MK Chest Game Third Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x07, "Chest Game Fourth Room Chest", "MK Chest Game Fourth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x09, "Chest Game Fifth Room Chest", "MK Chest Game Fifth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Item", "MK Chest Game First Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Item", "MK Chest Game Second Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Item", "MK Chest Game Third Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Item", "MK Chest Game Fourth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Item", "MK Chest Game Fifth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Key", "MK Chest Game First Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Key", "MK Chest Game Second Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Key", "MK Chest Game Third Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Key", "MK Chest Game Fourth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Key", "MK Chest Game Fifth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Hyrule Castle locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5d32e7a35..eb34721b5 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1649,21 +1649,28 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, RandomizerCheck specialRc = RC_UNKNOWN_CHECK; // TODO: Migrate these special cases into table, or at least document why they are special switch(sceneNum) { - case SCENE_TREASURE_BOX_SHOP: - if(actorParams == 20170) specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD; + case SCENE_TREASURE_BOX_SHOP: { + if ((actorId == ACTOR_EN_BOX && actorParams == 20170) || (actorId == ACTOR_ITEM_ETCETERA && actorParams == 2572)) { + specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD; + } - // RANDOTODO update logic to match 3ds rando when we implement keysanity - // keep keys og - if ((actorParams & 0x60) == 0x20) break; - - if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if((actorParams & 0xF) < 2) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_1; - if((actorParams & 0xF) < 4) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_2; - if((actorParams & 0xF) < 6) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_3; - if((actorParams & 0xF) < 8) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_4; - if((actorParams & 0xF) < 10) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_5; + // todo: handle the itemetc part of this so drawing works when we implement shuffle + if (actorId == ACTOR_EN_BOX) { + bool isAKey = (actorParams & 0x60) == 0x20; + if ((actorParams & 0xF) < 2) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_1 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_1; + } else if ((actorParams & 0xF) < 4) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_2 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_2; + } else if ((actorParams & 0xF) < 6) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_3 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_3; + } else if ((actorParams & 0xF) < 8) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_4 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_4; + } else if ((actorParams & 0xF) < 10) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_5 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_5; + } } break; + } case SCENE_SACRED_FOREST_MEADOW: if (actorId == ACTOR_EN_SA) { specialRc = RC_SONG_FROM_SARIA; diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 91906d127..f1d368763 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -733,6 +733,11 @@ typedef enum { RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RC_MARKET_TREASURE_CHEST_GAME_KEY_1, + RC_MARKET_TREASURE_CHEST_GAME_KEY_2, + RC_MARKET_TREASURE_CHEST_GAME_KEY_3, + RC_MARKET_TREASURE_CHEST_GAME_KEY_4, + RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RC_MARKET_GS_GUARD_HOUSE, RC_MARKET_BAZAAR_ITEM_1, RC_MARKET_BAZAAR_ITEM_2, @@ -2332,6 +2337,11 @@ typedef enum { RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RHT_MARKET_GS_GUARD_HOUSE, RHT_MARKET_BAZAAR_ITEM_1, RHT_MARKET_BAZAAR_ITEM_2, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 67b396d74..14749e574 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -282,6 +282,17 @@ typedef enum { RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, RAND_INF_OGC_GREAT_FAIRY_REWARD, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5, + // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index e4edcc1d3..2379c8ba9 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -6275,58 +6275,3 @@ s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f return true; } - -GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play) { - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - // RANDOTODO update this logic when we implement keysanity - // because 3drando replaces the keys not the rupees - if (ogDrawId == GID_RUPEE_GREEN || - ogDrawId == GID_RUPEE_BLUE || - ogDrawId == GID_RUPEE_RED) - { - switch(room) { - case 1: - if(!Flags_GetCollectible(play, 0x1B)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, GI_RUPEE_GREEN); - } - break; - case 2: - if(!Flags_GetCollectible(play, 0x1C)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, GI_RUPEE_GREEN); - } - break; - case 3: - if(!Flags_GetCollectible(play, 0x1D)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, GI_RUPEE_BLUE); - } - break; - case 4: - if(!Flags_GetCollectible(play, 0x1E)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, GI_RUPEE_BLUE); - } - break; - case 5: - if(!Flags_GetCollectible(play, 0x1F)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, GI_RUPEE_RED); - } - break; - } - } - } - - if(ogDrawId == GID_HEART_PIECE) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_REWARD, GI_HEART_PIECE); - } - - return (GetItemEntry)GET_ITEM_NONE; -} - -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(room, ogDrawId, play); - - if (randoGetItem.itemId != ITEM_NONE) { - return randoGetItem.gid; - } - - return ogDrawId; -} diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index 22c850111..04f388b39 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -20,7 +20,6 @@ void DoorAna_WaitClosed(DoorAna* this, PlayState* play); void DoorAna_WaitOpen(DoorAna* this, PlayState* play); void DoorAna_GrabPlayer(DoorAna* this, PlayState* play); -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play); void Grotto_OverrideActorEntrance(Actor* thisx); const ActorInit Door_Ana_InitVars = { diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 32f50d9e1..3860336ef 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -229,25 +229,19 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { this->scale = 0.5f; this->unkFloat = 0.5f; this->actor.velocity.y = 10.0f; - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - switch (this->type) { - case EXITEM_GREEN_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_GREEN; - break; - case EXITEM_BLUE_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_BLUE; - break; - case EXITEM_RED_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_RED; - break; - case EXITEM_14: - this->giDrawId = GID_RUPEE_PURPLE; - break; - } - } else { - if (play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - this->giDrawId = GetChestGameRandoGiDrawId(play->roomCtx.curRoom.num, GID_RUPEE_GREEN, play); - } + switch (this->type) { + case EXITEM_GREEN_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_GREEN; + break; + case EXITEM_BLUE_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_BLUE; + break; + case EXITEM_RED_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_RED; + break; + case EXITEM_14: + this->giDrawId = GID_RUPEE_PURPLE; + break; } this->actionFunc = EnExItem_ExitChest; break; diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index 8a26860f7..796b157a3 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -206,16 +206,6 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { if (play->actorCtx.lensActive) { func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); - - if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - if (randoGetItem.itemId != ITEM_NONE) { - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - GetItem_Draw(play, this->giDrawId); } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 7125500f7..dff81a13e 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6866,7 +6866,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { } func_80836898(play, this, func_8083A434); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, &giEntry)) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, chest)) { this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; func_8083AE40(this, giEntry.objectId); } From ced34ab68a3b76cd27f636bd98469e962b7b9d03 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:00:04 +0100 Subject: [PATCH 143/300] [Fix] Disable Lod Applies To Everything (Macready) (#4034) * make lod cvar affect everything * add to more functions * re-add to player * only add to necessary funcs --- soh/src/code/z_fcurve_data_skelanime.c | 4 ++++ soh/src/code/z_skelanime.c | 8 ++++++++ soh/src/overlays/actors/ovl_player_actor/z_player.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index c75450be2..b75c34a61 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -131,6 +131,10 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv Matrix_TranslateRotateZYX(&pos, &rot); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (lod == 0) { s32 pad1; diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 7440640a0..2123c2d3b 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -78,6 +78,10 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3f pos; Vec3s rot; + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (skeleton == NULL) { osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL." @@ -191,6 +195,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3s rot; Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx)); + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (skeleton == NULL) { osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL." diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index ca7333497..965389c40 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11339,7 +11339,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) { lod = 1; } - if (CVarGetInteger("gDisableLOD", 0) != 0) { + if (CVarGetInteger("gDisableLOD", 0)) { lod = 0; } From 63afaa3cc993254cc35c4acc92ce1f31759f09cd Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 16 Apr 2024 20:18:26 -0400 Subject: [PATCH 144/300] vb ocarina memory (#107) * Ocarina Memory Game * vb memory game --------- Co-authored-by: Taw --- .../game-interactor/GameInteractor.h | 2 ++ .../Enhancements/randomizer/hook_handlers.cpp | 8 ++++++ soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 27 ++++++------------- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h | 2 ++ 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 3790545fd..440a241ef 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -287,6 +287,8 @@ typedef enum { // Opt: *EnFr GI_VB_GIVE_ITEM_FROM_FROGS, // Opt: *EnSkj + GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, + // Opt: *EnSkj GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, // Opt: *EnSyatekiMan diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index ae6beb869..47441fb31 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -27,6 +27,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Sth/z_en_sth.h" #include "src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h" #include "src/overlays/actors/ovl_En_Box/z_en_box.h" +#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -909,6 +910,13 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } + case GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME: { + EnSkj* enSkj = static_cast(optionalArg); + Flags_SetItemGetInf(ITEMGETINF_17); + enSkj->actionFunc = (EnSkjActionFunc)EnSkj_CleanupOcarinaGame; + *should = false; + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 344a09f19..94df7a49f 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1541,7 +1541,9 @@ void EnSkj_WaitForOfferResponse(EnSkj* this, PlayState* play) { void EnSkj_WonOcarinaMiniGame(EnSkj* this, PlayState* play) { if (D_80B01EA0) { - this->actionFunc = EnSkj_WaitToGiveReward; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, true, this)) { + this->actionFunc = EnSkj_WaitToGiveReward; + } } else { func_8002F2CC(&this->actor, play, 26.0f); } @@ -1549,13 +1551,8 @@ void EnSkj_WonOcarinaMiniGame(EnSkj* this, PlayState* play) { void EnSkj_WaitToGiveReward(EnSkj* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (IS_RANDO && gSaveContext.ocarinaGameRoundNum != 3) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); - } else { - Actor_OfferGetItem(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); - } - + Actor_OfferGetItem(&this->actor, play, + sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); this->actionFunc = EnSkj_GiveOcarinaGameReward; } } @@ -1565,12 +1562,8 @@ void EnSkj_GiveOcarinaGameReward(EnSkj* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnSkj_FinishOcarinaGameRound; } else { - if (IS_RANDO && gSaveContext.ocarinaGameRoundNum != 3) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); - } else { - Actor_OfferGetItem(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); - } + Actor_OfferGetItem(&this->actor, play, + sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); } } @@ -1582,11 +1575,7 @@ void EnSkj_FinishOcarinaGameRound(EnSkj* this, PlayState* play) { gSaveContext.ocarinaGameRoundNum++; } - if (IS_RANDO) { - gSaveContext.ocarinaGameRoundNum = 3; - } - - if (ocarinaGameRoundNum == 2 || IS_RANDO) { + if (ocarinaGameRoundNum == 2) { Flags_SetItemGetInf(ITEMGETINF_17); this->actionFunc = EnSkj_CleanupOcarinaGame; } else { diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h index bc8febcd4..3f8b75ba2 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h @@ -37,4 +37,6 @@ typedef struct EnSkj { /* 0x02F4 */ Vec3f posCopy; } EnSkj; // size = 0x0300 +void EnSkj_CleanupOcarinaGame(EnSkj* enSkj, PlayState* play); + #endif From 60d74f720a0c9b032b1f4bbd7392b95102da01f3 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 16 Apr 2024 20:28:20 -0400 Subject: [PATCH 145/300] vb richard (#108) * Lost Dog + Custom Hook Handler * vb richard * fix the merge --------- Co-authored-by: Taw --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 10 ++++ soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c | 54 +++++++------------ soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h | 2 + 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 440a241ef..a4054f2cb 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -303,6 +303,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, // Opt: *EnSth GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, + // Opt: *EnHy + GI_VB_GIVE_ITEM_FROM_LOST_DOG, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 47441fb31..dcc36873a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -28,6 +28,7 @@ extern "C" { #include "src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h" #include "src/overlays/actors/ovl_En_Box/z_en_box.h" #include "src/overlays/actors/ovl_En_Skj/z_en_skj.h" +#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -917,6 +918,15 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } + case GI_VB_GIVE_ITEM_FROM_LOST_DOG: { + EnHy* enHy = static_cast(optionalArg); + Flags_SetInfTable(INFTABLE_191); + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + enHy->actionFunc = func_80A7127C; + *should = false; + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index 6d8640f3f..adb50441e 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -14,6 +14,7 @@ #include "objects/object_cne/object_cne.h" #include "objects/object_cob/object_cob.h" #include "objects/object_os_anime/object_os_anime.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -659,19 +660,10 @@ s16 func_80A70058(PlayState* play, Actor* thisx) { gSaveContext.dogParams = 0; break; case 0x709F: - if (Flags_GetInfTable(INFTABLE_191)) { // Already brought the lost dog back - func_80A6F7CC(this, play, GI_RUPEE_BLUE); - } else { - if (!IS_RANDO) { - func_80A6F7CC(this, play, GI_HEART_PIECE); - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_LOST_DOG, GI_HEART_PIECE); - // The follownig line and last arguments of GiveItemEntryFromActor are copied from func_80A6F7CC - this->unkGetItemId = this->getItemEntry.getItemId; - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LOST_DOG, true, this)) { + func_80A6F7CC(this, play, Flags_GetInfTable(INFTABLE_191) ? GI_RUPEE_BLUE : GI_HEART_PIECE); + this->actionFunc = func_80A714C4; } - this->actionFunc = func_80A714C4; break; } return NPC_TALK_STATE_IDLE; @@ -1068,36 +1060,26 @@ void func_80A714C4(EnHy* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80A71530; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - Actor_OfferGetItem(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + Actor_OfferGetItem(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); } } void func_80A71530(EnHy* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (IS_RANDO) { - if (!Flags_GetInfTable(INFTABLE_191)) { - Flags_SetInfTable(INFTABLE_191); - } - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - } else { - switch (this->unkGetItemId) { - case GI_HEART_PIECE: - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - Flags_SetInfTable(INFTABLE_191); - break; - case GI_RUPEE_BLUE: - Rupees_ChangeBy(5); - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - break; - } + switch (this->unkGetItemId) { + case GI_HEART_PIECE: + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + SET_INFTABLE(INFTABLE_191); + break; + case GI_RUPEE_BLUE: + Rupees_ChangeBy(5); + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + break; } + this->actionFunc = func_80A7127C; } } diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h index 6a5ed2680..7d94a5ca6 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h @@ -62,4 +62,6 @@ typedef struct EnHy { /* */ GetItemEntry getItemEntry; } EnHy; // size = 0x0334 +void func_80A7127C(EnHy* enHy, PlayState* play); + #endif From 84db4c8ab807112bd8931c7cf78f46da61c1b583 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:02:16 -0400 Subject: [PATCH 146/300] vb beehives (#109) * vb beehives * format --- .../Enhancements/randomizer/hook_handlers.cpp | 78 ++++++++++++++++++- .../overlays/actors/ovl_Obj_Comb/z_obj_comb.c | 29 +------ .../overlays/actors/ovl_Obj_Comb/z_obj_comb.h | 2 + 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index dcc36873a..f1715c8eb 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -29,6 +29,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Box/z_en_box.h" #include "src/overlays/actors/ovl_En_Skj/z_en_skj.h" #include "src/overlays/actors/ovl_En_Hy/z_en_hy.h" +#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -599,7 +600,11 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void case GI_VB_GIVE_ITEM_FROM_ITEM_00: { EnItem00* item00 = static_cast(optionalArg); if (item00->actor.params == ITEM00_SOH_DUMMY) { - Flags_SetCollectible(gPlayState, item00->collectibleFlag); + if (item00->randoInf != RAND_INF_MAX) { + Flags_SetRandomizerInf(item00->randoInf); + } else { + Flags_SetCollectible(gPlayState, item00->collectibleFlag); + } Actor_Kill(&item00->actor); *should = false; } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY) { @@ -1043,6 +1048,70 @@ void EnDns_RandomizerPurchase(EnDns* enDns) { Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf); } +void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) { + s16 params = objComb->actor.params & 0x1F; + + if ( + RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && + !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf) + ) { + EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = objComb->beehiveIdentity.randomizerInf; + item00->itemEntry = OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + return; + } + + if ((params > 0) || (params < 0x1A)) { + if (params == 6) { + if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) { + params = -1; + } else { + params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8)); + } + } else if (Rand_ZeroOne() < 0.5f) { + params = -1; + } + if (params >= 0 && !CVarGetInteger("gNoRandomDrops", 0)) { + Item_DropCollectible(play, &objComb->actor.world.pos, params); + } + } +} + +void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) { + s32 dmgFlags; + + objComb->unk_1B0 -= 50; + if ( + RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && + !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf) + ) { + if (objComb->unk_1B0 <= -5000) { + objComb->unk_1B0 = 1500; + } + } else if (objComb->unk_1B0 < 0) { + objComb->unk_1B0 = 0; + } + + if ((objComb->collider.base.acFlags & AC_HIT) != 0) { + objComb->collider.base.acFlags &= ~AC_HIT; + dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags; + if (dmgFlags & 0x4001F866) { + objComb->unk_1B0 = 1500; + } else { + ObjComb_Break(objComb, play); + ObjComb_RandomizerChooseItemDrop(objComb, play); + Actor_Kill(&objComb->actor); + } + } else { + CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base); + } + + if (objComb->actor.update != NULL) { + CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base); + } +} + void RandomizerOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); @@ -1140,6 +1209,13 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } } + + if (actor->id == ACTOR_OBJ_COMB) { + ObjComb* objComb = static_cast(actorRef); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(gPlayState->sceneNum, (s16)actor->world.pos.x, respawnData); + objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait; + } } void RandomizerRegisterHooks() { diff --git a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c index 0dde415e0..e17de7597 100644 --- a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c +++ b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c @@ -132,21 +132,6 @@ void ObjComb_Break(ObjComb* this, PlayState* play) { void ObjComb_ChooseItemDrop(ObjComb* this, PlayState* play) { s16 params = this->actor.params & 0x1F; - if ( - IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_BEEHIVES) && - !Flags_GetRandomizerInf(this->beehiveIdentity.randomizerInf) - ) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(this->beehiveIdentity.randomizerCheck, GI_NONE); - - EnItem00* actor = (EnItem00*)Item_DropCollectible2(play, &this->actor.world.pos, ITEM00_SMALL_KEY); - actor->randoCheck = this->beehiveIdentity.randomizerCheck; - actor->randoGiEntry = getItemEntry; - actor->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - actor->randoInf = this->beehiveIdentity.randomizerInf; - return; - } - if ((params > 0) || (params < 0x1A)) { if (params == 6) { if (Flags_GetCollectible(play, (this->actor.params >> 8) & 0x3F)) { @@ -170,10 +155,6 @@ void ObjComb_Init(Actor* thisx, PlayState* play) { Collider_InitJntSph(play, &this->collider); Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->colliderItems); ObjComb_SetupWait(this); - if (IS_RANDO) { - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - this->beehiveIdentity = Randomizer_IdentifyBeehive(play->sceneNum, (s16)this->actor.world.pos.x, respawnData); - } } void ObjComb_Destroy(Actor* thisx, PlayState* play2) { @@ -191,15 +172,7 @@ void ObjComb_Wait(ObjComb* this, PlayState* play) { s32 dmgFlags; this->unk_1B0 -= 50; - if ( - IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_BEEHIVES) && - !Flags_GetRandomizerInf(this->beehiveIdentity.randomizerInf) - ) { - if (this->unk_1B0 <= -5000) { - this->unk_1B0 = 1500; - } - } else if (this->unk_1B0 < 0) { + if (this->unk_1B0 < 0) { this->unk_1B0 = 0; } diff --git a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h index f7713a961..ded72dfc4 100644 --- a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h +++ b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h @@ -18,4 +18,6 @@ typedef struct ObjComb { /* */ BeehiveIdentity beehiveIdentity; } ObjComb; // size = 0x01B4 +void ObjComb_Break(ObjComb* objComb, PlayState* play); + #endif From f6a583446b21cd0f338a718d13700c1602036da7 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 17 Apr 2024 20:49:29 -0400 Subject: [PATCH 147/300] vb bombchu bowling (#110) * vb bombchu bowling * don't need it * it's drawing the right thing but it's tiny * scale * no need to should, don't rescale every draw * slightly safer --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 59 +++++++++++++++++++ .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c | 35 ++--------- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h | 1 - .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 48 ++------------- .../actors/ovl_En_Ex_Item/z_en_ex_item.h | 5 ++ 6 files changed, 75 insertions(+), 75 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index a4054f2cb..89d2467c6 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -305,6 +305,8 @@ typedef enum { GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, // Opt: *EnHy GI_VB_GIVE_ITEM_FROM_LOST_DOG, + // Opt: *EnBomBowlPit + GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f1715c8eb..07f2ecb54 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -30,6 +30,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Skj/z_en_skj.h" #include "src/overlays/actors/ovl_En_Hy/z_en_hy.h" #include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h" +#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -256,6 +257,30 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { } } +void EnExItem_DrawRandomizedItem(EnExItem* enExItem, PlayState* play) { + func_8002ED80(&enExItem->actor, play, 0); + EnItem00_CustomItemsParticles(&enExItem->actor, play, enExItem->sohItemEntry); + GetItemEntry_Draw(play, enExItem->sohItemEntry); +} + +void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) { + EnExItem_WaitForObject(enExItem, play); + if (Object_IsLoaded(&play->objectCtx, enExItem->objectIdx)) { + enExItem->actor.draw = (ActorFunc)EnExItem_DrawRandomizedItem; + Actor_SetScale(&enExItem->actor, enExItem->scale); + + // for now we're just using this to not have items float + // below the bowling counter, but it would be nice to use + // this to not draw gigantic skull tokens etc. + switch (enExItem->type) { + case EXITEM_BOMB_BAG_COUNTER: { + enExItem->actor.shape.yOffset = -10.0f; + break; + } + } + } +} + void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) { f32 mtxScale = CVarGetFloat("gTimeSavers.SkipGetItemAnimationScale", 10.0f); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); @@ -932,6 +957,13 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } + case GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING: { + EnBomBowlPit* enBomBowlPit = static_cast(optionalArg); + if (enBomBowlPit->prizeIndex == EXITEM_BOMB_BAG_BOWLING || enBomBowlPit->prizeIndex == EXITEM_HEART_PIECE_BOWLING) { + *should = false; + } + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: @@ -1216,6 +1248,33 @@ void RandomizerOnActorInitHandler(void* actorRef) { objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(gPlayState->sceneNum, (s16)actor->world.pos.x, respawnData); objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait; } + + if (actor->id == ACTOR_EN_EX_ITEM) { + EnExItem* enExItem = static_cast(actorRef); + + RandomizerCheck rc = RC_UNKNOWN_CHECK; + switch (enExItem->type) { + case EXITEM_BOMB_BAG_COUNTER: + case EXITEM_BOMB_BAG_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE; + break; + case EXITEM_HEART_PIECE_COUNTER: + case EXITEM_HEART_PIECE_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE; + break; + case EXITEM_BOMBCHUS_COUNTER: + case EXITEM_BOMBCHUS_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS; + break; + case EXITEM_BULLET_BAG: + rc = RC_LW_TARGET_IN_WOODS; + break; + } + if (rc != RC_UNKNOWN_CHECK) { + enExItem->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + enExItem->actionFunc = (EnExItemActionFunc)EnExItem_WaitForObjectRandomized; + } + } } void RandomizerRegisterHooks() { diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 232b096f9..7e5cc3ef1 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -2,6 +2,7 @@ #include "vt.h" #include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.h" #include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -177,56 +178,30 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { Player_SetCsActionWithHaltedActors(play, NULL, 7); this->getItemId = sGetItemIds[this->prizeIndex]; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; if ((this->getItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) { this->getItemId = GI_BOMB_BAG_40; } - if (IS_RANDO) { - switch (this->prizeIndex) { - case EXITEM_BOMB_BAG_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); - this->getItemId = this->getItemEntry.getItemId; - break; - case EXITEM_HEART_PIECE_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); - this->getItemId = this->getItemEntry.getItemId; - break; - case EXITEM_BOMBCHUS_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); - this->getItemId = this->getItemEntry.getItemId; - break; - } - } - player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; this->actor.parent = NULL; - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->actionFunc = EnBomBowlPit_WaitTillPrizeGiven; } void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { this->actionFunc = EnBomBowlPit_Reset; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } void EnBomBowlPit_Reset(EnBomBowlPit* this, PlayState* play) { - if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && - Message_ShouldAdvance(play)) || - (IS_RANDO && this->getItemId == GI_ICE_TRAP)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // "Normal termination"/"completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (this->getItemId == GI_HEART_PIECE) { diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h index 97ff39ac8..48cfbd5c2 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h @@ -33,7 +33,6 @@ typedef struct EnBomBowlPit { /* 0x01D4 */ Vec3f unk_1D4; // camera eye (maxsteps) /* 0x01E0 */ EnExItem* exItem; /* 0x01E4 */ char unk_1E4[0x3520]; - /* */ GetItemEntry getItemEntry; } EnBomBowlPit; // size = 0x3704 #endif diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 3860336ef..28e89036d 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -138,12 +138,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { onCounter = true; case EXITEM_BOMB_BAG_BOWLING: this->unk_17C = func_8002EBCC; - if (IS_RANDO) { - this->giDrawId = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20).gid; - } else { - this->giDrawId = GID_BOMB_BAG_30; - } + this->giDrawId = GID_BOMB_BAG_30; this->timer = 65; this->prizeRotateTimer = 35; this->scale = 0.5f; @@ -151,7 +146,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { this->actionFunc = EnExItem_BowlPrize; } else { this->actionFunc = EnExItem_SetupBowlCounter; - this->actor.shape.yOffset = IS_RANDO ? -10.0f : -18.0f; + this->actor.shape.yOffset = -18.0f; } break; case EXITEM_HEART_PIECE_COUNTER: @@ -173,11 +168,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { onCounter = true; case EXITEM_BOMBCHUS_BOWLING: this->unk_17C = func_8002EBCC; - if (IS_RANDO) { - this->giDrawId = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10).gid; - } else { - this->giDrawId = GID_BOMBCHU; - } + this->giDrawId = GID_BOMBCHU; this->timer = 65; this->prizeRotateTimer = 35; this->scale = 0.5f; @@ -496,43 +487,12 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { } if (this) {} func_8002ED80(&this->actor, play, 0); - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - switch (this->type) { - case EXITEM_BOMB_BAG_BOWLING: - case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); - break; - case EXITEM_BOMBCHUS_BOWLING: - case EXITEM_BOMBCHUS_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); - break; - case EXITEM_BULLET_BAG: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - break; - } - - if (randoGetItem.getItemId != GI_NONE) { - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - GetItem_Draw(play, this->giDrawId); } void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); - - if (IS_RANDO) { - GetItemEntry randoGetItem = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - } else { - GetItem_Draw(play, GID_HEART_PIECE); - } + GetItem_Draw(play, GID_HEART_PIECE); } void EnExItem_DrawMagic(EnExItem* this, PlayState* play, s16 magicIndex) { diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h index d014e19be..090d7028c 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h @@ -27,6 +27,9 @@ typedef struct EnExItem { /* 0x0170 */ Vec3f initPos; // unused /* 0x017C */ EnExItemLightFunc unk_17C; /* 0x0180 */ EnExItemLightFunc unk_180; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } EnExItem; // size = 0x0184 typedef enum { @@ -52,6 +55,8 @@ typedef enum { /* 19 */ EXITEM_BULLET_BAG } EnExItemType; +void EnExItem_WaitForObject(EnExItem* enExItem, PlayState* play); + #define EXITEM_COUNTER 5 #define EXITEM_CHEST 10 #define EXITEM_MAGIC 16 From 54b15051371561df1344257b6be9c946afbcfbda Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 17 Apr 2024 21:17:00 -0400 Subject: [PATCH 148/300] vb gerudo (#111) * vb gerudo * clean up --- .../game-interactor/GameInteractor.h | 6 ++++ .../randomizer/3drando/spoiler_log.hpp | 1 - .../Enhancements/randomizer/hook_handlers.cpp | 32 +++++++++++++++++++ soh/soh/Enhancements/randomizer/location.h | 4 --- .../Enhancements/randomizer/location_list.cpp | 2 +- .../randomizer/randomizer_check_tracker.cpp | 2 -- .../Enhancements/randomizer/randomizer_inf.h | 2 ++ .../ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c | 17 ++-------- soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 23 +++---------- soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h | 2 ++ soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c | 31 +++++------------- soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c | 15 +++------ 12 files changed, 63 insertions(+), 74 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 89d2467c6..a3d7e9045 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -212,6 +212,10 @@ typedef enum { // Opt: *BgDyYoseizo // Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, + // Vanilla condition: see CheckCarpentersFreed in z_en_ge1 and z_en_ge2 + GI_VB_GERUDOS_BE_FRIENDLY, + // Vanilla condition: switch + GI_VB_GTG_GATE_BE_OPEN, /*** Play Cutscenes ***/ @@ -308,6 +312,8 @@ typedef enum { // Opt: *EnBomBowlPit GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, + GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, + GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, GI_VB_GIVE_ITEM_LIGHT_ARROW, diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp index 7e20b176a..89b9d36bc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp @@ -20,7 +20,6 @@ typedef enum { SPOILER_CHK_INF_TABLE, SPOILER_CHK_FISH, SPOILER_CHK_MINIGAME, - SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, SPOILER_CHK_POE_POINTS, SPOILER_CHK_SHOP_ITEM, SPOILER_CHK_MASTER_SWORD, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 07f2ecb54..f8e1c5020 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -31,6 +31,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Hy/z_en_hy.h" #include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h" #include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" +#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -135,6 +136,13 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { } void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) { + if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && + sceneNum == SCENE_GERUDOS_FORTRESS && + flagType == FLAG_SCENE_SWITCH && + flag == 0x3A) { + Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); + } + RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); if (rc == RC_UNKNOWN_CHECK) return; @@ -964,6 +972,21 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } + case GI_VB_GERUDOS_BE_FRIENDLY: { + *should = CHECK_QUEST_ITEM(QUEST_GERUDO_CARD); + break; + } + case GI_VB_GTG_GATE_BE_OPEN: { + if (Flags_GetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)) { + *should = true; + } + break; + } + case GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD: { + Flags_SetRandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS); + *should = false; + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: @@ -1275,6 +1298,15 @@ void RandomizerOnActorInitHandler(void* actorRef) { enExItem->actionFunc = (EnExItemActionFunc)EnExItem_WaitForObjectRandomized; } } + + if (actor->id == ACTOR_EN_GE1) { + EnGe1* enGe1 = static_cast(actorRef); + auto ge1Type = enGe1->actor.params & 0xFF; + if (ge1Type == GE1_TYPE_TRAINING_GROUNDS_GUARD && + Flags_GetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)) { + enGe1->actionFunc = (EnGe1ActionFunc)EnGe1_SetNormalText; + } + } } void RandomizerRegisterHooks() { diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index a962e4501..1731067cf 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -59,10 +59,6 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit); } - static auto GerudoToken() { - return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00); - } - static auto BigPoePoints() { return SpoilerCollectionCheck(SPOILER_CHK_POE_POINTS, 0x00, 0x00); } diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 39f9b7477..1dfa2f5e4 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -659,7 +659,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_190), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // RandoTodo: Do we replace these with the RC_HIDEOUT keys or keep these? - locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 7c5b63c37..fda9d717d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -426,8 +426,6 @@ bool HasItemBeenCollected(RandomizerCheck rc) { return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)); case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF: return gSaveContext.eventChkInf[flag / 16] & (0x01 << flag % 16); - case SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD: - return CHECK_FLAG_ALL(gSaveContext.eventChkInf[0x09], 0x0F); case SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA: return GET_GS_FLAGS(scene) & flag; case SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE: diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 14749e574..465f5316c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -293,6 +293,8 @@ typedef enum { RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4, RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5, + RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS, + RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN, // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c index 519767534..6d65c049f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c @@ -6,6 +6,7 @@ #include "z_bg_spot12_saku.h" #include "objects/object_spot12_obj/object_spot12_obj.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -58,15 +59,9 @@ void func_808B3420(BgSpot12Saku* this, PlayState* play, CollisionHeader* collisi void BgSpot12Saku_Init(Actor* thisx, PlayState* play) { BgSpot12Saku* this = (BgSpot12Saku*)thisx; - // If ER is on, force the gate to always use its permanent flag - // (which it only uses in Child Gerudo Fortress in the vanilla game) - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) { - thisx->params = 0x0002; - } - func_808B3420(this, play, &gGerudoFortressGTGShutterCol, DPM_UNK); Actor_ProcessInitChain(&this->dyna.actor, sInitChain); - if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B3714(this); } else { func_808B3550(this); @@ -87,7 +82,7 @@ void func_808B3550(BgSpot12Saku* this) { } void func_808B357C(BgSpot12Saku* this, PlayState* play) { - if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B35E4(this); this->timer = 20; OnePointCutscene_Init(play, 4170, -99, &this->dyna.actor, MAIN_CAM); @@ -131,12 +126,6 @@ void func_808B37AC(BgSpot12Saku* this, PlayState* play) { void BgSpot12Saku_Update(Actor* thisx, PlayState* play) { BgSpot12Saku* this = (BgSpot12Saku*)thisx; - // If ER is on, when the guard opens the GtG gate its permanent flag will be set. - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && - Flags_GetSwitch(play, 0x3A)) { - Flags_SetSwitch(play, 0x2); - } - if (this->timer > 0) { this->timer--; } diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 995e3d5fd..2086e528f 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -134,7 +134,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_GATE_OPERATOR: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_CheckGate_GateOp; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -144,7 +144,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_NORMAL: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_SetNormalText; } else { this->actionFunc = EnGe1_WatchForAndSensePlayer; @@ -174,7 +174,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { if (gSaveContext.eventInf[0] & 0x100) { this->actionFunc = EnGe1_TalkAfterGame_Archery; - } else if (EnGe1_CheckCarpentersFreed()) { + } else if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_Wait_Archery; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -184,13 +184,8 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_TRAINING_GROUNDS_GUARD: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { - // If the gtg gate is permanently open, don't let the gaurd charge to open it again - if (IS_RANDO && gSaveContext.sceneFlags[93].swch & 0x00000004) { - this->actionFunc = EnGe1_SetNormalText; - } else { - this->actionFunc = EnGe1_CheckForCard_GTGGuard; - } + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + this->actionFunc = EnGe1_CheckForCard_GTGGuard; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; } @@ -236,14 +231,6 @@ void EnGe1_SetAnimationIdle(EnGe1* this) { } s32 EnGe1_CheckCarpentersFreed(void) { - if (IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_GERUDO_CARD)) { - return 1; - } else { - return 0; - } - } - u16 carpenterFlags = gSaveContext.eventChkInf[9]; if (!((carpenterFlags & 1) && (carpenterFlags & 2) && (carpenterFlags & 4) && (carpenterFlags & 8))) { return 0; diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h index 1851fdbce..afb57fb41 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h @@ -57,4 +57,6 @@ typedef struct EnGe1 { /* 0x02B8 */ EnGe1AnimFunc animFunc; } EnGe1; // size = 0x02BC +void EnGe1_SetNormalText(EnGe1* enGe1, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 5602dd883..0b5b9c09e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_gla/object_gla.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -139,14 +140,14 @@ void EnGe2_Init(Actor* thisx, PlayState* play) { switch (this->actor.params & 0xFF) { case GE2_TYPE_PATROLLING: EnGe2_ChangeAction(this, GE2_ACTION_WALK); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } break; case GE2_TYPE_STATIONARY: EnGe2_ChangeAction(this, GE2_ACTION_STAND); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -227,14 +228,6 @@ s32 Ge2_DetectPlayerInUpdate(PlayState* play, EnGe2* this, Vec3f* pos, s16 yRot, } s32 EnGe2_CheckCarpentersFreed(void) { - if (IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_GERUDO_CARD)) { - return 1; - } else { - return 0; - } - } - if (CHECK_FLAG_ALL(gSaveContext.eventChkInf[EVENTCHKINF_CARPENTERS_FREE_INDEX] & (EVENTCHKINF_CARPENTERS_FREE_MASK_ALL | 0xF0), EVENTCHKINF_CARPENTERS_FREE_MASK_ALL)) { @@ -467,16 +460,11 @@ void EnGe2_WaitLookAtPlayer(EnGe2* this, PlayState* play) { } void EnGe2_WaitTillCardGiven(EnGe2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe2_SetActionAfterTalk; } else { - if (!IS_RANDO) { - Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -485,11 +473,8 @@ void EnGe2_GiveCard(EnGe2* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe2_WaitTillCardGiven; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } } @@ -620,7 +605,7 @@ void EnGe2_Update(Actor* thisx, PlayState* play) { } EnGe2_MoveAndBlink(this, play); - if (EnGe2_CheckCarpentersFreed() && !(this->stateFlags & GE2_STATE_KO)) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL) && !(this->stateFlags & GE2_STATE_KO)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -645,7 +630,7 @@ void EnGe2_UpdateStunned(Actor* thisx, PlayState* play2) { } CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; this->actor.colorFilterTimer = 0; diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index aaa198060..1265ba51e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -6,6 +6,7 @@ #include "z_en_ge3.h" #include "objects/object_geldb/object_geldb.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -140,16 +141,11 @@ void EnGe3_WaitLookAtPlayer(EnGe3* this, PlayState* play) { } void EnGe3_WaitTillCardGiven(EnGe3* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe3_Wait; } else { - if (!IS_RANDO) { - Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -158,11 +154,8 @@ void EnGe3_GiveCard(EnGe3* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe3_WaitTillCardGiven; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); } } } From edf6d9334a7a6f275e18c8d448a1ae64e4faa8e6 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 18 Apr 2024 20:42:25 -0500 Subject: [PATCH 149/300] Migrate ganon trials --- .../Enhancements/debugger/debugSaveEditor.h | 7 -- .../Enhancements/randomizer/hook_handlers.cpp | 15 ++++ .../Enhancements/randomizer/randomizer.cpp | 28 +++---- soh/soh/Enhancements/randomizer/randomizer.h | 2 +- .../Enhancements/randomizer/randomizer_inf.h | 7 -- soh/soh/Enhancements/randomizer/savefile.cpp | 13 ++- soh/soh/OTRGlobals.cpp | 4 +- soh/soh/OTRGlobals.h | 2 +- .../actors/ovl_Demo_Kekkai/z_demo_kekkai.c | 80 +++---------------- .../ovl_Object_Kankyo/z_object_kankyo.c | 21 ----- 10 files changed, 48 insertions(+), 131 deletions(-) diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index ff9f9bf8f..047df95f8 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -358,13 +358,6 @@ const std::vector flagTables = { { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" }, - { RAND_INF_TRIALS_DONE_LIGHT_TRIAL, "TRIALS_DONE_LIGHT_TRIAL" }, - { RAND_INF_TRIALS_DONE_FOREST_TRIAL, "TRIALS_DONE_FOREST_TRIAL" }, - { RAND_INF_TRIALS_DONE_FIRE_TRIAL, "TRIALS_DONE_FIRE_TRIAL" }, - { RAND_INF_TRIALS_DONE_WATER_TRIAL, "TRIALS_DONE_WATER_TRIAL" }, - { RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, "TRIALS_DONE_SPIRIT_TRIAL" }, - { RAND_INF_TRIALS_DONE_SHADOW_TRIAL, "TRIALS_DONE_SHADOW_TRIAL" }, - { RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, "COWS_MILKED_KF_LINKS_HOUSE_COW" }, { RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, "COWS_MILKED_HF_COW_GROTTO_COW" }, { RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, "COWS_MILKED_LLR_STABLES_LEFT_COW" }, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f8e1c5020..f47d1adad 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -107,6 +107,15 @@ bool MeetsLACSRequirements() { return false; } +bool CompletedAllTrials() { + return Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_WATER_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_LIGHT_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FIRE_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SHADOW_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SPIRIT_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL); +} + // Todo Move this to randomizer context, clear it out on save load etc static std::queue randomizerQueuedChecks; static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; @@ -1307,6 +1316,12 @@ void RandomizerOnActorInitHandler(void* actorRef) { enGe1->actionFunc = (EnGe1ActionFunc)EnGe1_SetNormalText; } } + + if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER + if (CompletedAllTrials()) { + Actor_Kill(actor); + } + } } void RandomizerRegisterHooks() { diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index eb34721b5..74409c4c7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -164,21 +164,6 @@ Randomizer::Randomizer() { Randomizer::~Randomizer() { } -std::unordered_map spoilerFileTrialToEnum = { - { "the Forest Trial", RAND_INF_TRIALS_DONE_FOREST_TRIAL }, - { "l'épreuve de la Forêt", RAND_INF_TRIALS_DONE_FOREST_TRIAL }, - { "the Fire Trial", RAND_INF_TRIALS_DONE_FIRE_TRIAL }, - { "l'épreuve du Feu", RAND_INF_TRIALS_DONE_FIRE_TRIAL }, - { "the Water Trial", RAND_INF_TRIALS_DONE_WATER_TRIAL }, - { "l'épreuve de l'Eau", RAND_INF_TRIALS_DONE_WATER_TRIAL }, - { "the Spirit Trial", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL }, - { "l'épreuve de l'Esprit", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL }, - { "the Shadow Trial", RAND_INF_TRIALS_DONE_SHADOW_TRIAL }, - { "l'épreuve de l'Ombre", RAND_INF_TRIALS_DONE_SHADOW_TRIAL }, - { "the Light Trial", RAND_INF_TRIALS_DONE_LIGHT_TRIAL }, - { "l'épreuve de la Lumière", RAND_INF_TRIALS_DONE_LIGHT_TRIAL } -}; - std::unordered_map spoilerFileDungeonToScene = { { "Deku Tree", SCENE_DEKU_TREE }, { "Dodongo's Cavern", SCENE_DODONGOS_CAVERN }, @@ -576,8 +561,17 @@ void Randomizer::LoadMerchantMessages() { "\x08{{item}} {{price}} Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w\x09\x02")); } -bool Randomizer::IsTrialRequired(RandomizerInf trial) { - return Rando::Context::GetInstance()->GetTrial(trial - RAND_INF_TRIALS_DONE_LIGHT_TRIAL)->IsRequired(); +std::map trialFlagToTrialKey = { + { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, Rando::TrialKey::LIGHT_TRIAL, }, + { EVENTCHKINF_COMPLETED_FOREST_TRIAL, Rando::TrialKey::FOREST_TRIAL, }, + { EVENTCHKINF_COMPLETED_FIRE_TRIAL, Rando::TrialKey::FIRE_TRIAL, }, + { EVENTCHKINF_COMPLETED_WATER_TRIAL, Rando::TrialKey::WATER_TRIAL, }, + { EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, Rando::TrialKey::SPIRIT_TRIAL, }, + { EVENTCHKINF_COMPLETED_SHADOW_TRIAL, Rando::TrialKey::SHADOW_TRIAL, } +}; + +bool Randomizer::IsTrialRequired(s32 trialFlag) { + return Rando::Context::GetInstance()->GetTrial(trialFlagToTrialKey[trialFlag])->IsRequired(); } GetItemEntry Randomizer::GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 4d5a2ff30..de7f216e6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -46,7 +46,7 @@ class Randomizer { bool SpoilerFileExists(const char* spoilerFileName); void LoadMerchantMessages(); void LoadHintMessages(); - bool IsTrialRequired(RandomizerInf trial); + bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc); diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 465f5316c..8bd2cc7c1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -10,13 +10,6 @@ typedef enum { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, - RAND_INF_TRIALS_DONE_LIGHT_TRIAL, - RAND_INF_TRIALS_DONE_FOREST_TRIAL, - RAND_INF_TRIALS_DONE_FIRE_TRIAL, - RAND_INF_TRIALS_DONE_WATER_TRIAL, - RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, - RAND_INF_TRIALS_DONE_SHADOW_TRIAL, - RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 95840b15c..a43e9e2be 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -351,10 +351,15 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.entranceIndex = -1; } - // If any trials aren't required, set them as completed - for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) { - if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired((RandomizerInf)i)) { - Flags_SetRandomizerInf((RandomizerInf)i); + for (auto trialFlag : { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, + EVENTCHKINF_COMPLETED_FOREST_TRIAL, + EVENTCHKINF_COMPLETED_FIRE_TRIAL, + EVENTCHKINF_COMPLETED_WATER_TRIAL, + EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, + EVENTCHKINF_COMPLETED_SHADOW_TRIAL } + ) { + if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag)) { + Flags_SetEventChkInf(trialFlag); } } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a01d96fed..c7e363ad7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2359,8 +2359,8 @@ extern "C" void Randomizer_LoadMerchantMessages() { OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(); } -extern "C" bool Randomizer_IsTrialRequired(RandomizerInf trial) { - return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trial); +extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { + return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } extern "C" u32 SpoilerFileExists(const char* spoilerFileName) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index c90f07316..00b643bcb 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -159,7 +159,7 @@ FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); void Randomizer_LoadHintMessages(); void Randomizer_LoadMerchantMessages(); -bool Randomizer_IsTrialRequired(RandomizerInf trial); +bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); diff --git a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c index 01a2ab047..09a45856b 100644 --- a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c +++ b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c @@ -64,66 +64,23 @@ static u8 sEnergyColors[] = { /* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0, }; -// Translates from the barrier's actor params to their corresponding randInf flags. -RandomizerInf trialParamToRandInf(u16 params) { - switch (params) { - case KEKKAI_LIGHT: - return RAND_INF_TRIALS_DONE_LIGHT_TRIAL; - case KEKKAI_FOREST: - return RAND_INF_TRIALS_DONE_FOREST_TRIAL; - case KEKKAI_FIRE: - return RAND_INF_TRIALS_DONE_FIRE_TRIAL; - case KEKKAI_WATER: - return RAND_INF_TRIALS_DONE_WATER_TRIAL; - case KEKKAI_SPIRIT: - return RAND_INF_TRIALS_DONE_SPIRIT_TRIAL; - case KEKKAI_SHADOW: - return RAND_INF_TRIALS_DONE_SHADOW_TRIAL; - } -} - s32 DemoKekkai_CheckEventFlag(s32 params) { - static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB }; + static s32 eventFlags[] = { + EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER, + EVENTCHKINF_COMPLETED_WATER_TRIAL, + EVENTCHKINF_COMPLETED_LIGHT_TRIAL, + EVENTCHKINF_COMPLETED_FIRE_TRIAL, + EVENTCHKINF_COMPLETED_SHADOW_TRIAL, + EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, + EVENTCHKINF_COMPLETED_FOREST_TRIAL, + }; if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) { return true; } - if (IS_RANDO && params > KEKKAI_TOWER) { - return Flags_GetRandomizerInf(trialParamToRandInf(params)); - } return Flags_GetEventChkInf(eventFlags[params]); } -u32 TrialsDoneCount() { - u8 trialCount = 0; - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) { - trialCount++; - } - - return trialCount; -} - void DemoKekkai_Init(Actor* thisx, PlayState* play) { s32 pad; DemoKekkai* this = (DemoKekkai*)thisx; @@ -147,13 +104,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) { this->collider2.dim.radius = thisx->scale.x * 6100.0f; this->collider2.dim.height = thisx->scale.y * 5000.0f; this->collider2.dim.yShift = 300; - - if (IS_RANDO) { - if (TrialsDoneCount() == NUM_TRIALS) { - Actor_Kill(thisx); - return; - } - } break; case KEKKAI_WATER: case KEKKAI_LIGHT: @@ -161,10 +111,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) { case KEKKAI_SHADOW: case KEKKAI_SPIRIT: case KEKKAI_FOREST: - if (IS_RANDO && Flags_GetRandomizerInf(trialParamToRandInf(thisx->params))) { - Actor_Kill(thisx); - return; - } this->energyAlpha = 1.0f; this->orbScale = 1.0f; Actor_SetScale(thisx, 0.1f); @@ -265,18 +211,10 @@ void DemoKekkai_Update(Actor* thisx, PlayState* play2) { } void DemoKekkai_TrialBarrierDispel(Actor* thisx, PlayState* play) { - static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB }; static u16 csFrames[] = { 0, 280, 280, 280, 280, 280, 280 }; s32 pad; DemoKekkai* this = (DemoKekkai*)thisx; - if (IS_RANDO) { - Flags_SetRandomizerInf(trialParamToRandInf(thisx->params)); - // May or may not be needed. Not sure if needed for anything - // that randoInf isn't already covering. Leaving it for safety. - Flags_SetEventChkInf(eventFlags[thisx->params]); - } - if (play->csCtx.frames == csFrames[this->actor.params]) { func_800F3F3C(0xA); } diff --git a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c index eefaf9c0c..2600acd6b 100644 --- a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c +++ b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c @@ -136,27 +136,6 @@ void ObjectKankyo_Init(Actor* thisx, PlayState* play) { this->effects[5].size = 0.0f; } - if (IS_RANDO) { - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) { - this->effects[0].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) { - this->effects[1].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) { - this->effects[2].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) { - this->effects[3].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) { - this->effects[4].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) { - this->effects[5].size = 0.0f; - } - } - if (gSaveContext.cutsceneTrigger != 0) { if (gSaveContext.entranceIndex == ENTR_INSIDE_GANONS_CASTLE_2) { this->effects[0].size = 0.1f; From 16836172105ee90802f2e81ddcedf67193b2a20d Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 18 Apr 2024 21:13:40 -0500 Subject: [PATCH 150/300] Migrate rainbow bridge --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 57 +++++++++++++ .../Enhancements/timesaver_hook_handlers.cpp | 7 ++ .../ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c | 82 +++++-------------- 4 files changed, 85 insertions(+), 63 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index a3d7e9045..8dc20e215 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -113,6 +113,7 @@ typedef enum { GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, // Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, + GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, /* Vanilla Condition: ``` LINK_IS_ADULT && @@ -255,6 +256,7 @@ typedef enum { GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, // Opt: *EnOkarinaTag GI_VB_PLAY_DOOR_OF_TIME_CS, + GI_VB_PLAY_RAINBOW_BRIDGE_CS, /*** Give Items ***/ diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f47d1adad..a2fe8697e 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -116,6 +116,59 @@ bool CompletedAllTrials() { Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL); } +bool MeetsRainbowBridgeRequirements() { + switch (RAND_GET_OPTION(RSK_RAINBOW_BRIDGE)) { + case RO_BRIDGE_VANILLA: { + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { + return true; + } + break; + } + case RO_BRIDGE_STONES: { + if ((CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_STONE_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_MEDALLIONS: { + if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEON_REWARDS: { + if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_REWARD_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEONS: { + if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_TOKENS: { + if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_TOKEN_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_GREG: { + if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { + return true; + } + break; + } + case RO_BRIDGE_ALWAYS_OPEN: { + return true; + } + } + + return false; +} + // Todo Move this to randomizer context, clear it out on save load etc static std::queue randomizerQueuedChecks; static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; @@ -996,6 +1049,10 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } + case GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE: { + *should = MeetsRainbowBridgeRequirements(); + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 18249e0bf..886b3ddea 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -666,6 +666,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } + case GI_VB_PLAY_RAINBOW_BRIDGE_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = false; + func_800F595C(NA_BGM_BRIDGE_TO_GANONS); + } + break; + } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index b592edcd5..543770505 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -7,6 +7,7 @@ #include "z_bg_gjyo_bridge.h" #include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "scenes/dungeons/ganon_tou/ganon_tou_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -50,8 +51,7 @@ void BgGjyoBridge_Init(Actor* thisx, PlayState* play) { this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT) || (IS_RANDO && bridge == RO_BRIDGE_ALWAYS_OPEN)) { + if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT)) { this->actionFunc = func_808787A4; } else { this->dyna.actor.draw = NULL; @@ -70,8 +70,10 @@ void func_808787A4(BgGjyoBridge* this, PlayState* play) { } void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); - gSaveContext.cutsceneTrigger = 1; + if (GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); + gSaveContext.cutsceneTrigger = 1; + } this->actionFunc = BgGjyoBridge_SpawnBridge; } @@ -84,70 +86,24 @@ u8 CheckPlayerPosition(Player* player, PlayState* play) { void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (!IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, play)) { - LaunchBridgeCutscene(this, play); - } - } else { - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); - int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); - int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); - int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); - int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); + u8 vanillaBridgeCondition = + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && + CheckPlayerPosition(player, play); - switch (bridge) { - case RO_BRIDGE_VANILLA: - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_STONES: - if ((CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeStoneCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_MEDALLIONS: - if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= bridgeMedallionCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEON_REWARDS: - if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeRewardCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEONS: - if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= bridgeDungeonCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_TOKENS: - if (gSaveContext.inventory.gsTokens >= bridgeTokenCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_GREG: - if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - } + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) { + LaunchBridgeCutscene(this, play); } } void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) { - if (IS_RANDO || (play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[2] != NULL) && - (play->csCtx.npcActions[2]->action == 2)) { + u8 vanillaBridgeCondition = + (play->csCtx.state != CS_STATE_IDLE) && + (play->csCtx.npcActions[2] != NULL) && + (play->csCtx.npcActions[2]->action == 2); + + if (!GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) { this->dyna.actor.draw = BgGjyoBridge_Draw; func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId); Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT); From abdbe25c8a92c0c38b28ef2445ef197c45883187 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 18 Apr 2024 21:36:10 -0500 Subject: [PATCH 151/300] Migrate purple poe faster fight --- .../Enhancements/timesaver_hook_handlers.cpp | 30 +++++++++++++++++++ .../ovl_En_Po_Sisters/z_en_po_sisters.c | 11 ------- .../ovl_En_Po_Sisters/z_en_po_sisters.h | 2 ++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 886b3ddea..6c6930ec4 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -23,6 +23,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" +#include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -686,6 +687,8 @@ static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02KillHook = 0; +static uint32_t enPoSistersUpdateHook = 0; +static uint32_t enPoSistersKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); @@ -816,6 +819,33 @@ void TimeSaverOnActorInitHandler(void* actorRef) { EnDntDemo* enDntDemo = static_cast(actorRef); enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; } + + // Forest Temple entrance cutscene + if (actor->id == ACTOR_EN_PO_SISTERS && actor->params == 4124) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + Flags_SetSwitch(gPlayState, 0x1B); + Actor_Kill(actor); + } + } + + // Forest Temple purple poe fight speedup + if (actor->id == ACTOR_EN_PO_SISTERS && actor->params == 28) { + enPoSistersUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_PO_SISTERS && innerActor->params == 28 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnPoSisters* enPoSisters = static_cast(innerActorRef); + if (enPoSisters->actionFunc == func_80ADB338) { + enPoSisters->unk_19C = 0; + } + } + }); + enPoSistersKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enPoSistersUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enPoSistersKillHook); + enPoSistersUpdateHook = 0; + enPoSistersKillHook = 0; + }); + } } void TimeSaverOnSceneInitHandler(int16_t sceneNum) { diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index ea324c5a5..280640efd 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -183,12 +183,6 @@ void EnPoSisters_Init(Actor* thisx, PlayState* play) { this->epoch++; - // Skip Poe Intro Cutscene - if (IS_RANDO && thisx->params == 4124 && !Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { - Flags_SetSwitch(play, 0x1B); - Actor_Kill(thisx); - } - Actor_ProcessInitChain(&this->actor, sInitChain); ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 50.0f); SkelAnime_Init(play, &this->skelAnime, &gPoeSistersSkel, &gPoeSistersSwayAnim, this->jointTable, @@ -862,11 +856,6 @@ void func_80ADB338(EnPoSisters* this, PlayState* play) { if (Actor_WorldDistXZToPoint(&player->actor, &this->actor.home.pos) < 600.0f) { if (this->unk_19C != 0) { this->unk_19C--; - - // Force Meg to respawn instantly after getting hit - if (IS_RANDO) { - this->unk_19C = 0; - } } } else { this->unk_19C = 100; diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h index 2bd780983..5f42856a4 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h @@ -32,4 +32,6 @@ typedef struct EnPoSisters { u32 epoch; } EnPoSisters; // size = 0x0338 +void func_80ADB338(EnPoSisters* enPoSisters, PlayState* play); + #endif From 6c384c3cb69ba3a651148f2739fd2754542c0926 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 18 Apr 2024 21:52:38 -0500 Subject: [PATCH 152/300] Finish glitch aiding cutscenes toggle --- soh/soh/Enhancements/randomizer/savefile.cpp | 4 ---- soh/soh/Enhancements/timesaver_hook_handlers.cpp | 8 ++++++++ soh/soh/SohMenuBar.cpp | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index a43e9e2be..ffab46e49 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -302,10 +302,6 @@ extern "C" void Randomizer_InitSaveFile() { // gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora // gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora - if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { - Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple - } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A); Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 6c6930ec4..5d77515da 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -846,6 +846,14 @@ void TimeSaverOnActorInitHandler(void* actorRef) { enPoSistersKillHook = 0; }); } + + // Fire Temple Darunia cutscene + if (actor->id == ACTOR_EN_DU && gPlayState->sceneNum == SCENE_FIRE_TEMPLE) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); + Actor_Kill(actor); + } + } } void TimeSaverOnSceneInitHandler(int16_t sceneNum) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index b32a39627..95f59a14f 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -581,7 +581,7 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) && CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) && CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && @@ -593,7 +593,7 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) || CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) || CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || @@ -637,7 +637,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); From 0b8cc71d0d59883304aee2d3287f19bc81da03b7 Mon Sep 17 00:00:00 2001 From: Archez Date: Fri, 19 Apr 2024 09:41:04 -0400 Subject: [PATCH 153/300] fix actor init flow with object loading (#3987) --- soh/src/code/z_actor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index c1dc66e23..0accb49d0 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1220,7 +1220,7 @@ void Actor_Init(Actor* actor, PlayState* play) { actor->floorBgId = BGCHECK_SCENE; ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { - //Actor_SetObjectDependency(play, actor); + Actor_SetObjectDependency(play, actor); actor->init(actor, play); actor->init = NULL; @@ -2548,6 +2548,13 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { Actor_SetObjectDependency(play, actor); actor->init(actor, play); actor->init = NULL; + + GameInteractor_ExecuteOnActorInit(actor); + + // For enemy health bar we need to know the max health during init + if (actor->category == ACTORCAT_ENEMY) { + actor->maximumHealth = actor->colChkInfo.health; + } } actor = actor->next; } else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { From 19be6e9b9973f3a94cd0f582d7de42d9e6e6b0c6 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 19 Apr 2024 06:41:46 -0700 Subject: [PATCH 154/300] Trackers MQ Cleanup (#4009) * Clean up grayed out items in file select. Tie personal notes saving to `OnExitGame()` to account for save scum resets. Hide text input box (but not window) for personal notes when a save isn't loaded to prevent saving over a save's notes while in file select. * Allow check tracker window to be visible and show the "Waiting for file load..." text in file select (ease of positioning). * Fix key label text placement. * Persist `areasSpoiled`, change trigger to `OnSceneTransition`. Add `IsAreaSpoiled` for tie-in to Item Tracker. Add `SetAreaSpoiled` to unify bitmagic. * Add proper spoiling evaluation based on specific entrance IDs, or first check collection. Add light yellow color for vanilla dungeon abbreviations to match the purple for MQ. * Initialize `areasSpoiled` to 0, so 0 gets saved on file create. * All new conditional statements around `GameInteractor::IsSaveLoaded()` were inverted. Fixed that. * Change some c-style casts to `static_cast`. * Few more cleanups, plus clarifying comment. --- .../randomizer/randomizer_check_tracker.cpp | 70 +++++++++++++------ .../randomizer/randomizer_check_tracker.h | 2 + .../randomizer/randomizer_item_tracker.cpp | 53 ++++++++------ 3 files changed, 81 insertions(+), 44 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index b9ca97a9b..7c1f99a15 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -103,6 +103,23 @@ std::map DungeonRCAreasBySceneID = { {SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE}, }; +// Dungeon entrances with obvious visual differences between MQ and vanilla qualifying as spoiling on sight +std::vector spoilingEntrances = { + 0x0000, // ENTR_DEKU_TREE_0 + 0x0467, // ENTR_DODONGOS_CAVERN_1 + 0x0028, // ENTR_JABU_JABU_0 + 0x0407, // ENTR_JABU_JABU_1 + 0x0169, // ENTR_FOREST_TEMPLE_0 + 0x0165, // ENTR_FIRE_TEMPLE_0 + 0x0175, // ENTR_FIRE_TEMPLE_1 + 0x0423, // ENTR_WATER_TEMPLE_1 + 0x0082, // ENTR_SPIRIT_TEMPLE_0 + 0x02B2, // ENTR_SHADOW_TEMPLE_1 + 0x0088, // ENTR_ICE_CAVERN_0 + 0x0008, // ENTR_GERUDO_TRAINING_GROUNDS_0 + 0x0467 // ENTR_INSIDE_GANONS_CASTLE_0 +}; + std::map> checksByArea; bool areasFullyChecked[RCAREA_INVALID]; u32 areasSpoiled = 0; @@ -263,6 +280,10 @@ void SetCheckCollected(RandomizerCheck rc) { } SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); + if (!IsAreaSpoiled(rcObj.rcArea)) { + SetAreaSpoiled(rcObj.rcArea); + } + doAreaScroll = true; UpdateOrdering(rcObj.rcArea); UpdateInventoryChecks(); @@ -467,9 +488,14 @@ void CheckTrackerLoadGame(int32_t fileNum) { areaChecksGotten[realRcObj.rcArea]++; } } - - if (areaChecksGotten[realRcObj.rcArea] != 0 || RandomizerCheckObjects::AreaIsOverworld(realRcObj.rcArea)) { - areasSpoiled |= (1 << realRcObj.rcArea); + } + for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) { + if (!IsAreaSpoiled(static_cast(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast(i)) || !IS_RANDO || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION || + (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) { + SetAreaSpoiled(static_cast(i)); } } if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) { @@ -539,6 +565,9 @@ void CheckTrackerTransition(uint32_t sceneNum) { SetShopSeen(sceneNum, false); break; } + if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) { + SetAreaSpoiled(currentArea); + } } void CheckTrackerFrame() { @@ -756,6 +785,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { void InitTrackerData(bool isDebug) { TrySetAreas(); + areasSpoiled = 0; for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) { if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) { DefaultCheckData(rc); @@ -783,6 +813,7 @@ void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) { SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem); }); }); + SaveManager::Instance->SaveData("areasSpoiled", areasSpoiled); } void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) { @@ -798,6 +829,7 @@ void LoadFile() { SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem); }); }); + SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled); } void Teardown() { @@ -809,6 +841,15 @@ void Teardown() { lastLocationChecked = RC_UNKNOWN_CHECK; } +bool IsAreaSpoiled(RandomizerCheckArea rcArea) { + return areasSpoiled & (1 << rcArea); +} + +void SetAreaSpoiled(RandomizerCheckArea rcArea) { + areasSpoiled |= (1 << rcArea); + SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); +} + void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast(check))->second.rcArea; if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) || @@ -827,10 +868,6 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { void CheckTrackerWindow::DrawElement() { ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver); - if (!initialized && (gPlayState == nullptr || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2)) { - return; - } - if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { return; @@ -851,7 +888,7 @@ void CheckTrackerWindow::DrawElement() { BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar); - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded() || !initialized) { ImGui::Text("Waiting for file load..."); //TODO Language EndFloatWindows(); return; @@ -862,8 +899,6 @@ void CheckTrackerWindow::DrawElement() { sceneId = (SceneID)gPlayState->sceneNum; } - areasSpoiled |= (1 << currentArea); - //Quick Options #ifdef __WIIU__ float headerHeight = 40.0f; @@ -925,7 +960,6 @@ void CheckTrackerWindow::DrawElement() { Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string stemp; - s32 areaMask = 1; for (auto& [rcArea, objs] : checksByArea) { RandomizerCheckArea thisArea = currentArea; @@ -978,11 +1012,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f)); - isThisAreaSpoiled = areasSpoiled & areaMask || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0) || !IS_RANDO || - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE || - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION || - (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12); + isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0); if (isThisAreaSpoiled) { if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { @@ -1015,7 +1045,6 @@ void CheckTrackerWindow::DrawElement() { ImGui::TreePop(); } } - areaMask <<= 1; } ImGui::EndTable(); //Checks Lead-out @@ -1219,10 +1248,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { } void UpdateInventoryChecks() { - //For all the areas with compasses, if you have one, spoil the area + //For all the areas with maps, if you have one, spoil the area for (auto [scene, area] : DungeonRCAreasBySceneID) { if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) { - areasSpoiled |= (1 << area); + SetAreaSpoiled(area); } } } @@ -1232,9 +1261,6 @@ void UpdateAreaFullyChecked(RandomizerCheckArea area) { void UpdateAreas(RandomizerCheckArea area) { areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size(); - if (areaChecksGotten[area] != 0 || RandomizerCheckObjects::AreaIsOverworld(area)) { - areasSpoiled |= (1 << area); - } } void UpdateAllOrdering() { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index a8928cca3..85a4f1d9e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -50,6 +50,8 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); +bool IsAreaSpoiled(RandomizerCheckArea rcArea); +void SetAreaSpoiled(RandomizerCheckArea rcArea); } // namespace CheckTracker diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f63b37b62..44671b5c6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "randomizer_check_tracker.h" #include extern "C" { @@ -290,15 +291,15 @@ bool IsValidSaveFile() { } bool HasSong(ItemTrackerItem item) { - return (1 << item.id) & gSaveContext.inventory.questItems; + return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false; } bool HasQuestItem(ItemTrackerItem item) { - return (item.data & gSaveContext.inventory.questItems) != 0; + return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false; } bool HasEquipment(ItemTrackerItem item) { - return (item.data & gSaveContext.inventory.equipment) != 0; + return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false; } ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { @@ -406,8 +407,12 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { #define IM_COL_GREEN IM_COL32(0, 255, 0, 255) #define IM_COL_GRAY IM_COL32(155, 155, 155, 255) #define IM_COL_PURPLE IM_COL32(180, 90, 200, 255) +#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255) -void DrawItemCount(ItemTrackerItem item) { +void DrawItemCount(ItemTrackerItem item, bool hideMax) { + if (!GameInteractor::IsSaveLoaded()) { + return; + } int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ImVec2 p = ImGui::GetCursorScreenPos(); @@ -416,7 +421,7 @@ void DrawItemCount(ItemTrackerItem item) { if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { std::string currentString = ""; - std::string maxString = std::to_string(currentAndMax.maxCapacity); + std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity); ImU32 currentColor = IM_COL_WHITE; ImU32 maxColor = IM_COL_GREEN; // "Collected / Max", "Current / Collected / Max", "Current / Max" @@ -548,7 +553,7 @@ void DrawQuest(ItemTrackerItem item) { ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); if (item.id == QUEST_SKULL_TOKEN) { - DrawItemCount(item); + DrawItemCount(item, false); } ImGui::EndGroup(); @@ -558,7 +563,7 @@ void DrawQuest(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) { - uint32_t actualItemId = INV_CONTENT(item.id); + uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); bool hasItem = actualItemId != ITEM_NONE; std::string itemName = ""; @@ -617,7 +622,7 @@ void DrawItem(ItemTrackerItem item) { ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - DrawItemCount(item); + DrawItemCount(item, false); ImGui::EndGroup(); if (itemName == "") { @@ -628,7 +633,7 @@ void DrawItem(ItemTrackerItem item) { } void DrawBottle(ItemTrackerItem item) { - uint32_t actualItemId = gSaveContext.inventory.items[SLOT(item.id) + item.data]; + uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false; bool hasItem = actualItemId != ITEM_NONE; if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) { @@ -647,8 +652,8 @@ void DrawDungeonItem(ItemTrackerItem item) { ImU32 dungeonColor = IM_COL_WHITE; uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[item.data]) != 0; - bool hasSmallKey = (gSaveContext.inventory.dungeonKeys[item.data]) >= 0; + bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false; + bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; ImGui::BeginGroup(); if (itemId == ITEM_KEY_SMALL) { ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), @@ -659,16 +664,18 @@ void DrawDungeonItem(ItemTrackerItem item) { ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } - if (ResourceMgr_IsSceneMasterQuest(item.data) && (CHECK_DUNGEON_ITEM(DUNGEON_MAP, item.data) || item.data == SCENE_GERUDO_TRAINING_GROUND || item.data == SCENE_INSIDE_GANONS_CASTLE)) { - dungeonColor = IM_COL_PURPLE; + if (CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast(item.data))) && GameInteractor::IsSaveLoaded()) { + dungeonColor = (ResourceMgr_IsSceneMasterQuest(item.data) ? IM_COL_PURPLE : IM_COL_LIGHT_YELLOW); } if (itemId == ITEM_KEY_SMALL) { - DrawItemCount(item); + DrawItemCount(item, !CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast(item.data)))); ImVec2 p = ImGui::GetCursorScreenPos(); + // offset puts the text at the correct level. for some reason, if the save is loaded, the margin is 3 pixels higher only for small keys, so we use 16 then. Otherwise, 13 is where everything else is + int offset = GameInteractor::IsSaveLoaded() ? 16 : 13; std::string dungeonName = itemTrackerDungeonShortNames[item.data]; - ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16))); + ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + offset))); ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor); ImGui::Text("%s", dungeonName.c_str()); ImGui::PopStyleColor(); @@ -725,13 +732,15 @@ void DrawNotes(bool resizeable = false) { } }; ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200); - if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) { - notesNeedSave = true; - notesIdleFrames = 0; - } - if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { - notesNeedSave = false; - SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); + if (GameInteractor::IsSaveLoaded()) { + if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) { + notesNeedSave = true; + notesIdleFrames = 0; + } + if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { + notesNeedSave = false; + SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); + } } ImGui::EndGroup(); } From 32288be744a959f5cb12d7787e3aaff7ea948238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaro=20Mart=C3=ADnez?= Date: Fri, 19 Apr 2024 08:41:55 -0500 Subject: [PATCH 155/300] Save in-game language setting (#4026) --- soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c index 5c5cb3e6d..1682de47d 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c @@ -692,6 +692,7 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { sLastOptionButtonIndex = -1; osSyncPrintf("SAVE"); Save_SaveGlobal(); + CVarSave(); osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); From bfe13906e9c1e21e06f7afa1313b0ee4de825d32 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:42:12 +0100 Subject: [PATCH 156/300] Make equip swap work on pause any cursor (#4052) --- soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 665c95b81..4e82cb8e7 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -237,8 +237,8 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { s16 oldCursorPoint; s16 moveCursorResult; bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); // only allow mask select when: // the shop is open: From 02f7310c167b27befe05e4d41e7070eb8a959570 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 19 Apr 2024 06:42:26 -0700 Subject: [PATCH 157/300] Add keyring to check for placing Gerudo Fortess Keys in Any Dungeon or Overworld. (#4055) --- soh/soh/Enhancements/randomizer/3drando/fill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index f9d3a9592..fa20a083d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -846,10 +846,10 @@ static void RandomizeDungeonItems() { } if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) { - auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; }); + auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; }); AddElementsToPool(anyDungeonItems, gerudoKeys); } else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) { - auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; }); + auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; }); AddElementsToPool(overworldItems, gerudoKeys); } From 32bf8cc53ce6a90ade7b6ce47cc3d7db3b46a6b9 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 09:42:41 -0400 Subject: [PATCH 158/300] fix wii u ci (#4056) --- .github/workflows/generate-builds.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 38cc4c9ad..c4523b917 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -235,7 +235,6 @@ jobs: - name: Install dependencies if: ${{ !vars.LINUX_RUNNER }} run: | - sudo apt-get update sudo apt-get install -y ninja-build - uses: actions/checkout@v3 with: From 2216b681111b951744980f219529bb6d9bb69db0 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:06:52 -0400 Subject: [PATCH 159/300] fix: add include missed in merge conflict resolution --- soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 7d58d9476..08efbf99b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "randomizer_check_tracker.h" #include extern "C" { From 43e8eec6bd417ce119f505419670a4476b520035 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 19 Apr 2024 12:28:38 -0500 Subject: [PATCH 160/300] Replace some printfs with spdlogs (#4058) --- .../Enhancements/randomizer/3drando/fill.cpp | 24 ++++++++----------- .../Enhancements/randomizer/3drando/hints.cpp | 4 ++-- .../randomizer/3drando/item_pool.cpp | 2 +- .../Enhancements/randomizer/3drando/menu.cpp | 6 ++--- .../randomizer/3drando/playthrough.cpp | 16 ++++++------- .../randomizer/3drando/spoiler_log.cpp | 2 +- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 9394ef22d..f87871944 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -635,7 +635,7 @@ static void AssumedFill(const std::vector& items, const std::vect bool setLocationsAsHintable = false) { auto ctx = Rando::Context::GetInstance(); if (items.size() > allowedLocations.size()) { - printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); + SPDLOG_ERROR("ERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); SPDLOG_DEBUG("Items:\n"); // NOLINTNEXTLINE(clang-diagnostic-unused-variable) for (const RandomizerGet item : items) { @@ -984,9 +984,9 @@ void VanillaFill() { } //If necessary, handle ER stuff if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { - printf("\x1b[7;10HShuffling Entrances..."); + SPDLOG_INFO("Shuffling Entrances..."); ctx->GetEntranceShuffler()->ShuffleAllEntrances(); - printf("\x1b[7;32HDone"); + SPDLOG_INFO("Shuffling Entrances Done"); } // Populate the playthrough for entrances so they are placed in the spoiler log GeneratePlaythrough(); @@ -997,11 +997,6 @@ void VanillaFill() { } void ClearProgress() { - printf("\x1b[7;32H "); // Done - printf("\x1b[8;10H "); // Placing Items...Done - printf("\x1b[9;10H "); // Calculating Playthrough...Done - printf("\x1b[10;10H "); // Creating Hints...Done - printf("\x1b[11;10H "); // Writing Spoiler Log...Done } int Fill() { @@ -1024,13 +1019,13 @@ int Fill() { //can validate the world using deku/hylian shields AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4 if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { - printf("\x1b[7;10HShuffling Entrances"); + SPDLOG_INFO("Shuffling Entrances..."); if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { retries++; ClearProgress(); continue; } - printf("\x1b[7;32HDone"); + SPDLOG_INFO("Shuffling Entrances Done"); } SetAreas(); //erase temporary shop items @@ -1142,19 +1137,20 @@ int Fill() { GeneratePlaythrough(); //Successful placement, produced beatable result if(ctx->playthroughBeatable && !placementFailure) { - printf("Done"); - printf("\x1b[9;10HCalculating Playthrough..."); + SPDLOG_INFO("Calculating Playthrough..."); PareDownPlaythrough(); CalculateWotH(); CalculateBarren(); - printf("Done"); + SPDLOG_INFO("Calculating Playthrough Done"); ctx->CreateItemOverrides(); ctx->GetEntranceShuffler()->CreateEntranceOverrides(); + SPDLOG_INFO("Creating Other Hint Texts..."); //funny ganon line Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); SetGanonText(ganonText); + SPDLOG_INFO("Creating Other Hint Texts Done"); CreateAllHints(); CreateWarpSongTexts(); @@ -1162,7 +1158,7 @@ int Fill() { } //Unsuccessful placement if(retries < 4) { - SPDLOG_DEBUG("\nGOT STUCK. RETRYING...\n"); + SPDLOG_DEBUG("Failed to generate a beatable seed. Retrying..."); Areas::ResetAllLocations(); logic->Reset(); ClearProgress(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index c55655de0..ce29c95d0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -1114,8 +1114,8 @@ void CreateAllHints(){ CreateFrogsHint(); } if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) { - printf("\x1b[10;10HCreating Hints..."); + SPDLOG_INFO("Creating Hints..."); CreateStoneHints(); - printf("Done"); + SPDLOG_INFO("Creating Hints Done"); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index a54f522aa..f1119123c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -468,7 +468,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) { return; } } - printf("ERROR: No Junk to Place!!!\n"); + SPDLOG_ERROR("ERROR: No Junk to Place!!!"); } static void PlaceVanillaDekuScrubItems() { diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 752984032..76cf6f1bc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -50,12 +50,10 @@ bool GenerateRandomizer(std::set excludedLocations, std::setGetSettings()->GetSeed(), excludedLocations, enabledTricks); 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_DEBUG("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");//RANDOTODO print seed for reproduction purposes + SPDLOG_ERROR("Failed to generate after 5 tries."); return false; } else { - printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret); + SPDLOG_ERROR("Error {} with fill.", ret); return false; } } diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 7aef15aa5..d29b6e8a6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -69,18 +69,18 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, if (true) { //TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files, etc.) // write logs - printf("\x1b[11;10HWriting Spoiler Log..."); + SPDLOG_INFO("Writing Spoiler Log..."); if (SpoilerLog_Write()) { - printf("Done"); + SPDLOG_INFO("Writing Spoiler Log Done"); } else { - printf("Failed"); + SPDLOG_ERROR("Writing Spoiler Log Failed"); } #ifdef ENABLE_DEBUG - printf("\x1b[11;10HWriting Placement Log..."); + SPDLOG_INFO("Writing Placement Log..."); if (PlacementLog_Write()) { - printf("Done\n"); + SPDLOG_INFO("Writing Placement Log Done"); } else { - printf("Failed\n"); + SPDLOG_ERROR("Writing Placement Log Failed"); } #endif } @@ -93,7 +93,7 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, // used for generating a lot of seeds at once int Playthrough_Repeat(std::set excludedLocations, std::set enabledTricks, int count /*= 1*/) { - printf("\x1b[0;0HGENERATING %d SEEDS", count); + SPDLOG_INFO("GENERATING {} SEEDS", count); auto ctx = Rando::Context::GetInstance(); uint32_t repeatedSeed = 0; for (int i = 0; i < count; i++) { @@ -103,7 +103,7 @@ int Playthrough_Repeat(std::set excludedLocations, std::setGetSettings()->GetSeed(), excludedLocations, enabledTricks); - printf("\x1b[15;15HSeeds Generated: %d\n", i + 1); + SPDLOG_INFO("Seeds Generated: {}", i + 1); } return 1; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index ba63e4641..3fdf56b60 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -260,7 +260,7 @@ void WriteIngameSpoilerLog() { } } if (spoilerOutOfSpace || playthroughItemNotFound) { - printf("Error! "); + SPDLOG_ERROR("In-game spoiler log is out of space, playthrough data will not be written"); } } } From ed0ef62c0cc86cc82a3aac4eb0521094411107ba Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:15:15 -0400 Subject: [PATCH 161/300] fix: add location access for treasure chest game items vb treasure chest game added new RCs for the treasure chest game (now there are RCs for each of the 5 keys and each of the 5 non key chests), but the location area table only had the keys, this adds the items --- .../3drando/location_access/locacc_castle_town.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index f48a2bb53..ac4a8ef50 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -235,10 +235,15 @@ void AreaTable_Init_CastleTown() { LocationAccess(RC_GREG_HINT, {[]{return true;}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), From d3beac7337f1c62a666dfdde852795e25ec99f08 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 16:29:37 -0400 Subject: [PATCH 162/300] fix: gift from sages location access --- .../randomizer/3drando/location_access/locacc_castle_town.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index ac4a8ef50..9527f5243 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -65,6 +65,7 @@ void AreaTable_Init_CastleTown() { }, { //Locations LocationAccess(RC_TOT_MASTER_SWORD, {[]{return logic->IsAdult;}}), + LocationAccess(RC_GIFT_FROM_SAGES, {[]{return logic->IsAdult;}}), LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return logic->ForestMedallion && logic->IsAdult;}}), }, { //Exits From 3b0548f585b4a4894157c3f7d63bdef786023a0e Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 18:05:38 -0400 Subject: [PATCH 163/300] vb tower escape --- .../Enhancements/randomizer/option_descriptions.cpp | 2 -- soh/soh/Enhancements/randomizer/randomizerTypes.h | 1 - soh/soh/Enhancements/randomizer/settings.cpp | 4 ---- soh/soh/Enhancements/timesaver_hook_handlers.cpp | 11 ++++++++++- soh/soh/SohMenuBar.cpp | 10 ++++++++-- soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c | 8 +------- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index e50846005..82228dbed 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -438,8 +438,6 @@ void Settings::CreateOptionDescriptions() { "Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; - mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE] = - "The tower escape sequence between Ganondorf and Ganon will be skipped."; mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] = "Once the happy mask shop is opened, all masks will be available to be borrowed."; mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] = diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index f1d368763..074849b00 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -3598,7 +3598,6 @@ typedef enum { RSK_CUCCO_COUNT, RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, - RSK_SKIP_TOWER_ESCAPE, RSK_COMPLETE_MASK_QUEST, RSK_SKIP_SCARECROWS_SONG, RSK_ENABLE_GLITCH_CUTSCENES, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index ac947d4da..5edc219dd 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -147,7 +147,6 @@ void Settings::CreateOptions() { mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", "gRandomizeShuffleKeyRingsGanonsCastle"); mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildStealth", mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildZelda", mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); - mOptions[RSK_SKIP_TOWER_ESCAPE] = Option::Bool("Skip Tower Escape", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipTowerEscape", mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipEponaRace", mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", "gRandomizeSkipScarecrowsSong", mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, "gRandomizeBigPoeTargetCount", mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); @@ -716,7 +715,6 @@ void Settings::CreateOptions() { &mOptions[RSK_SKIP_CHILD_STEALTH], &mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_EPONA_RACE], - &mOptions[RSK_SKIP_TOWER_ESCAPE], &mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_SKIP_SCARECROWS_SONG] }, false, WidgetContainerType::COLUMN); @@ -1200,7 +1198,6 @@ void Settings::CreateOptions() { { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, - { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }, { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, { "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG }, { "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES }, @@ -2523,7 +2520,6 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SKIP_CHILD_ZELDA: case RSK_SKIP_CHILD_STEALTH: case RSK_SKIP_EPONA_RACE: - case RSK_SKIP_TOWER_ESCAPE: if (it.value() == "Don't Skip") { mOptions[index].SetSelectedIndex(RO_GENERIC_DONT_SKIP); } else if (it.value() == "Skip") { diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 5d77515da..61a83b482 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -136,7 +136,7 @@ void TimeSaverOnGameFrameUpdateHandler() { void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { - case GI_VB_PLAY_TRANSITION_CS: + case GI_VB_PLAY_TRANSITION_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.cutsceneIndex = 0; *should = false; @@ -260,7 +260,16 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = false; } } + + if (gSaveContext.entranceIndex == ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0) { + if (CVarGetInteger("gTimeSavers.SkipTowerEscape", false) || IS_BOSS_RUSH) { + Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); + gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; + *should = false; + } + } break; + } case GI_VB_PLAY_ENTRANCE_CS: { s32* entranceFlag = static_cast(opt); if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 95f59a14f..c11b88a62 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -586,7 +586,8 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipTowerEscape", false); bool someChecked = CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) || @@ -598,7 +599,8 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) || - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipTowerEscape", false); ImGuiContext* g = ImGui::GetCurrentContext(); ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; @@ -616,6 +618,7 @@ void DrawEnhancementsMenu() { CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1); CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1); CVarSetInteger("gTimeSavers.DisableTitleCard", 1); + CVarSetInteger("gTimeSavers.SkipTowerEscape", 1); } else { CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0); CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0); @@ -628,6 +631,7 @@ void DrawEnhancementsMenu() { CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0); CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0); CVarSetInteger("gTimeSavers.DisableTitleCard", 0); + CVarSetInteger("gTimeSavers.SkipTowerEscape", 0); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -645,6 +649,8 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", "gTimeSavers.SkipTowerEscape", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::Tooltip("Skip the tower escape sequence between Ganondorf and Ganon."); UIWidgets::PaddedText("Skip Get Item Animations", true, false); UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index b1c45feed..169794568 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -1539,13 +1539,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { if (this->csTimer == 180) { play->transitionTrigger = TRANS_TRIGGER_START; - if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE) || IS_BOSS_RUSH)) { - Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); - play->nextEntranceIndex = ENTR_GANON_BOSS_0; - } - else { - play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0; - } + play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0; play->transitionType = TRANS_TYPE_FADE_WHITE_FAST; } break; From 2aa2092c2777eb07c0291ef541472546810ad2c8 Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Sat, 20 Apr 2024 10:27:13 -0400 Subject: [PATCH 164/300] filter randomizer checks in tracker (#4021) * filter randomizer checks in tracker Co-authored-by: Michael Stergianis * Adds an option to hide empty areas Co-authored-by: Jamie Klassen Signed-off-by: Michael Stergianis * Removes extra whitespace Co-authored-by: Jamie Klassen Signed-off-by: Michael Stergianis * Changes gCheckTrackerHideFilteredAreas to default to true Refactors the for loop in shouldHideArea Signed-off-by: Michael Stergianis * Addresses PR feedback * https://github.com/HarbourMasters/Shipwright/pull/4021#discussion_r1538377614 * https://github.com/HarbourMasters/Shipwright/pull/4021#discussion_r1538381310 Co-authored-by: Jamie Klassen Signed-off-by: Michael Stergianis * Updates config variable to gTrackers.CheckTracker.HideFilteredAreas Signed-off-by: Michael Stergianis * Adds check visibility guard to shouldHideArea Refactors rcObject to check in passesTextFilter Signed-off-by: Michael Stergianis --------- Signed-off-by: Michael Stergianis Co-authored-by: Michael Stergianis --- .../randomizer/randomizer_check_tracker.cpp | 83 ++++++++++++++----- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 9f6e9ff6f..917e93a11 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -33,9 +33,9 @@ using json = nlohmann::json; void to_json(json& j, const RandomizerCheckTrackerData& rctd) { j = json { - { "status", rctd.status == RCSHOW_COLLECTED ? RCSHOW_SAVED : rctd.status }, - { "skipped", rctd.skipped }, - { "price", rctd.price }, + { "status", rctd.status == RCSHOW_COLLECTED ? RCSHOW_SAVED : rctd.status }, + { "skipped", rctd.skipped }, + { "price", rctd.price }, { "hintItem", rctd.hintItem }}; } @@ -133,6 +133,8 @@ RandomizerCheckArea previousArea = RCAREA_INVALID; RandomizerCheckArea currentArea = RCAREA_INVALID; OSContPad* trackerButtonsPressed; +bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheckObject rcObject); +bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0); bool CompareChecks(RandomizerCheckObject, RandomizerCheckObject); bool CheckByArea(RandomizerCheckArea); @@ -513,7 +515,7 @@ void CheckTrackerLoadGame(int32_t fileNum) { break; } RandomizerCheckObject linksPocket = { RC_LINKS_POCKET, RCVORMQ_BOTH, RCTYPE_LINKS_POCKET, startingArea, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, false, "Link's Pocket", "Link's Pocket" }; - + checksByArea.find(startingArea)->second.push_back(linksPocket); areaChecksGotten[startingArea]++; areaCheckTotals[startingArea]++; @@ -692,7 +694,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { break; case FLAG_EVENT_CHECK_INF: if ((flag == EVENTCHKINF_CARPENTERS_FREE(0) || flag == EVENTCHKINF_CARPENTERS_FREE(1) || - flag == EVENTCHKINF_CARPENTERS_FREE(2) || flag == EVENTCHKINF_CARPENTERS_FREE(3)) + flag == EVENTCHKINF_CARPENTERS_FREE(2) || flag == EVENTCHKINF_CARPENTERS_FREE(3)) && GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) { SetCheckCollected(RC_GF_GERUDO_MEMBERSHIP_CARD); return; @@ -851,12 +853,12 @@ void SetAreaSpoiled(RandomizerCheckArea rcArea) { void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast(check))->second.rcArea; - if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) || - ((gSaveContext.checkTrackerData[check].status != RCSHOW_COLLECTED && gSaveContext.checkTrackerData[check].status != RCSHOW_SAVED) && + if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) || + ((gSaveContext.checkTrackerData[check].status != RCSHOW_COLLECTED && gSaveContext.checkTrackerData[check].status != RCSHOW_SAVED) && (data.status == RCSHOW_COLLECTED || data.status == RCSHOW_SAVED))) { areaChecksGotten[area]++; - } else if ((gSaveContext.checkTrackerData[check].skipped && !data.skipped) || - ((gSaveContext.checkTrackerData[check].status == RCSHOW_COLLECTED || gSaveContext.checkTrackerData[check].status == RCSHOW_SAVED) && + } else if ((gSaveContext.checkTrackerData[check].skipped && !data.skipped) || + ((gSaveContext.checkTrackerData[check].status == RCSHOW_COLLECTED || gSaveContext.checkTrackerData[check].status == RCSHOW_SAVED) && (data.status != RCSHOW_COLLECTED && data.status != RCSHOW_SAVED))) { areaChecksGotten[area]--; } @@ -927,6 +929,14 @@ void CheckTrackerWindow::DrawElement() { optExpandAll = false; optCollapseAll = true; } + ImGui::SameLine(); + static ImGuiTextFilter checkSearch; + if (ImGui::Button("Clear")) { + checkSearch.Clear(); + } + UIWidgets::Tooltip("Clear the search field"); + checkSearch.Draw(); + UIWidgets::PaddedSeparator(); //Checks Section Lead-in @@ -973,10 +983,9 @@ void CheckTrackerWindow::DrawElement() { previousShowHidden = showHidden; doAreaScroll = true; } - if (!showHidden && ( - hideComplete && thisAreaFullyChecked || - hideIncomplete && !thisAreaFullyChecked - )) { + if (shouldHideArea(checkSearch, checksByArea, rcArea) || + (!showHidden && ((hideComplete && thisAreaFullyChecked) || (hideIncomplete && !thisAreaFullyChecked))) + ) { doDraw = false; } else { //Get the colour for the area @@ -1035,11 +1044,14 @@ void CheckTrackerWindow::DrawElement() { ImGui::SetScrollHereY(0.0f); doAreaScroll = false; } - for (auto rco : objs) { - if (IsVisibleInCheckTracker(rco) && doDraw && isThisAreaSpoiled) { - DrawLocation(rco); + + for (auto rcObject : objs) { + if (IsVisibleInCheckTracker(rcObject) && passesTextFilter(checkSearch, rcObject) && doDraw && + isThisAreaSpoiled) { + DrawLocation(rcObject); } } + if (doDraw) { ImGui::TreePop(); } @@ -1055,6 +1067,28 @@ void CheckTrackerWindow::DrawElement() { } } +bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { + bool shouldHideFilteredAreas = CVarGetInteger("gTrackers.CheckTracker.HideFilteredAreas", 1); + if (!shouldHideFilteredAreas) { + return false; + } + + for (auto check : checksByArea[rcArea]) { + if (IsVisibleInCheckTracker(check) && passesTextFilter(checkSearch, check)) { + return false; + } + } + + return true; +} + +bool passesTextFilter(ImGuiTextFilter& checkSearch, RandomizerCheckObject check) { + return ( + checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(check.rcArea).c_str()) || + checkSearch.PassFilter(check.rcShortName.c_str()) + ); +} + // Windowing stuff void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags) { ImGuiWindowFlags windowFlags = flags; @@ -1326,7 +1360,7 @@ bool IsHeartPiece(GetItemID giid) { } void DrawLocation(RandomizerCheckObject rcObj) { - Color_RGBA8 mainColor; + Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string txt; bool showHidden = CVarGetInteger("gCheckTrackerOptionShowHidden", 0); @@ -1376,13 +1410,13 @@ void DrawLocation(RandomizerCheckObject rcObj) { CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default); extraColor = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default); } - + //Main Text txt = rcObj.rcShortName; if (lastLocationChecked == rcObj.rc) { txt = "* " + txt; } - + // Draw button - for Skipped/Seen/Scummed/Unchecked only if (status == RCSHOW_UNCHECKED || status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED || status == RCSHOW_SCUMMED || skipped) { if (UIWidgets::StateButton(std::to_string(rcObj.rc).c_str(), skipped ? ICON_FA_PLUS : ICON_FA_TIMES)) { @@ -1487,13 +1521,13 @@ void RainbowTick() { if (CVarGetInteger((cvar + "RBM").c_str(), 0) == 0) { continue; } - + Color_RGBA8 newColor; newColor.r = sin(freqHue + 0) * 127 + 128; newColor.g = sin(freqHue + (2 * M_PI / 3)) * 127 + 128; newColor.b = sin(freqHue + (4 * M_PI / 3)) * 127 + 128; newColor.a = 255; - + CVarSetColor(cvar.c_str(), newColor); } @@ -1530,7 +1564,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, main_color = CVarGetColor(cvarMainName, main_default_color); }; ImGui::PopItemWidth(); - + ImGui::TableNextColumn(); ImGui::AlignTextToFramePadding(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); @@ -1604,6 +1638,11 @@ void CheckTrackerSettingsWindow::DrawElement() { } UIWidgets::Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings."); + // Filtering settings + UIWidgets::PaddedSeparator(); + UIWidgets::EnhancementCheckbox("Filter Empty Areas", "gTrackers.CheckTracker.HideFilteredAreas", false, "", UIWidgets::CheckboxGraphics::Checkmark, true); + UIWidgets::Tooltip("If enabled, will hide area headers that have no locations matching filter"); + ImGui::TableNextColumn(); CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", "gCheckTrackerAreaMainIncompleteColor", "gCheckTrackerAreaExtraIncompleteColor", Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, "gCheckTrackerAreaIncompleteHide", ""); From b045689df15951546c1c95d893190289da2aff84 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sat, 20 Apr 2024 07:29:19 -0700 Subject: [PATCH 165/300] Step 1 of CVar macro/sectionalizing: Randomizer Settings (#3206) * Add all macros. Replace all randomizer seed setting CVars with appropriate macro. Cleaned up non-gameplay-critical things that are part of Spock Race rando presets (like RTA timing, displaying timer, displaying the glitch lineup tick, or Fast File Select). * Wrong slash... * Forgot "gManualSeedEntry". * Renamed CVars from "Mq..." to "MQ...". --- soh/soh/Enhancements/presets.h | 611 +++++++------- .../randomizer/3drando/playthrough.cpp | 3 +- .../Enhancements/randomizer/randomizer.cpp | 786 +++++++++--------- .../randomizer/randomizer_check_objects.cpp | 75 +- soh/soh/OTRGlobals.h | 16 + .../ovl_file_choose/z_file_choose.c | 4 +- 6 files changed, 743 insertions(+), 752 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 3fede1e9b..d0b7a05f4 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -7,6 +7,7 @@ #include #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/enhancementTypes.h" +#include "soh/OTRGlobals.h" enum PresetEntryType { PRESET_ENTRY_TYPE_S32, @@ -354,139 +355,138 @@ const std::vector cheatCvars = { }; const std::vector randomizerCvars = { - "gRandomize10GSHint", - "gRandomize20GSHint", - "gRandomize30GSHint", - "gRandomize40GSHint", - "gRandomize50GSHint", - "gRandomizeAllLocationsReachable", - "gRandomizeAltarHint", - "gRandomizeBigPoeTargetCount", - "gRandomizeBlueFireArrows", - "gRandomizeBombchusInLogic", - "gRandomizeBossKeysanity", - "gRandomizeBridgeRewardOptions", - "gRandomizeCompleteMaskQuest", - "gRandomizeCuccosToReturn", - "gRandomizeDampeHint", - "gRandomizeDecoupleEntrances", - "gRandomizeDoorOfTime", - "gRandomizeDungeonCount", - "gRandomizeEnableBombchuDrops", - "gRandomizeEnableGlitchCutscenes", - "gRandomizeEnabledGlitches", - "gRandomizeEnabledTricks", - "gRandomizeExcludedLocations", - "gRandomizeForest", - "gRandomizeFullWallets", - "gRandomizeGanonTrial", - "gRandomizeGanonTrialCount", - "gRandomizeGerudoFortress", - "gRandomizeGerudoKeys", - "gRandomizeGossipStoneHints", - "gRandomizeGsExpectSunsSong", - "gRandomizeHintClarity", - "gRandomizeHintDistribution", - "gRandomizeIceTraps", - "gRandomizeItemPool", - "gRandomizeKakarikoGate", - "gRandomizeKeysanity", - "gRandomizeLacsDungeonCount", - "gRandomizeLacsMedallionCount", - "gRandomizeLacsRewardCount", - "gRandomizeLacsRewardOptions", - "gRandomizeLacsStoneCount", - "gRandomizeLacsTokenCount", - "gRandomizeLAHint", - "gRandomizeLinksPocket", - "gRandomizeLogicRules", - "gRandomizeMedallionCount", - "gRandomizeMixDungeons", - "gRandomizeMixedEntrances", - "gRandomizeMixGrottos", - "gRandomizeMixInteriors", - "gRandomizeMixOverworld", - "gRandomizeMqDungeonCount", - "gRandomizeMqDungeons", - "gRandomizeRainbowBridge", - "gRandomizeRewardCount", - "gRandomizeScrubText", - "gRandomizeShopsanity", - "gRandomizeShopsanityPrices", - "gRandomizeShopsanityPricesAffordable", - "gRandomizeShuffleAdultTrade", - "gRandomizeShuffleBeans", - "gRandomizeShuffleBossEntrances", - "gRandomizeShuffleCows", - "gRandomizeShuffleDungeonReward", - "gRandomizeShuffleDungeonsEntrances", - "gRandomizeShuffleFrogSongRupees", - "gRandomizeShuffleGanonBossKey", - "gRandomizeShuffleGerudoToken", - "gRandomizeShuffleGrottosEntrances", - "gRandomizeShuffleInteriorsEntrances", - "gRandomizeShuffleKeyRings", - "gRandomizeShuffleKeyRingsBottomOfTheWell", - "gRandomizeShuffleKeyRingsFireTemple", - "gRandomizeShuffleKeyRingsForestTemple", - "gRandomizeShuffleKeyRingsGanonsCastle", - "gRandomizeShuffleKeyRingsGerudoFortress", - "gRandomizeShuffleKeyRingsGTG", - "gRandomizeShuffleKeyRingsRandomCount", - "gRandomizeShuffleKeyRingsShadowTemple", - "gRandomizeShuffleKeyRingsSpiritTemple", - "gRandomizeShuffleKeyRingsWaterTemple", - "gRandomizeShuffleKokiriSword", - "gRandomizeShuffleMerchants", - "gRandomizeShuffleOcarinas", - "gRandomizeShuffleOverworldEntrances", - "gRandomizeShuffleOverworldSpawns", - "gRandomizeShuffleOwlDrops", - "gRandomizeShuffleScrubs", - "gRandomizeShuffleSongs", - "gRandomizeShuffleTokens", - "gRandomizeShuffleWarpSongs", - "gRandomizeShuffleWeirdEgg", - "gRandomizeSkipChildStealth", - "gRandomizeSkipChildZelda", - "gRandomizeSkipEponaRace", - "gRandomizeSkipScarecrowsSong", - "gRandomizeSkipTowerEscape", - "gRandomizeStartingAge", - "gRandomizeStartingConsumables", - "gRandomizeStartingBoleroOfFire", - "gRandomizeStartingDekuShield", - "gRandomizeStartingEponasSong", - "gRandomizeStartingKokiriSword", - "gRandomizeStartingMapsCompasses", - "gRandomizeStartingMinuetOfForest", - "gRandomizeStartingNocturneOfShadow", - "gRandomizeStartingOcarina", - "gRandomizeStartingPreludeOfLight", - "gRandomizeStartingRequiemOfSpirit", - "gRandomizeStartingSariasSong", - "gRandomizeStartingSerenadeOfWater", - "gRandomizeStartingSkulltulaToken", - "gRandomizeStartingSongOfStorms", - "gRandomizeStartingSongOfTime", - "gRandomizeStartingSunsSong", - "gRandomizeStartingZeldasLullaby", - "gRandomizeStoneCount", - "gRandomizeSunlightArrows", - "gRandomizeTokenCount", - "gRandomizeWarpSongText", - "gRandomizeZorasFountain", - "gRandomizeShuffle100GSReward", - "gRandomizeGregHint", - "gRandoManualSeedEntry", - "gRandomizerSettingsEnabled", - "gRandomizeTriforceHuntTotalPieces", - "gRandomizeTriforceHuntRequiredPieces", - "gRandomizeTriforceHunt", - "gRandomizeShuffleMasterSword", - "gRandomizeSariaHint", + RANDOMIZER_SEED_CVAR("10GSHint"), + RANDOMIZER_SEED_CVAR("20GSHint"), + RANDOMIZER_SEED_CVAR("30GSHint"), + RANDOMIZER_SEED_CVAR("40GSHint"), + RANDOMIZER_SEED_CVAR("50GSHint"), + RANDOMIZER_SEED_CVAR("AllLocationsReachable"), + RANDOMIZER_SEED_CVAR("AltarHint"), + RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), + RANDOMIZER_SEED_CVAR("BlueFireArrows"), + RANDOMIZER_SEED_CVAR("BombchusInLogic"), + RANDOMIZER_SEED_CVAR("BossKeysanity"), + RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), + RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), + RANDOMIZER_SEED_CVAR("CuccosToReturn"), + RANDOMIZER_SEED_CVAR("DampeHint"), + RANDOMIZER_SEED_CVAR("DecoupleEntrances"), + RANDOMIZER_SEED_CVAR("DoorOfTime"), + RANDOMIZER_SEED_CVAR("DungeonCount"), + RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), + RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), + RANDOMIZER_SEED_CVAR("EnabledGlitches"), + RANDOMIZER_SEED_CVAR("EnabledTricks"), + RANDOMIZER_SEED_CVAR("ExcludedLocations"), + RANDOMIZER_SEED_CVAR("Forest"), + RANDOMIZER_SEED_CVAR("FullWallets"), + RANDOMIZER_SEED_CVAR("GanonTrial"), + RANDOMIZER_SEED_CVAR("GanonTrialCount"), + RANDOMIZER_SEED_CVAR("GerudoFortress"), + RANDOMIZER_SEED_CVAR("GerudoKeys"), + RANDOMIZER_SEED_CVAR("GossipStoneHints"), + RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), + RANDOMIZER_SEED_CVAR("HintClarity"), + RANDOMIZER_SEED_CVAR("HintDistribution"), + RANDOMIZER_SEED_CVAR("IceTraps"), + RANDOMIZER_SEED_CVAR("ItemPool"), + RANDOMIZER_SEED_CVAR("KakarikoGate"), + RANDOMIZER_SEED_CVAR("Keysanity"), + RANDOMIZER_SEED_CVAR("LacsDungeonCount"), + RANDOMIZER_SEED_CVAR("LacsMedallionCount"), + RANDOMIZER_SEED_CVAR("LacsRewardCount"), + RANDOMIZER_SEED_CVAR("LacsRewardOptions"), + RANDOMIZER_SEED_CVAR("LacsStoneCount"), + RANDOMIZER_SEED_CVAR("LacsTokenCount"), + RANDOMIZER_SEED_CVAR("LAHint"), + RANDOMIZER_SEED_CVAR("LinksPocket"), + RANDOMIZER_SEED_CVAR("LogicRules"), + RANDOMIZER_SEED_CVAR("MedallionCount"), + RANDOMIZER_SEED_CVAR("MixDungeons"), + RANDOMIZER_SEED_CVAR("MixedEntrances"), + RANDOMIZER_SEED_CVAR("MixGrottos"), + RANDOMIZER_SEED_CVAR("MixInteriors"), + RANDOMIZER_SEED_CVAR("MixOverworld"), + RANDOMIZER_SEED_CVAR("MQDungeonCount"), + RANDOMIZER_SEED_CVAR("MQDungeons"), + RANDOMIZER_SEED_CVAR("RainbowBridge"), + RANDOMIZER_SEED_CVAR("RewardCount"), + RANDOMIZER_SEED_CVAR("ScrubText"), + RANDOMIZER_SEED_CVAR("Shopsanity"), + RANDOMIZER_SEED_CVAR("ShopsanityPrices"), + RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), + RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), + RANDOMIZER_SEED_CVAR("ShuffleBeans"), + RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), + RANDOMIZER_SEED_CVAR("ShuffleCows"), + RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), + RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), + RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), + RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), + RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), + RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), + RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple"), + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple"), + RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), + RANDOMIZER_SEED_CVAR("ShuffleMerchants"), + RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), + RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), + RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), + RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), + RANDOMIZER_SEED_CVAR("ShuffleScrubs"), + RANDOMIZER_SEED_CVAR("ShuffleSongs"), + RANDOMIZER_SEED_CVAR("ShuffleTokens"), + RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), + RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), + RANDOMIZER_SEED_CVAR("SkipChildStealth"), + RANDOMIZER_SEED_CVAR("SkipChildZelda"), + RANDOMIZER_SEED_CVAR("SkipEponaRace"), + RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), + RANDOMIZER_SEED_CVAR("SkipTowerEscape"), + RANDOMIZER_SEED_CVAR("StartingAge"), + RANDOMIZER_SEED_CVAR("StartingConsumables"), + RANDOMIZER_SEED_CVAR("StartingBoleroOfFire"), + RANDOMIZER_SEED_CVAR("StartingDekuShield"), + RANDOMIZER_SEED_CVAR("StartingEponasSong"), + RANDOMIZER_SEED_CVAR("StartingKokiriSword"), + RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), + RANDOMIZER_SEED_CVAR("StartingMinuetOfForest"), + RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow"), + RANDOMIZER_SEED_CVAR("StartingOcarina"), + RANDOMIZER_SEED_CVAR("StartingPreludeOfLight"), + RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit"), + RANDOMIZER_SEED_CVAR("StartingSariasSong"), + RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater"), + RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), + RANDOMIZER_SEED_CVAR("StartingSongOfStorms"), + RANDOMIZER_SEED_CVAR("StartingSongOfTime"), + RANDOMIZER_SEED_CVAR("StartingSunsSong"), + RANDOMIZER_SEED_CVAR("StartingZeldasLullaby"), + RANDOMIZER_SEED_CVAR("StoneCount"), + RANDOMIZER_SEED_CVAR("SunlightArrows"), + RANDOMIZER_SEED_CVAR("TokenCount"), + RANDOMIZER_SEED_CVAR("WarpSongText"), + RANDOMIZER_SEED_CVAR("ZorasFountain"), + RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), + RANDOMIZER_SEED_CVAR("GregHint"), + RANDOMIZER_SEED_CVAR("ManualSeedEntry"), + RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), + RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), + RANDOMIZER_SEED_CVAR("TriforceHunt"), + RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), + RANDOMIZER_SEED_CVAR("SariaHint"), "gRandomizeRupeeNames", - "gRandomizeFrogsHint", + RANDOMIZER_SEED_CVAR("FrogsHint"), "gRandoRelevantNavi", "gRandoQuestItemFanfares", }; @@ -857,15 +857,13 @@ const std::vector randomizerPresetEntries = { }; const std::vector spockRacePresetEntries = { - PRESET_ENTRY_S32("gRandomizeLogicRules", 0), - PRESET_ENTRY_S32("gGameplayStats.RTATiming", 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LogicRules"), 0), PRESET_ENTRY_S32("gTextSpeed", 5), PRESET_ENTRY_S32("gMweepSpeed", 5), PRESET_ENTRY_S32("gClimbSpeed", 4), PRESET_ENTRY_S32("gFasterBlockPush", 5), PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), PRESET_ENTRY_S32("gNoForcedNavi", 1), - PRESET_ENTRY_S32("gDisableLOD", 1), PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), PRESET_ENTRY_S32("gFastChests", 1), PRESET_ENTRY_S32("gFastDrops", 1), @@ -878,22 +876,17 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32("gMarketSneak", 1), PRESET_ENTRY_S32("gInstantPutaway", 1), PRESET_ENTRY_S32("gFastBoomerang", 1), - PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), PRESET_ENTRY_S32("gAdultBunnyHood", 1), PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), PRESET_ENTRY_S32("gSeparateArrows", 1), PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), PRESET_ENTRY_S32("gDayGravePull", 1), - PRESET_ENTRY_S32("gDrawLineupTick", 1), PRESET_ENTRY_S32("gNewDrops", 1), PRESET_ENTRY_S32("gCreditsFix", 1), PRESET_ENTRY_S32("gSkipText", 1), PRESET_ENTRY_S32("gSkulltulaFreeze", 1), PRESET_ENTRY_S32("gPauseAnyCursor", 1), - PRESET_ENTRY_S32("gHideBuildInfo", 1), - PRESET_ENTRY_S32("gSkipLogoTitle", 1), - PRESET_ENTRY_S32("gSaveFileID", 4), PRESET_ENTRY_S32("gFastFarores", 1), PRESET_ENTRY_S32("gNoInputForCredits", 1), PRESET_ENTRY_S32("gMaskSelect", 1), @@ -906,50 +899,48 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), PRESET_ENTRY_S32("gGoronPot", 1), PRESET_ENTRY_S32("gForgeTime", 0), - PRESET_ENTRY_S32("gDisableFirstPersonChus", 1), PRESET_ENTRY_S32("gCheatEasyPauseBufferEnabled", 1), PRESET_ENTRY_S32("gDampeAllNight", 1), - PRESET_ENTRY_S32("gRandomize10GSHint", 1), - PRESET_ENTRY_S32("gRandomize20GSHint", 1), - PRESET_ENTRY_S32("gRandomize30GSHint", 1), - PRESET_ENTRY_S32("gRandomize40GSHint", 1), - PRESET_ENTRY_S32("gRandomize50GSHint", 1), - PRESET_ENTRY_S32("gRandomizeAllLocationsReachable", 0), - PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1), - PRESET_ENTRY_S32("gRandomizeBombchusInLogic", 1), - PRESET_ENTRY_S32("gRandomizeCompleteMaskQuest", 1), - PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 1), - PRESET_ENTRY_S32("gRandomizeDampeHint", 1), - PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), - PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations( + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("10GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("20GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("30GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("40GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("50GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), 0), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DampeHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), + PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations( { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), - PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), - PRESET_ENTRY_S32("gRandomizeFullWallets", 1), - PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST), - PRESET_ENTRY_S32("gRandomizeGregHint", 1), - PRESET_ENTRY_S32("gRandomizeGsExpectSunsSong", 1), - PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32("gRandomizeLacsRewardCount", 5), - PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_GREG), - PRESET_ENTRY_S32("gRandomizeScrubText", 1), - PRESET_ENTRY_S32("gRandomizeShopsanity", RO_SHOPSANITY_RANDOM), - PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_LACS_REWARDS), - PRESET_ENTRY_S32("gRandomizeShuffleKeyRings", RO_KEYRINGS_COUNT), - PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1), - PRESET_ENTRY_S32("gRandomizeShuffleOcarinas", 1), - PRESET_ENTRY_S32("gRandomizeShuffleScrubs", RO_SCRUBS_AFFORDABLE), - PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1), - PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1), - PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1), - PRESET_ENTRY_S32("gRandomizeSkipScarecrowsSong", 1), - PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1), - PRESET_ENTRY_S32("gRandomizeStartingConsumables", 1), - PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32("gRandomizeStartingOcarina", 1), - PRESET_ENTRY_S32("gRandomizeSunlightArrows", 1), - PRESET_ENTRY_S32("gRandomizerSettingsEnabled", 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("FullWallets"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GregHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 5), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_GREG), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ScrubText"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_COUNT), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_AFFORDABLE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), }; const std::vector spockRaceNoLogicPresetEntries = { @@ -964,14 +955,8 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gCustomizeFishing", 1), PRESET_ENTRY_S32("gDampeAllNight", 1), PRESET_ENTRY_S32("gDayGravePull", 1), - PRESET_ENTRY_S32("gDisableFirstPersonChus", 1), - PRESET_ENTRY_S32("gDisableLOD", 1), PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), - PRESET_ENTRY_S32("gDpadEquips", 1), PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), - PRESET_ENTRY_S32("gDpadOcarina", 1), - PRESET_ENTRY_S32("gDpadText", 1), - PRESET_ENTRY_S32("gDrawLineupTick", 1), PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), PRESET_ENTRY_S32("gFastBoomerang", 1), PRESET_ENTRY_S32("gFastChests", 1), @@ -982,8 +967,6 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), PRESET_ENTRY_S32("gFishNeverEscape", 1), PRESET_ENTRY_S32("gForgeTime", 0), - PRESET_ENTRY_S32("gGameplayStats.RTATiming", 1), - PRESET_ENTRY_S32("gGameplayStats.ShowIngameTimer", 1), PRESET_ENTRY_S32("gGoronPot", 1), PRESET_ENTRY_S32("gGuaranteeFishingBite", 1), PRESET_ENTRY_S32("gHideBuildInfo", 1), @@ -994,71 +977,61 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gMarketSneak", 1), PRESET_ENTRY_S32("gMaskSelect", 1), PRESET_ENTRY_S32("gMweepSpeed", 5), - PRESET_ENTRY_S32("gNewDrops", 1), PRESET_ENTRY_S32("gNoForcedNavi", 1), PRESET_ENTRY_S32("gNoInputForCredits", 1), - PRESET_ENTRY_S32("gOnFileSelectNameEntry", 0), - PRESET_ENTRY_S32("gOpenMenuBar", 1), PRESET_ENTRY_S32("gPauseAnyCursor", 1), - PRESET_ENTRY_S32("gRStickOcarina", 1), - PRESET_ENTRY_S32("gRandomize10GSHint", 1), - PRESET_ENTRY_S32("gRandomize20GSHint", 1), - PRESET_ENTRY_S32("gRandomize30GSHint", 1), - PRESET_ENTRY_S32("gRandomize40GSHint", 1), - PRESET_ENTRY_S32("gRandomize50GSHint", 1), - PRESET_ENTRY_S32("gRandomizeAllLocationsReachable", 0), - PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1), - PRESET_ENTRY_S32("gRandomizeBombchusInLogic", 1), - PRESET_ENTRY_S32("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeCompleteMaskQuest", 1), - PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 1), - PRESET_ENTRY_S32("gRandomizeDampeHint", 1), - PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), - PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations( + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("10GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("20GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("30GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("40GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("50GSHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), 0), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DampeHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), + PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations( { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), - PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), - PRESET_ENTRY_S32("gRandomizeFullWallets", 1), - PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST), - PRESET_ENTRY_S32("gRandomizeGerudoKeys", RO_GERUDO_KEYS_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeGregHint", 1), - PRESET_ENTRY_S32("gRandomizeGsExpectSunsSong", 0), - PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeLacsRewardCount", 5), - PRESET_ENTRY_S32("gRandomizeLogicRules", RO_LOGIC_NO_LOGIC), - PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_GREG), - PRESET_ENTRY_S32("gRandomizeScrubText", 1), - PRESET_ENTRY_S32("gRandomizeShopsanity", RO_SHOPSANITY_RANDOM), - PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 0), - PRESET_ENTRY_S32("gRandomizeShuffleBeans", 1), - PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_LACS_REWARDS), - PRESET_ENTRY_S32("gRandomizeShuffleGerudoToken", 1), - PRESET_ENTRY_S32("gRandomizeShuffleKeyRings", RO_KEYRINGS_COUNT), - PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1), - PRESET_ENTRY_S32("gRandomizeShuffleOcarinas", 1), - PRESET_ENTRY_S32("gRandomizeShuffleScrubs", 1), - PRESET_ENTRY_S32("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeShuffleTokens", RO_TOKENSANITY_ALL), - PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1), - PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1), - PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1), - PRESET_ENTRY_S32("gRandomizeSkipScarecrowsSong", 1), - PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1), - PRESET_ENTRY_S32("gRandomizeStartingConsumables", 1), - PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32("gRandomizeStartingOcarina", 1), - PRESET_ENTRY_S32("gRandomizeSunlightArrows", 1), - PRESET_ENTRY_S32("gRandomizerSettingsEnabled", 1), - PRESET_ENTRY_S32("gSaveFileID", 4), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("FullWallets"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GregHint"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 0), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 5), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_NO_LOGIC), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_GREG), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ScrubText"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 0), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_COUNT), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_ALL), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), PRESET_ENTRY_S32("gSeparateArrows", 1), - PRESET_ENTRY_S32("gSkipLogoTitle", 1), PRESET_ENTRY_S32("gSkipScarecrow", 1), - PRESET_ENTRY_S32("gSkipText", 1), PRESET_ENTRY_S32("gSkulltulaFreeze", 1), - PRESET_ENTRY_S32("gTextSpeed", 5), - PRESET_ENTRY_S32("gZFightingMode", 0), }; const std::vector s6PresetEntries = { @@ -1066,33 +1039,33 @@ const std::vector s6PresetEntries = { PRESET_ENTRY_S32("gFastChests", 1), PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1), - PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 4), - PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), - PRESET_ENTRY_CPP_STRING("gRandomizeExcludedLocations", FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })), - PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_CLOSED_DEKU), - PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32("gRandomizeGerudoFortress", RO_GF_FAST), - PRESET_ENTRY_S32("gRandomizeIceTraps", RO_ICE_TRAPS_OFF), - PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32("gRandomizeMedallionCount", 6), - PRESET_ENTRY_S32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE), - PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_MEDALLIONS), - PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1), - PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON), - PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_STARTWITH), - PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1), - PRESET_ENTRY_S32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_ON), - PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1), - PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1), - PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1), - PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1), - PRESET_ENTRY_S32("gRandomizeStartingAge", RO_AGE_RANDOM), - PRESET_ENTRY_S32("gRandomizeStartingConsumables", 1), - PRESET_ENTRY_S32("gRandomizeStartingDekuShield", 1), - PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32("gRandomizeStartingOcarina", 1), - PRESET_ENTRY_S32("gRandomizeZorasFountain", 0), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 4), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED_DEKU), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_OFF), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MedallionCount"), 6), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_MEDALLIONS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_STARTWITH), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_ON), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingDekuShield"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ZorasFountain"), 0), }; const std::vector hellModePresetEntries = { @@ -1100,51 +1073,51 @@ const std::vector hellModePresetEntries = { PRESET_ENTRY_S32("gFastChests", 1), PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32("gRandomizeBigPoeTargetCount", 1), - PRESET_ENTRY_S32("gRandomizeBlueFireArrows", 1), - PRESET_ENTRY_S32("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeCompleteMaskQuest", 1), - PRESET_ENTRY_S32("gRandomizeCuccosToReturn", 1), - PRESET_ENTRY_S32("gRandomizeDoorOfTime", RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32("gRandomizeEnableBombchuDrops", 1), - PRESET_ENTRY_S32("gRandomizeEnableGlitchCutscenes", 1), - PRESET_ENTRY_S32("gRandomizeForest", RO_FOREST_OPEN), - PRESET_ENTRY_S32("gRandomizeGanonTrial", RO_GANONS_TRIALS_SET_NUMBER), - PRESET_ENTRY_S32("gRandomizeGanonTrialCount", 6), - PRESET_ENTRY_S32("gRandomizeGerudoKeys", RO_GERUDO_KEYS_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeGsExpectSunsSong", 1), - PRESET_ENTRY_S32("gRandomizeIceTraps", RO_ICE_TRAPS_ONSLAUGHT), - PRESET_ENTRY_S32("gRandomizeItemPool", RO_ITEM_POOL_MINIMAL), - PRESET_ENTRY_S32("gRandomizeKakarikoGate", RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeLinksPocket", RO_LINKS_POCKET_NOTHING), - PRESET_ENTRY_S32("gRandomizeMqDungeons", RO_MQ_DUNGEONS_RANDOM_NUMBER), - PRESET_ENTRY_S32("gRandomizeRainbowBridge", RO_BRIDGE_DUNGEON_REWARDS), - PRESET_ENTRY_S32("gRandomizeShopsanity", RO_SHOPSANITY_FOUR_ITEMS), - PRESET_ENTRY_S32("gRandomizeShopsanityPrices", RO_SHOPSANITY_PRICE_TYCOON), - PRESET_ENTRY_S32("gRandomizeShuffleAdultTrade", 1), - PRESET_ENTRY_S32("gRandomizeShuffleBeans", 1), - PRESET_ENTRY_S32("gRandomizeShuffleCows", 1), - PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeShuffleFrogSongRupees", 1), - PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_LACS_DUNGEONS), - PRESET_ENTRY_S32("gRandomizeShuffleGerudoToken", 1), - PRESET_ENTRY_S32("gRandomizeShuffleKeyRings", RO_KEYRINGS_RANDOM), - PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1), - PRESET_ENTRY_S32("gRandomizeShuffleMasterSword", 1), - PRESET_ENTRY_S32("gRandomizeShuffleOcarinas", 1), - PRESET_ENTRY_S32("gRandomizeShuffleScrubs", RO_SCRUBS_RANDOM), - PRESET_ENTRY_S32("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeShuffleTokens", RO_TOKENSANITY_ALL), - PRESET_ENTRY_S32("gRandomizeShuffleWeirdEgg", 1), - PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1), - PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1), - PRESET_ENTRY_S32("gRandomizeSkipScarecrowsSong", 1), - PRESET_ENTRY_S32("gRandomizeSkipTowerEscape", 1), - PRESET_ENTRY_S32("gRandomizeStartingAge", RO_AGE_RANDOM), - PRESET_ENTRY_S32("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32("gRandomizeSunlightArrows", 1), - PRESET_ENTRY_S32("gRandomizeZorasFountain", 2), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrialCount"), 6), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_ONSLAUGHT), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ItemPool"), RO_ITEM_POOL_MINIMAL), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LinksPocket"), RO_LINKS_POCKET_NOTHING), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_RANDOM_NUMBER), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_FOUR_ITEMS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_TYCOON), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleCows"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_DUNGEONS), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_ALL), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_RANDOM), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), + PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ZorasFountain"), 2), }; typedef struct PresetDefinition { diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 62042246c..8fb8aa9b2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -10,6 +10,7 @@ #include "spoiler_log.hpp" #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "variables.h" +#include "soh/OTRGlobals.h" namespace Playthrough { @@ -41,7 +42,7 @@ int Playthrough_Init(uint32_t seed, std::unordered_map cvarSettings; - cvarSettings[RSK_LOGIC_RULES] = CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS); - cvarSettings[RSK_ALL_LOCATIONS_REACHABLE] = CVarGetInteger("gRandomizeAllLocationsReachable", RO_GENERIC_ON); - cvarSettings[RSK_FOREST] = CVarGetInteger("gRandomizeForest", RO_FOREST_CLOSED); - cvarSettings[RSK_KAK_GATE] = CVarGetInteger("gRandomizeKakarikoGate", RO_KAK_GATE_CLOSED); - cvarSettings[RSK_DOOR_OF_TIME] = CVarGetInteger("gRandomizeDoorOfTime", RO_DOOROFTIME_CLOSED); - cvarSettings[RSK_ZORAS_FOUNTAIN] = CVarGetInteger("gRandomizeZorasFountain", 0); - cvarSettings[RSK_STARTING_AGE] = CVarGetInteger("gRandomizeStartingAge", RO_AGE_CHILD); - cvarSettings[RSK_GERUDO_FORTRESS] = CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL); - cvarSettings[RSK_RAINBOW_BRIDGE] = CVarGetInteger("gRandomizeRainbowBridge", RO_BRIDGE_VANILLA); - cvarSettings[RSK_RAINBOW_BRIDGE_STONE_COUNT] = CVarGetInteger("gRandomizeStoneCount", 3); - cvarSettings[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = CVarGetInteger("gRandomizeMedallionCount", 6); - cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = CVarGetInteger("gRandomizeRewardCount", 9); - cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = CVarGetInteger("gRandomizeDungeonCount", 8); - cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = CVarGetInteger("gRandomizeTokenCount", 100); - cvarSettings[RSK_BRIDGE_OPTIONS] = CVarGetInteger("gRandomizeBridgeRewardOptions", 0); - cvarSettings[RSK_GANONS_TRIALS] = CVarGetInteger("gRandomizeGanonTrial", RO_GANONS_TRIALS_SET_NUMBER); - cvarSettings[RSK_TRIAL_COUNT] = CVarGetInteger("gRandomizeGanonTrialCount", 6); - cvarSettings[RSK_STARTING_OCARINA] = CVarGetInteger("gRandomizeStartingOcarina", 0); - cvarSettings[RSK_SHUFFLE_OCARINA] = CVarGetInteger("gRandomizeShuffleOcarinas", 0) || - CVarGetInteger("gRandomizeStartingOcarina", 0); - cvarSettings[RSK_STARTING_KOKIRI_SWORD] = CVarGetInteger("gRandomizeStartingKokiriSword", 0); - cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVarGetInteger("gRandomizeShuffleKokiriSword", 0) || - CVarGetInteger("gRandomizeStartingKokiriSword", 0); - cvarSettings[RSK_SHUFFLE_MASTER_SWORD] = CVarGetInteger("gRandomizeShuffleMasterSword", 0); - cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVarGetInteger("gRandomizeStartingDekuShield", 0); - cvarSettings[RSK_STARTING_ZELDAS_LULLABY] = CVarGetInteger("gRandomizeStartingZeldasLullaby", 0); - cvarSettings[RSK_STARTING_EPONAS_SONG] = CVarGetInteger("gRandomizeStartingEponasSong", 0); - cvarSettings[RSK_STARTING_SARIAS_SONG] = CVarGetInteger("gRandomizeStartingSariasSong", 0); - cvarSettings[RSK_STARTING_SUNS_SONG] = CVarGetInteger("gRandomizeStartingSunsSong", 0); - cvarSettings[RSK_STARTING_SONG_OF_TIME] = CVarGetInteger("gRandomizeStartingSongOfTime", 0); - cvarSettings[RSK_STARTING_SONG_OF_STORMS] = CVarGetInteger("gRandomizeStartingSongOfStorms", 0); - cvarSettings[RSK_STARTING_MINUET_OF_FOREST] = CVarGetInteger("gRandomizeStartingMinuetOfForest", 0); - cvarSettings[RSK_STARTING_BOLERO_OF_FIRE] = CVarGetInteger("gRandomizeStartingBoleroOfFire", 0); - cvarSettings[RSK_STARTING_SERENADE_OF_WATER] = CVarGetInteger("gRandomizeStartingSerenadeOfWater", 0); - cvarSettings[RSK_STARTING_REQUIEM_OF_SPIRIT] = CVarGetInteger("gRandomizeStartingRequiemOfSpirit", 0); - cvarSettings[RSK_STARTING_NOCTURNE_OF_SHADOW] = CVarGetInteger("gRandomizeStartingNocturneOfShadow", 0); - cvarSettings[RSK_STARTING_PRELUDE_OF_LIGHT] = CVarGetInteger("gRandomizeStartingPreludeOfLight", 0); - cvarSettings[RSK_STARTING_SKULLTULA_TOKEN] = CVarGetInteger("gRandomizeStartingSkulltulaToken", 0); - cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVarGetInteger("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON); - cvarSettings[RSK_SHUFFLE_SONGS] = CVarGetInteger("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_SONG_LOCATIONS); - cvarSettings[RSK_SHUFFLE_TOKENS] = CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF); - cvarSettings[RSK_SHOPSANITY] = CVarGetInteger("gRandomizeShopsanity", RO_SHOPSANITY_OFF); - cvarSettings[RSK_SHOPSANITY_PRICES] = CVarGetInteger("gRandomizeShopsanityPrices", RO_SHOPSANITY_PRICE_BALANCED); - cvarSettings[RSK_SHOPSANITY_PRICES_AFFORDABLE] = CVarGetInteger("gRandomizeShopsanityPricesAffordable", RO_SHOPSANITY_OFF); - cvarSettings[RSK_SHUFFLE_SCRUBS] = CVarGetInteger("gRandomizeShuffleScrubs", RO_SCRUBS_OFF); - cvarSettings[RSK_SHUFFLE_COWS] = CVarGetInteger("gRandomizeShuffleCows", 0); - cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVarGetInteger("gRandomizeShuffleAdultTrade", 0); - cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger("gRandomizeShuffleBeans", 0); - cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger("gRandomizeShuffleMerchants", RO_SHUFFLE_MERCHANTS_OFF); - cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger("gRandomizeShuffle100GSReward", RO_GENERIC_OFF); - cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger("gRandomizeEnableBombchuDrops", 0); - cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger("gRandomizeBombchusInLogic", 0); - cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger("gRandomizeSkipChildZelda", 0); + cvarSettings[RSK_LOGIC_RULES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS); + cvarSettings[RSK_ALL_LOCATIONS_REACHABLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), RO_GENERIC_ON); + cvarSettings[RSK_FOREST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED); + cvarSettings[RSK_KAK_GATE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_CLOSED); + cvarSettings[RSK_DOOR_OF_TIME] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_CLOSED); + cvarSettings[RSK_ZORAS_FOUNTAIN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ZorasFountain"), 0); + cvarSettings[RSK_STARTING_AGE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_CHILD); + cvarSettings[RSK_GERUDO_FORTRESS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL); + cvarSettings[RSK_RAINBOW_BRIDGE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_VANILLA); + cvarSettings[RSK_RAINBOW_BRIDGE_STONE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StoneCount"), 3); + cvarSettings[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MedallionCount"), 6); + cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("RewardCount"), 9); + cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DungeonCount"), 8); + cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TokenCount"), 100); + cvarSettings[RSK_BRIDGE_OPTIONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), 0); + cvarSettings[RSK_GANONS_TRIALS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER); + cvarSettings[RSK_TRIAL_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrialCount"), 6); + cvarSettings[RSK_STARTING_OCARINA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); + cvarSettings[RSK_SHUFFLE_OCARINA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 0) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); + cvarSettings[RSK_STARTING_KOKIRI_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); + cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 0) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); + cvarSettings[RSK_SHUFFLE_MASTER_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), 0); + cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingDekuShield"), 0); + cvarSettings[RSK_STARTING_ZELDAS_LULLABY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingZeldasLullaby"), 0); + cvarSettings[RSK_STARTING_EPONAS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingEponasSong"), 0); + cvarSettings[RSK_STARTING_SARIAS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSariasSong"), 0); + cvarSettings[RSK_STARTING_SUNS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSunsSong"), 0); + cvarSettings[RSK_STARTING_SONG_OF_TIME] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSongOfTime"), 0); + cvarSettings[RSK_STARTING_SONG_OF_STORMS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSongOfStorms"), 0); + cvarSettings[RSK_STARTING_MINUET_OF_FOREST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMinuetOfForest"), 0); + cvarSettings[RSK_STARTING_BOLERO_OF_FIRE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingBoleroOfFire"), 0); + cvarSettings[RSK_STARTING_SERENADE_OF_WATER] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater"), 0); + cvarSettings[RSK_STARTING_REQUIEM_OF_SPIRIT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit"), 0); + cvarSettings[RSK_STARTING_NOCTURNE_OF_SHADOW] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow"), 0); + cvarSettings[RSK_STARTING_PRELUDE_OF_LIGHT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingPreludeOfLight"), 0); + cvarSettings[RSK_STARTING_SKULLTULA_TOKEN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), 0); + cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON); + cvarSettings[RSK_SHUFFLE_SONGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS); + cvarSettings[RSK_SHUFFLE_TOKENS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF); + cvarSettings[RSK_SHOPSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF); + cvarSettings[RSK_SHOPSANITY_PRICES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED); + cvarSettings[RSK_SHOPSANITY_PRICES_AFFORDABLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), RO_SHOPSANITY_OFF); + cvarSettings[RSK_SHUFFLE_SCRUBS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_OFF); + cvarSettings[RSK_SHUFFLE_COWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleCows"), 0); + cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 0); + cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 0); + cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF); + cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), RO_GENERIC_OFF); + cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 0); + cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 0); + cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); // if we skip child zelda, we start with zelda's letter, and malon starts // at the ranch, so we should *not* shuffle the weird egg - cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVarGetInteger("gRandomizeSkipChildZelda", 0) == 0) && - CVarGetInteger("gRandomizeShuffleWeirdEgg", 0)); - cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVarGetInteger("gRandomizeShuffleGerudoToken", 0); - cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVarGetInteger("gRandomizeShuffleFrogSongRupees", 0); - cvarSettings[RSK_ITEM_POOL] = CVarGetInteger("gRandomizeItemPool", RO_ITEM_POOL_BALANCED); - cvarSettings[RSK_ICE_TRAPS] = CVarGetInteger("gRandomizeIceTraps", RO_ICE_TRAPS_NORMAL); - cvarSettings[RSK_TOT_ALTAR_HINT] = CVarGetInteger("gRandomizeAltarHint", RO_GENERIC_ON); - cvarSettings[RSK_LIGHT_ARROWS_HINT] = CVarGetInteger("gRandomizeLAHint", RO_GENERIC_ON); - cvarSettings[RSK_DAMPES_DIARY_HINT] = CVarGetInteger("gRandomizeDampeHint", RO_GENERIC_OFF); - cvarSettings[RSK_GREG_HINT] = CVarGetInteger("gRandomizeGregHint", RO_GENERIC_OFF); - cvarSettings[RSK_SARIA_HINT] = CVarGetInteger("gRandomizeSariaHint", RO_GENERIC_OFF); - cvarSettings[RSK_FROGS_HINT] = CVarGetInteger("gRandomizeFrogsHint", RO_GENERIC_OFF); - cvarSettings[RSK_WARP_SONG_HINTS] = CVarGetInteger("gRandomizeWarpSongText", RO_GENERIC_OFF); - cvarSettings[RSK_SCRUB_TEXT_HINT] = CVarGetInteger("gRandomizeScrubText", RO_GENERIC_OFF); - cvarSettings[RSK_KAK_10_SKULLS_HINT] = CVarGetInteger("gRandomize10GSHint", RO_GENERIC_OFF); - cvarSettings[RSK_KAK_20_SKULLS_HINT] = CVarGetInteger("gRandomize20GSHint", RO_GENERIC_OFF); - cvarSettings[RSK_KAK_30_SKULLS_HINT] = CVarGetInteger("gRandomize30GSHint", RO_GENERIC_OFF); - cvarSettings[RSK_KAK_40_SKULLS_HINT] = CVarGetInteger("gRandomize40GSHint", RO_GENERIC_OFF); - cvarSettings[RSK_KAK_50_SKULLS_HINT] = CVarGetInteger("gRandomize50GSHint", RO_GENERIC_OFF); - cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVarGetInteger("gRandomizeGossipStoneHints", RO_GOSSIP_STONES_NEED_NOTHING); - cvarSettings[RSK_HINT_CLARITY] = CVarGetInteger("gRandomizeHintClarity", RO_HINT_CLARITY_CLEAR); - cvarSettings[RSK_HINT_DISTRIBUTION] = CVarGetInteger("gRandomizeHintDistribution", RO_HINT_DIST_BALANCED); - cvarSettings[RSK_BLUE_FIRE_ARROWS] = CVarGetInteger("gRandomizeBlueFireArrows", 0); - cvarSettings[RSK_SUNLIGHT_ARROWS] = CVarGetInteger("gRandomizeSunlightArrows", 0); - cvarSettings[RSK_KEYSANITY] = CVarGetInteger("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_GERUDO_KEYS] = CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA); - cvarSettings[RSK_KEYRINGS] = CVarGetInteger("gRandomizeShuffleKeyRings", RO_KEYRINGS_OFF); - int maxKeyringCount = (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; - cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = std::min(CVarGetInteger("gRandomizeShuffleKeyRingsRandomCount", maxKeyringCount), maxKeyringCount); + cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0) == 0) && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), 0)); + cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 0); + cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), 0); + cvarSettings[RSK_ITEM_POOL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ItemPool"), RO_ITEM_POOL_BALANCED); + cvarSettings[RSK_ICE_TRAPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_NORMAL); + cvarSettings[RSK_TOT_ALTAR_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("AltarHint"), RO_GENERIC_ON); + cvarSettings[RSK_LIGHT_ARROWS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LAHint"), RO_GENERIC_ON); + cvarSettings[RSK_DAMPES_DIARY_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DampeHint"), RO_GENERIC_OFF); + cvarSettings[RSK_GREG_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GregHint"), RO_GENERIC_OFF); + cvarSettings[RSK_SARIA_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SariaHint"), RO_GENERIC_OFF); + cvarSettings[RSK_FROGS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("FrogsHint"), RO_GENERIC_OFF); + cvarSettings[RSK_WARP_SONG_HINTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("WarpSongText"), RO_GENERIC_OFF); + cvarSettings[RSK_SCRUB_TEXT_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ScrubText"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_10_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("10GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_20_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("20GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_30_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("30GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_40_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("40GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_50_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("50GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING); + cvarSettings[RSK_HINT_CLARITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("HintClarity"), RO_HINT_CLARITY_CLEAR); + cvarSettings[RSK_HINT_DISTRIBUTION] = CVarGetInteger(RANDOMIZER_SEED_CVAR("HintDistribution"), RO_HINT_DIST_BALANCED); + cvarSettings[RSK_BLUE_FIRE_ARROWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 0); + cvarSettings[RSK_SUNLIGHT_ARROWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SunlightArrows"), 0); + cvarSettings[RSK_KEYSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_GERUDO_KEYS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA); + cvarSettings[RSK_KEYRINGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_OFF); + int maxKeyringCount = (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; + cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = std::min(CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), maxKeyringCount), maxKeyringCount); // Don't allow this to be on if Gerudo Fortress Carpenters is anything other than Normal cvarSettings[RSK_KEYRINGS_GERUDO_FORTRESS] = - (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) - ? CVarGetInteger("gRandomizeShuffleKeyRingsGerudoFortress", RO_GENERIC_OFF) : RO_GENERIC_OFF; - cvarSettings[RSK_KEYRINGS_FOREST_TEMPLE] = CVarGetInteger("gRandomizeShuffleKeyRingsForestTemple", 0); - cvarSettings[RSK_KEYRINGS_FIRE_TEMPLE] = CVarGetInteger("gRandomizeShuffleKeyRingsFireTemple", 0); - cvarSettings[RSK_KEYRINGS_WATER_TEMPLE] = CVarGetInteger("gRandomizeShuffleKeyRingsWaterTemple", 0); - cvarSettings[RSK_KEYRINGS_SPIRIT_TEMPLE] = CVarGetInteger("gRandomizeShuffleKeyRingsSpiritTemple", 0); - cvarSettings[RSK_KEYRINGS_SHADOW_TEMPLE] = CVarGetInteger("gRandomizeShuffleKeyRingsShadowTemple", 0); - cvarSettings[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = CVarGetInteger("gRandomizeShuffleKeyRingsBottomOfTheWell", 0); - cvarSettings[RSK_KEYRINGS_GTG] = CVarGetInteger("gRandomizeShuffleKeyRingsGTG", 0); - cvarSettings[RSK_KEYRINGS_GANONS_CASTLE] = CVarGetInteger("gRandomizeShuffleKeyRingsGanonsCastle", 0); - cvarSettings[RSK_BOSS_KEYSANITY] = CVarGetInteger("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_GANONS_BOSS_KEY] = CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA); - cvarSettings[RSK_LACS_STONE_COUNT] = CVarGetInteger("gRandomizeLacsStoneCount", 3); - cvarSettings[RSK_LACS_MEDALLION_COUNT] = CVarGetInteger("gRandomizeLacsMedallionCount", 6); - cvarSettings[RSK_LACS_REWARD_COUNT] = CVarGetInteger("gRandomizeLacsRewardCount", 9); - cvarSettings[RSK_LACS_DUNGEON_COUNT] = CVarGetInteger("gRandomizeLacsDungeonCount", 8); - cvarSettings[RSK_LACS_TOKEN_COUNT] = CVarGetInteger("gRandomizeLacsTokenCount", 100); - cvarSettings[RSK_LACS_OPTIONS] = CVarGetInteger("gRandomizeLacsRewardOptions", 0); - cvarSettings[RSK_STARTING_CONSUMABLES] = CVarGetInteger("gRandomizeStartingConsumables", 0); - cvarSettings[RSK_FULL_WALLETS] = CVarGetInteger("gRandomizeFullWallets", 0); + (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) + ? CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), RO_GENERIC_OFF) : RO_GENERIC_OFF; + cvarSettings[RSK_KEYRINGS_FOREST_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple"), 0); + cvarSettings[RSK_KEYRINGS_FIRE_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple"), 0); + cvarSettings[RSK_KEYRINGS_WATER_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple"), 0); + cvarSettings[RSK_KEYRINGS_SPIRIT_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple"), 0); + cvarSettings[RSK_KEYRINGS_SHADOW_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple"), 0); + cvarSettings[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell"), 0); + cvarSettings[RSK_KEYRINGS_GTG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG"), 0); + cvarSettings[RSK_KEYRINGS_GANONS_CASTLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle"), 0); + cvarSettings[RSK_BOSS_KEYSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_GANONS_BOSS_KEY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA); + cvarSettings[RSK_LACS_STONE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsStoneCount"), 3); + cvarSettings[RSK_LACS_MEDALLION_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 6); + cvarSettings[RSK_LACS_REWARD_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 9); + cvarSettings[RSK_LACS_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 8); + cvarSettings[RSK_LACS_TOKEN_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsTokenCount"), 100); + cvarSettings[RSK_LACS_OPTIONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), 0); + cvarSettings[RSK_STARTING_CONSUMABLES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingConsumables"), 0); + cvarSettings[RSK_FULL_WALLETS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("FullWallets"), 0); // RANDOTODO implement chest minigame shuffle with keysanity cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME] = false; cvarSettings[RSK_LANGUAGE] = CVarGetInteger("gLanguages", 0); - cvarSettings[RSK_CUCCO_COUNT] = CVarGetInteger("gRandomizeCuccosToReturn", 7); - cvarSettings[RSK_BIG_POE_COUNT] = CVarGetInteger("gRandomizeBigPoeTargetCount", 10); + cvarSettings[RSK_CUCCO_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 7); + cvarSettings[RSK_BIG_POE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 10); // If we skip child zelda, skip child stealth is pointless, so this needs to be reflected in the spoiler log - cvarSettings[RSK_SKIP_CHILD_STEALTH] = !CVarGetInteger("gRandomizeSkipChildZelda", 0) && CVarGetInteger("gRandomizeSkipChildStealth", 0); + cvarSettings[RSK_SKIP_CHILD_STEALTH] = !CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0) && CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 0); - cvarSettings[RSK_SKIP_EPONA_RACE] = CVarGetInteger("gRandomizeSkipEponaRace", 0); - cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVarGetInteger("gRandomizeSkipTowerEscape", 0); - cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVarGetInteger("gRandomizeCompleteMaskQuest", 0); - cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVarGetInteger("gRandomizeSkipScarecrowsSong", 0); - cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVarGetInteger("gRandomizeEnableGlitchCutscenes", 0); + cvarSettings[RSK_SKIP_EPONA_RACE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 0); + cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 0); + cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 0); + cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 0); + cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), 0); - cvarSettings[RSK_SKULLS_SUNS_SONG] = CVarGetInteger("gRandomizeGsExpectSunsSong", 0); + cvarSettings[RSK_SKULLS_SUNS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 0); // Link's Pocket has to have a dungeon reward if the other rewards are shuffled to end of dungeon. - cvarSettings[RSK_LINKS_POCKET] = CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON ? - CVarGetInteger("gRandomizeLinksPocket", RO_LINKS_POCKET_DUNGEON_REWARD) : RO_LINKS_POCKET_DUNGEON_REWARD; + cvarSettings[RSK_LINKS_POCKET] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON ? + CVarGetInteger(RANDOMIZER_SEED_CVAR("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) : RO_LINKS_POCKET_DUNGEON_REWARD; if (OTRGlobals::Instance->HasMasterQuest() && OTRGlobals::Instance->HasOriginal()) { // If both OTRs are loaded. - cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE); - cvarSettings[RSK_MQ_DUNGEON_COUNT] = CVarGetInteger("gRandomizeMqDungeonCount", 12); + cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE); + cvarSettings[RSK_MQ_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12); } else if (OTRGlobals::Instance->HasMasterQuest()) { // If only Master Quest is loaded. cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = RO_MQ_DUNGEONS_SET_NUMBER; @@ -2978,52 +2978,52 @@ void GenerateRandomizerImgui(std::string seed = "") { cvarSettings[RSK_MQ_DUNGEON_COUNT] = 0; } - cvarSettings[RSK_TRIFORCE_HUNT] = CVarGetInteger("gRandomizeTriforceHunt", 0); - cvarSettings[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = CVarGetInteger("gRandomizeTriforceHuntTotalPieces", 30); - cvarSettings[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = CVarGetInteger("gRandomizeTriforceHuntRequiredPieces", 20); + cvarSettings[RSK_TRIFORCE_HUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0); + cvarSettings[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 30); + cvarSettings[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 20); - cvarSettings[RSK_MQ_DEKU_TREE] = CVarGetInteger("gRandomizeMqDungeonsDekuTree", 0); - cvarSettings[RSK_MQ_DODONGOS_CAVERN] = CVarGetInteger("gRandomizeMqDungeonsDodongosCavern", 0); - cvarSettings[RSK_MQ_JABU_JABU] = CVarGetInteger("gRandomizeMqDungeonsJabuJabu", 0); - cvarSettings[RSK_MQ_FOREST_TEMPLE] = CVarGetInteger("gRandomizeMqDungeonsForestTemple", 0); - cvarSettings[RSK_MQ_FIRE_TEMPLE] = CVarGetInteger("gRandomizeMqDungeonsFireTemple", 0); - cvarSettings[RSK_MQ_WATER_TEMPLE] = CVarGetInteger("gRandomizeMqDungeonsWaterTemple", 0); - cvarSettings[RSK_MQ_SPIRIT_TEMPLE] = CVarGetInteger("gRandomizeMqDungeonsSpiritTemple", 0); - cvarSettings[RSK_MQ_SHADOW_TEMPLE] = CVarGetInteger("gRandomizeMqDungeonsShadowTemple", 0); - cvarSettings[RSK_MQ_BOTTOM_OF_THE_WELL] = CVarGetInteger("gRandomizeMqDungeonsBottomOfTheWell", 0); - cvarSettings[RSK_MQ_ICE_CAVERN] = CVarGetInteger("gRandomizeMqDungeonsIceCavern", 0); - cvarSettings[RSK_MQ_GTG] = CVarGetInteger("gRandomizeMqDungeonsGTG", 0); - cvarSettings[RSK_MQ_GANONS_CASTLE] = CVarGetInteger("gRandomizeMqDungeonsGanonsCastle", 0); + cvarSettings[RSK_MQ_DEKU_TREE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsDekuTree"), 0); + cvarSettings[RSK_MQ_DODONGOS_CAVERN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsDodongosCavern"), 0); + cvarSettings[RSK_MQ_JABU_JABU] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsJabuJabu"), 0); + cvarSettings[RSK_MQ_FOREST_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsForestTemple"), 0); + cvarSettings[RSK_MQ_FIRE_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsFireTemple"), 0); + cvarSettings[RSK_MQ_WATER_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsWaterTemple"), 0); + cvarSettings[RSK_MQ_SPIRIT_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsSpiritTemple"), 0); + cvarSettings[RSK_MQ_SHADOW_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsShadowTemple"), 0); + cvarSettings[RSK_MQ_BOTTOM_OF_THE_WELL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsBottomOfTheWell"), 0); + cvarSettings[RSK_MQ_ICE_CAVERN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsIceCavern"), 0); + cvarSettings[RSK_MQ_GTG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsGTG"), 0); + cvarSettings[RSK_MQ_GANONS_CASTLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsGanonsCastle"), 0); // Enable if any of the entrance rando options are enabled. - cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVarGetInteger("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger("gRandomizeShuffleBossEntrances", RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF) || - CVarGetInteger("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF) || - CVarGetInteger("gRandomizeShuffleOwlDrops", RO_GENERIC_OFF) || - CVarGetInteger("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF) || - CVarGetInteger("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), RO_GENERIC_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF) || + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVarGetInteger("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_BOSS_ENTRANCES] = CVarGetInteger("gRandomizeShuffleBossEntrances", RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVarGetInteger("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVarGetInteger("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_OWL_DROPS] = CVarGetInteger("gRandomizeShuffleOwlDrops", RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_WARP_SONGS] = CVarGetInteger("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF); - cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF); - cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger("gRandomizeMixDungeons", RO_GENERIC_OFF); - cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger("gRandomizeMixBosses", RO_GENERIC_OFF); - cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger("gRandomizeMixOverworld", RO_GENERIC_OFF); - cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger("gRandomizeMixInteriors", RO_GENERIC_OFF); - cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger("gRandomizeMixGrottos", RO_GENERIC_OFF); - cvarSettings[RSK_DECOUPLED_ENTRANCES] = CVarGetInteger("gRandomizeDecoupleEntrances", RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_BOSS_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_OWL_DROPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_WARP_SONGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_OFF); + cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixedEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixDungeons"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixBosses"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixOverworld"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixInteriors"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixGrottos"), RO_GENERIC_OFF); + cvarSettings[RSK_DECOUPLED_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DecoupleEntrances"), RO_GENERIC_OFF); // todo: this efficently when we build out cvar array support std::set excludedLocations; - std::stringstream excludedLocationStringStream(CVarGetString("gRandomizeExcludedLocations", "")); + std::stringstream excludedLocationStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), "")); std::string excludedLocationString; while (getline(excludedLocationStringStream, excludedLocationString, ',')) { excludedLocations.insert((RandomizerCheck)std::stoi(excludedLocationString)); @@ -3032,7 +3032,7 @@ void GenerateRandomizerImgui(std::string seed = "") { // todo: better way to sort out linking tricks rather than name std::set enabledTricks; - std::stringstream enabledTrickStringStream(CVarGetString("gRandomizeEnabledTricks", "")); + std::stringstream enabledTrickStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), "")); std::string enabledTrickString; while (getline(enabledTrickStringStream, enabledTrickString, ',')) { enabledTricks.insert((RandomizerTrick)std::stoi(enabledTrickString)); @@ -3154,8 +3154,8 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::EndDisabled(); UIWidgets::Spacer(0); - UIWidgets::EnhancementCheckbox("Manual seed entry", "gRandoManualSeedEntry", false, ""); - if (CVarGetInteger("gRandoManualSeedEntry", 0)) { + UIWidgets::EnhancementCheckbox("Manual seed entry", RANDOMIZER_SEED_CVAR("ManualSeedEntry"), false, ""); + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ManualSeedEntry"), 0)) { ImGui::Text("Seed"); ImGui::InputText("##RandomizerSeed", seedString, MAX_SEED_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); UIWidgets::Tooltip( @@ -3174,14 +3174,14 @@ void RandomizerSettingsWindow::DrawElement() { } UIWidgets::Spacer(0); - ImGui::BeginDisabled(CVarGetInteger("gRandomizerDontGenerateSpoiler", 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT); if (ImGui::Button("Generate Randomizer")) { - GenerateRandomizer(CVarGetInteger("gRandoManualSeedEntry", 0) ? seedString : ""); + GenerateRandomizer(CVarGetInteger(RANDOMIZER_SEED_CVAR("ManualSeedEntry"), 0) ? seedString : ""); } ImGui::EndDisabled(); UIWidgets::Spacer(0); - if (!CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) { + if (!CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { std::string spoilerfilepath = CVarGetString("gSpoilerLog", ""); ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str()); } @@ -3209,7 +3209,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::PopItemFlag(); ImGui::TableNextRow(); - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // COLUMN 1 - Area Access ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; @@ -3230,7 +3230,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "boy no longer blocks the path out of the forest." ); - UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, RO_FOREST_CLOSED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Forest"), randoForest, RO_FOREST_CLOSED); UIWidgets::PaddedSeparator(); @@ -3243,7 +3243,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - The gate is always open. The happy mask shop " "will open immediately after obtaining Zelda's letter." ); - UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, RO_KAK_GATE_CLOSED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("KakarikoGate"), randoKakarikoGate, RO_KAK_GATE_CLOSED); UIWidgets::PaddedSeparator(); @@ -3258,7 +3258,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Open - The Door of Time is permanently open with no requirements." ); - UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, RO_DOOROFTIME_CLOSED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("DoorOfTime"), randoDoorOfTime, RO_DOOROFTIME_CLOSED); UIWidgets::PaddedSeparator(); @@ -3275,7 +3275,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - King Zora has already mweeped out of the way in both " "time periods. Ruto's Letter is removed from the item pool." ); - UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, RO_ZF_CLOSED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ZorasFountain"), randoZorasFountain, RO_ZF_CLOSED); UIWidgets::PaddedSeparator(); @@ -3289,9 +3289,9 @@ void RandomizerSettingsWindow::DrawElement() { //Starting Age //Disabled when Forest is set to Closed or under very specific conditions - bool disableRandoStartingAge = CVarGetInteger("gRandomizeForest", RO_FOREST_CLOSED) == RO_FOREST_CLOSED || - ((CVarGetInteger("gRandomizeDoorOfTime", RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED) && - (CVarGetInteger("gRandomizeShuffleOcarinas", RO_GENERIC_OFF) == RO_GENERIC_OFF)); // closed door of time with ocarina shuffle off + bool disableRandoStartingAge = CVarGetInteger(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED) == RO_FOREST_CLOSED || + ((CVarGetInteger(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED) && + (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), RO_GENERIC_OFF) == RO_GENERIC_OFF)); // closed door of time with ocarina shuffle off static const char* disableRandoStartingAgeText = "This option is disabled due to other options making the game unbeatable."; ImGui::Text("%s", Settings::StartingAge.GetName().c_str()); @@ -3300,7 +3300,7 @@ void RandomizerSettingsWindow::DrawElement() { "Starting as adult means you start with the Master Sword in your inventory.\n" "The child option is forcefully set if it would conflict with other options." ); - UIWidgets::EnhancementCombobox("gRandomizeStartingAge", randoStartingAge, RO_AGE_CHILD, disableRandoStartingAge, disableRandoStartingAgeText, RO_AGE_CHILD); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("StartingAge"), randoStartingAge, RO_AGE_CHILD, disableRandoStartingAge, disableRandoStartingAgeText, RO_AGE_CHILD); UIWidgets::PaddedSeparator(); @@ -3318,7 +3318,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Only \"Normal\" is compatible with Gerudo Fortress Key Rings." ); - UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, RO_GF_NORMAL); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GerudoFortress"), randoGerudoFortress, RO_GF_NORMAL); UIWidgets::PaddedSeparator(); @@ -3347,9 +3347,9 @@ void RandomizerSettingsWindow::DrawElement() { "Greg - Find Greg the Green Rupee." ); - UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, RO_BRIDGE_VANILLA); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("RainbowBridge"), randoRainbowBridge, RO_BRIDGE_VANILLA); ImGui::PopItemWidth(); - switch (CVarGetInteger("gRandomizeRainbowBridge", RO_BRIDGE_VANILLA)) { + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_VANILLA)) { case RO_BRIDGE_ALWAYS_OPEN: break; case RO_BRIDGE_VANILLA: @@ -3367,19 +3367,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeBridgeRewardOptions", randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeBridgeRewardOptions", RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - "gRandomizeStoneCount", 1, 3, "", 3, true, true, false); + RANDOMIZER_SEED_CVAR("StoneCount"), 1, 3, "", 3, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - "gRandomizeStoneCount", 1, 4, "", 4, true, true, false); + RANDOMIZER_SEED_CVAR("StoneCount"), 1, 4, "", 4, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - "gRandomizeStoneCount", 1, 3, "", 3, true, true, false); + RANDOMIZER_SEED_CVAR("StoneCount"), 1, 3, "", 3, true, true, false); break; } break; @@ -3396,19 +3396,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeBridgeRewardOptions", randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeBridgeRewardOptions", RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - "gRandomizeMedallionCount", 1, 6, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 6, "", 6, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - "gRandomizeMedallionCount", 1, 7, "", 7, true, true, false); + RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 7, "", 7, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - "gRandomizeMedallionCount", 1, 6, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 6, "", 6, true, true, false); break; } break; @@ -3425,19 +3425,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeBridgeRewardOptions", randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeBridgeRewardOptions", RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - "gRandomizeRewardCount", 1, 9, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("RewardCount"), 1, 9, "", 9, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - "gRandomizeRewardCount", 1, 10, "", 10, true, true, false); + RANDOMIZER_SEED_CVAR("RewardCount"), 1, 10, "", 10, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - "gRandomizeRewardCount", 1, 9, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("RewardCount"), 1, 9, "", 9, true, true, false); break; } @@ -3455,25 +3455,25 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeBridgeRewardOptions", randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeBridgeRewardOptions", RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - "gRandomizeDungeonCount", 1, 8, "", 8, true, true, false); + RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 8, "", 8, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - "gRandomizeDungeonCount", 1, 9, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 9, "", 9, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - "gRandomizeDungeonCount", 1, 8, "", 8, true, true, false); + RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 8, "", 8, true, true, false); break; } break; case RO_BRIDGE_TOKENS: UIWidgets::PaddedEnhancementSliderInt("Token Count: %d", "##RandoTokenCount", - "gRandomizeTokenCount", 1, 100, "", 100, true, true, false); + RANDOMIZER_SEED_CVAR("TokenCount"), 1, 100, "", 100, true, true, false); break; case RO_BRIDGE_GREG: break; @@ -3494,11 +3494,11 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Random Number - A Random number and set of trials will be required." ); - UIWidgets::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, RO_GANONS_TRIALS_SET_NUMBER); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GanonTrial"), randoGanonsTrial, RO_GANONS_TRIALS_SET_NUMBER); ImGui::PopItemWidth(); - if (CVarGetInteger("gRandomizeGanonTrial", RO_GANONS_TRIALS_SET_NUMBER) == RO_GANONS_TRIALS_SET_NUMBER) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) == RO_GANONS_TRIALS_SET_NUMBER) { UIWidgets::PaddedEnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", - "gRandomizeGanonTrialCount", 1, 6, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("GanonTrialCount"), 1, 6, "", 6, true, true, false); UIWidgets::InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); } @@ -3522,46 +3522,46 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Selection - Leave unchecked for Vanilla and checked for Master Quest." ); - UIWidgets::EnhancementCombobox("gRandomizeMqDungeons", randoMqDungeons, RO_MQ_DUNGEONS_NONE); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("MQDungeons"), randoMqDungeons, RO_MQ_DUNGEONS_NONE); ImGui::PopItemWidth(); - if (CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER) { UIWidgets::PaddedEnhancementSliderInt( - "Master Quest Dungeon Count: %d", "##RandoMqDungeonCount", "gRandomizeMqDungeonCount", 1, - 12, "", CVarGetInteger("gRandomizeMqDungeonCount", 12), true, true, false); + "Master Quest Dungeon Count: %d", "##RandoMqDungeonCount", RANDOMIZER_SEED_CVAR("MQDungeonCount"), 1, + 12, "", CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12), true, true, false); } - else if (CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { + else if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { UIWidgets::EnhancementCheckbox("Deku Tree##RandomizeMqDungeons", - "gRandomizeMqDungeonsDekuTree"); + RANDOMIZER_SEED_CVAR("MQDungeonsDekuTree")); UIWidgets::EnhancementCheckbox("Dodongo's Cavern##RandomizeMqDungeons", - "gRandomizeMqDungeonsDodongosCavern"); + RANDOMIZER_SEED_CVAR("MQDungeonsDodongosCavern")); UIWidgets::EnhancementCheckbox("Jabu Jabu's Belly##RandomizeMqDungeons", - "gRandomizeMqDungeonsJabuJabu"); + RANDOMIZER_SEED_CVAR("MQDungeonsJabuJabu")); UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeMqDungeons", - "gRandomizeMqDungeonsForestTemple"); + RANDOMIZER_SEED_CVAR("MQDungeonsForestTemple")); UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeMqDungeons", - "gRandomizeMqDungeonsFireTemple"); + RANDOMIZER_SEED_CVAR("MQDungeonsFireTemple")); UIWidgets::EnhancementCheckbox("Water Temple##RandomizeMqDungeons", - "gRandomizeMqDungeonsWaterTemple"); + RANDOMIZER_SEED_CVAR("MQDungeonsWaterTemple")); UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeMqDungeons", - "gRandomizeMqDungeonsSpiritTemple"); + RANDOMIZER_SEED_CVAR("MQDungeonsSpiritTemple")); UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeMqDungeons", - "gRandomizeMqDungeonsShadowTemple"); + RANDOMIZER_SEED_CVAR("MQDungeonsShadowTemple")); UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeMqDungeons", - "gRandomizeMqDungeonsBottomOfTheWell"); + RANDOMIZER_SEED_CVAR("MQDungeonsBottomOfTheWell")); UIWidgets::EnhancementCheckbox("Ice Cavern##RandomizeMqDungeons", - "gRandomizeMqDungeonsIceCavern"); - UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeMqDungeons", "gRandomizeMqDungeonsGTG"); + RANDOMIZER_SEED_CVAR("MQDungeonsIceCavern")); + UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeMqDungeons", RANDOMIZER_SEED_CVAR("MQDungeonsGTG")); UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeMqDungeons", - "gRandomizeMqDungeonsGanonsCastle"); + RANDOMIZER_SEED_CVAR("MQDungeonsGanonsCastle")); } UIWidgets::PaddedSeparator(); } - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // Triforce Hunt - UIWidgets::EnhancementCheckbox("Triforce Hunt", "gRandomizeTriforceHunt"); + UIWidgets::EnhancementCheckbox("Triforce Hunt", RANDOMIZER_SEED_CVAR("TriforceHunt")); UIWidgets::InsertHelpHoverText( "Pieces of the Triforce of Courage have been scattered across the world. Find them all to finish the game!\n\n" "When the required amount of pieces have been found, the game is saved and Ganon's Boss key is given " @@ -3569,26 +3569,26 @@ void RandomizerSettingsWindow::DrawElement() { "Keep in mind Ganon might not be logically beatable when \"All Locations Reachable\" is turned off." ); - if (CVarGetInteger("gRandomizeTriforceHunt", 0)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0)) { // Triforce Hunt (total pieces) UIWidgets::Spacer(0); - int totalPieces = CVarGetInteger("gRandomizeTriforceHuntTotalPieces", 30); + int totalPieces = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 30); ImGui::Text("Triforce Pieces in the world: %d", totalPieces); UIWidgets::InsertHelpHoverText( "The amount of Triforce pieces that will be placed in the world. " "Keep in mind seed generation can fail if more pieces are placed than there are junk items in the item pool." ); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##TriforceHuntTotalPieces", "gRandomizeTriforceHuntTotalPieces", 1, 100, "", 30); + UIWidgets::EnhancementSliderInt("", "##TriforceHuntTotalPieces", RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 1, 100, "", 30); // Triforce Hunt (required pieces) - int requiredPieces = CVarGetInteger("gRandomizeTriforceHuntRequiredPieces", 20); + int requiredPieces = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 20); ImGui::Text("Triforce Pieces to win: %d", requiredPieces); UIWidgets::InsertHelpHoverText( "The amount of Triforce pieces required to win the game." ); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##TriforceHuntRequiredPieces", "gRandomizeTriforceHuntRequiredPieces", 1, totalPieces, "", 20); + UIWidgets::EnhancementSliderInt("", "##TriforceHuntRequiredPieces", RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 1, totalPieces, "", 20); } UIWidgets::PaddedSeparator(); @@ -3615,7 +3615,7 @@ void RandomizerSettingsWindow::DrawElement() { "- Bottom of the Well will be open for adult after playing Song of Storms to the Windmill guy as child.\n" "- Gerudo Training Ground will be open for child after adult has paid to open the gate once." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonsEntrances", randoShuffleDungeonsEntrances, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), randoShuffleDungeonsEntrances, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); @@ -3628,12 +3628,12 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Full - Shuffle the entrances of all boss rooms together. Child may be expected to defeat Phantom Ganon and/or Bongo Bongo." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleBossEntrances", randoShuffleBossEntrances, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), randoShuffleBossEntrances, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); // Shuffle Overworld Entrances - UIWidgets::EnhancementCheckbox("Shuffle Overworld Entrances", "gRandomizeShuffleOverworldEntrances"); + UIWidgets::EnhancementCheckbox("Shuffle Overworld Entrances", RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle the pool of Overworld entrances, which corresponds to almost all loading zones between overworld areas.\n" "\n" @@ -3656,12 +3656,12 @@ void RandomizerSettingsWindow::DrawElement() { "- Temple of Time\n" "- Kakariko Potion Shop" ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleInteriorsEntrances", randoShuffleInteriorsEntrances, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), randoShuffleInteriorsEntrances, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); // Shuffle Grotto Entrances - UIWidgets::EnhancementCheckbox("Shuffle Grotto Entrances", "gRandomizeShuffleGrottosEntrances"); + UIWidgets::EnhancementCheckbox("Shuffle Grotto Entrances", RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle the pool of grotto entrances, including all graves, small Fairy fountains and the Deku Theatre." ); @@ -3669,7 +3669,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Owl Drops - UIWidgets::EnhancementCheckbox("Shuffle Owl Drops", "gRandomizeShuffleOwlDrops"); + UIWidgets::EnhancementCheckbox("Shuffle Owl Drops", RANDOMIZER_SEED_CVAR("ShuffleOwlDrops")); UIWidgets::InsertHelpHoverText( "Randomize where Kaepora Gaebora (the Owl) drops you at when you talk " "to him at Lake Hylia or at the top of Death Mountain Trail." @@ -3678,7 +3678,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Warp Songs - UIWidgets::EnhancementCheckbox("Shuffle Warp Songs", "gRandomizeShuffleWarpSongs"); + UIWidgets::EnhancementCheckbox("Shuffle Warp Songs", RANDOMIZER_SEED_CVAR("ShuffleWarpSongs")); UIWidgets::InsertHelpHoverText( "Randomize where each of the 6 warp songs leads to." ); @@ -3686,7 +3686,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Overworld Spawns - UIWidgets::EnhancementCheckbox("Shuffle Overworld Spawns", "gRandomizeShuffleOverworldSpawns"); + UIWidgets::EnhancementCheckbox("Shuffle Overworld Spawns", RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns")); UIWidgets::InsertHelpHoverText( "Randomize where you start as Child or Adult when loading a save in the Overworld. This " "means you may not necessarily spawn inside Link's House or Temple of Time.\n" @@ -3700,7 +3700,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Decouple Entrances - UIWidgets::EnhancementCheckbox("Decouple Entrances", "gRandomizeDecoupleEntrances"); + UIWidgets::EnhancementCheckbox("Decouple Entrances", RANDOMIZER_SEED_CVAR("DecoupleEntrances")); UIWidgets::InsertHelpHoverText( "Decouple entrances when shuffling them. This means you are no longer guaranteed " "to end up back where you came from when you go back through an entrance.\n" @@ -3712,7 +3712,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Mixed Entrance Pools - UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", "gRandomizeMixedEntrances"); + UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", RANDOMIZER_SEED_CVAR("MixedEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose " "entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n" @@ -3722,36 +3722,36 @@ void RandomizerSettingsWindow::DrawElement() { "vice versa, while overworld entrances are shuffled in their own separate pool and indoors stay vanilla." ); - if (CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF)) { - if (CVarGetInteger("gRandomizeShuffleDungeonsEntrances", RO_GENERIC_OFF)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MixedEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Dungeons", "gRandomizeMixDungeons"); + UIWidgets::EnhancementCheckbox("Mix Dungeons", RANDOMIZER_SEED_CVAR("MixDungeons")); UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool"); } - if (CVarGetInteger("gRandomizeShuffleBossEntrances", RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Bosses", "gRandomizeMixBosses"); + UIWidgets::EnhancementCheckbox("Mix Bosses", RANDOMIZER_SEED_CVAR("MixBosses")); UIWidgets::InsertHelpHoverText("Boss entrances will be part of the mixed pool"); } - if (CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Overworld", "gRandomizeMixOverworld"); + UIWidgets::EnhancementCheckbox("Mix Overworld", RANDOMIZER_SEED_CVAR("MixOverworld")); UIWidgets::InsertHelpHoverText("Overworld entrances will be part of the mixed pool"); } - if (CVarGetInteger("gRandomizeShuffleInteriorsEntrances", RO_GENERIC_OFF)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Interiors", "gRandomizeMixInteriors"); + UIWidgets::EnhancementCheckbox("Mix Interiors", RANDOMIZER_SEED_CVAR("MixInteriors")); UIWidgets::InsertHelpHoverText("Interior entrances will be part of the mixed pool"); } - if (CVarGetInteger("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF)) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Grottos", "gRandomizeMixGrottos"); + UIWidgets::EnhancementCheckbox("Mix Grottos", RANDOMIZER_SEED_CVAR("MixGrottos")); UIWidgets::InsertHelpHoverText("Grotto entrances will be part of the mixed pool"); } } @@ -3764,7 +3764,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::EndTabItem(); } - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (ImGui::BeginTabItem("Items")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoStartingInventory", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { @@ -3796,7 +3796,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Songs can appear at any location." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, RO_SONG_SHUFFLE_SONG_LOCATIONS); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleSongs"), randoShuffleSongs, RO_SONG_SHUFFLE_SONG_LOCATIONS); UIWidgets::PaddedSeparator(); @@ -3814,9 +3814,9 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "All Tokens - Shuffle all 100 GS tokens." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, RO_TOKENSANITY_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleTokens"), randoTokensanity, RO_TOKENSANITY_OFF); - UIWidgets::PaddedEnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong", true, false); + UIWidgets::PaddedEnhancementCheckbox("Nighttime GS expect Sun's Song", RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), true, false); UIWidgets::InsertHelpHoverText( "All Golden Skulltulas that require nighttime to appear will only be " "expected to be collected after getting Sun's Song." @@ -3826,9 +3826,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Kokiri Sword // Disabled when Start with Kokiri Sword is active - bool disableShuffleKokiriSword = CVarGetInteger("gRandomizeStartingKokiriSword", 0); + bool disableShuffleKokiriSword = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); static const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword", + UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), disableShuffleKokiriSword, disableShuffleKokiriSwordText); UIWidgets::InsertHelpHoverText( "Shuffles the Kokiri Sword into the item pool.\n" @@ -3840,9 +3840,9 @@ void RandomizerSettingsWindow::DrawElement() { //Shuffle Master Sword //RANDOTODO: Disable when Start with Master Sword is active - // bool disableShuffleMasterSword = CvarGetInteger("gRandomizeStartingMasterSword", 0); + // bool disableShuffleMasterSword = CvarGetInteger(RANDOMIZER_SEED_CVAR("StartingMasterSword"), 0); // static const char* disableShuffleMasterSwordText = "This option is disabled because \"Start with Master Sword\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleMasterSword.GetName().c_str(), "gRandomizeShuffleMasterSword"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleMasterSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleMasterSword")); UIWidgets::InsertHelpHoverText( "Shuffles the Master Sword into the item pool.\n" "\n" @@ -3854,9 +3854,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Ocarinas // Disabled when Start with Ocarina is active - bool disableShuffleOcarinas = CVarGetInteger("gRandomizeStartingOcarina", 0); + bool disableShuffleOcarinas = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); static const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas", + UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), disableShuffleOcarinas, disableShuffleOcarinasText); UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" @@ -3868,9 +3868,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Weird Egg // Disabled when Skip Child Zelda is active - bool disableShuffleWeirdEgg = CVarGetInteger("gRandomizeSkipChildZelda", 0); + bool disableShuffleWeirdEgg = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); static const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg", + UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), disableShuffleWeirdEgg, disableShuffleWeirdEggText); UIWidgets::InsertHelpHoverText( "Shuffles the Weird Egg from Malon in to the item pool. Enabling " @@ -3887,7 +3887,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Gerudo Membership Card - UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), "gRandomizeShuffleGerudoToken"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleGerudoToken")); UIWidgets::InsertHelpHoverText( "Shuffles the Gerudo Membership Card into the item pool.\n" "\n" @@ -3917,10 +3917,10 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Random - Vanilla shop items will be shuffled among different shops, and each shop will contain a random number(1-4) of non-vanilla shop items.\n" ); - UIWidgets::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, RO_SHOPSANITY_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Shopsanity"), randoShopsanity, RO_SHOPSANITY_OFF); // Shopsanity Prices - switch (CVarGetInteger("gRandomizeShopsanity", RO_SHOPSANITY_OFF)) { + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF)) { case RO_SHOPSANITY_OFF: case RO_SHOPSANITY_ZERO_ITEMS: // no need to show it if there aren't shop slots in the pool break; @@ -3932,9 +3932,9 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "X Wallet - Randomized between 5 and the wallet's max size, in multiples of 5" ); - UIWidgets::EnhancementCombobox("gRandomizeShopsanityPrices", randoShopsanityPrices, RO_SHOPSANITY_PRICE_BALANCED); - UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), "gRandomizeShopsanityPricesAffordable", - CVarGetInteger("gRandomizeShopsanityPrices", RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED, + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), randoShopsanityPrices, RO_SHOPSANITY_PRICE_BALANCED); + UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED, "This can only apply to a wallet range."); UIWidgets::InsertHelpHoverText("Random selection between the selected wallet tier's affordable price and the affordable prices of the preceding wallet tiers.\n\n" "Affordable prices per tier: starter = 10, adult = 105, giant = 205, tycoon = 505\n\n" @@ -3954,17 +3954,17 @@ void RandomizerSettingsWindow::DrawElement() { "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" "\n" "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"); - UIWidgets::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, RO_SCRUBS_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), randoShuffleScrubs, RO_SCRUBS_OFF); UIWidgets::PaddedSeparator(); // Shuffle Cows - UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleCows")); UIWidgets::InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleBeans")); UIWidgets::InsertHelpHoverText( "Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean " "Salesman to sell a random item at a price of 60 rupees." @@ -3985,12 +3985,12 @@ void RandomizerSettingsWindow::DrawElement() { "Granny's item will only be offered after you have traded in the Odd Mushroom when Shuffle Adult Trade is on. " "Otherwise when off, you will need to have found the Claim Check to buy her item (simulating the trade quest is complete)." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleMerchants", randoShuffleMerchants, RO_SHUFFLE_MERCHANTS_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), randoShuffleMerchants, RO_SHUFFLE_MERCHANTS_OFF); UIWidgets::PaddedSeparator(); // Shuffle Frog Song Rupees - UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees")); UIWidgets::InsertHelpHoverText( "Shuffles 5 Purple Rupees into to the item pool, and allows\n" "you to earn items by playing songs at the Frog Choir.\n" @@ -4002,7 +4002,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Adult Trade Quest - UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), "gRandomizeShuffleAdultTrade"); + UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleAdultTrade")); UIWidgets::InsertHelpHoverText( "Adds all of the adult trade quest items into the pool, each of which " "can be traded for a unique reward.\n" @@ -4019,9 +4019,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle 100 GS Reward // Forcefully enabled if Ganon's Boss Key is on the cursed man bool forceEnable100GSShuffle = - (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS); + (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS); static const char* disable100GSRewardText = "This option is forcefully enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\""; - UIWidgets::EnhancementCheckbox(Settings::Shuffle100GSReward.GetName().c_str(), "gRandomizeShuffle100GSReward", + UIWidgets::EnhancementCheckbox(Settings::Shuffle100GSReward.GetName().c_str(), RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), forceEnable100GSShuffle, disable100GSRewardText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::InsertHelpHoverText( "Shuffle the item the cursed rich man in the House of Skulltula gives when you " @@ -4055,7 +4055,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Spiritual stones and medallions can appear anywhere." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, RO_DUNGEON_REWARDS_END_OF_DUNGEON); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), randoShuffleDungeonRewards, RO_DUNGEON_REWARDS_END_OF_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4074,7 +4074,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Maps & Compasses can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), randoShuffleMapsAndCompasses, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4095,7 +4095,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Small Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Keysanity"), randoShuffleSmallKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4118,30 +4118,30 @@ void RandomizerSettingsWindow::DrawElement() { "other than Vanilla, then the maximum amount of Key Rings that can be selected by Random or " "Count will be 9. Otherwise, the maximum amount of Key Rings will be 8." ); - UIWidgets::EnhancementCombobox("gRandomizeShuffleKeyRings", randoShuffleKeyRings, RO_KEYRINGS_OFF); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), randoShuffleKeyRings, RO_KEYRINGS_OFF); ImGui::PopItemWidth(); - switch (CVarGetInteger("gRandomizeShuffleKeyRings", RO_KEYRINGS_OFF)) { + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_OFF)) { case RO_KEYRINGS_COUNT: - maxKeyringCount = (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; + maxKeyringCount = (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; UIWidgets::PaddedEnhancementSliderInt("Key Ring Count: %d", "##RandomizeShuffleKeyRingsRandomCount", - "gRandomizeShuffleKeyRingsRandomCount", 1, + RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), 1, maxKeyringCount, "", maxKeyringCount, true, true, false); break; case RO_KEYRINGS_SELECTION: disableGFKeyring = - CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) != RO_GF_NORMAL || CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA; - UIWidgets::EnhancementCheckbox("Gerudo Fortress##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsGerudoFortress", + CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) != RO_GF_NORMAL || CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA; + UIWidgets::EnhancementCheckbox("Gerudo Fortress##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), disableGFKeyring, "Disabled because the currently selected Gerudo Fortress Carpenters\n setting and/or Gerudo Fortress Keys setting is incompatible with \nhaving a Gerudo Fortress keyring."); - UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsForestTemple"); - UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsFireTemple"); - UIWidgets::EnhancementCheckbox("Water Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsWaterTemple"); - UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsSpiritTemple"); - UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsShadowTemple"); - UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsBottomOfTheWell"); - UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsGTG"); - UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeShuffleKeyRings", "gRandomizeShuffleKeyRingsGanonsCastle"); + UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple")); + UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple")); + UIWidgets::EnhancementCheckbox("Water Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple")); + UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple")); + UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple")); + UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell")); + UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG")); + UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle")); break; default: break; @@ -4161,7 +4161,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Thieve's Hideout Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, RO_GERUDO_KEYS_VANILLA); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GerudoKeys"), randoShuffleGerudoFortressKeys, RO_GERUDO_KEYS_VANILLA); UIWidgets::PaddedSeparator(); @@ -4180,7 +4180,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Boss Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BossKeysanity"), randoShuffleBossKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4209,13 +4209,13 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "100 GS Reward - Ganon's Boss Key will be awarded by the cursed rich man after you collect 100 Gold Skulltula Tokens." ); - bool disableGBK = CVarGetInteger("gRandomizeTriforceHunt", 0); + bool disableGBK = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0); static const char* disableGBKText = "This option is disabled because Triforce Hunt is enabled. Ganon's Boss key\nwill instead be given to you after Triforce Hunt completion."; - UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), randoShuffleGanonsBossKey, RO_GANON_BOSS_KEY_VANILLA, disableGBK, disableGBKText, RO_GANON_BOSS_KEY_VANILLA); ImGui::PopItemWidth(); - switch (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA)) { + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA)) { case RO_GANON_BOSS_KEY_LACS_STONES: ImGui::Text("Reward Options"); UIWidgets::InsertHelpHoverText( @@ -4229,19 +4229,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeLacsRewardOptions", randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeLacsRewardOptions", RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - "gRandomizeLacsStoneCount", 1, 3, "", 3, true, true, false); + RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 3, "", 3, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - "gRandomizeLacsStoneCount", 1, 4, "", 3, true, true, false); + RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 4, "", 3, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - "gRandomizeLacsStoneCount", 1, 3, "", 3, true, true, false); + RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 3, "", 3, true, true, false); break; } break; @@ -4258,19 +4258,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeLacsRewardOptions", randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeLacsRewardOptions", RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - "gRandomizeLacsMedallionCount", 1, 6, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 6, "", 6, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - "gRandomizeLacsMedallionCount", 1, 7, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 7, "", 6, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - "gRandomizeLacsMedallionCount", 1, 6, "", 6, true, true, false); + RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 6, "", 6, true, true, false); break; } break; @@ -4287,19 +4287,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeLacsRewardOptions", randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeLacsRewardOptions", RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - "gRandomizeLacsRewardCount", 1, 9, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 9, "", 9, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - "gRandomizeLacsRewardCount", 1, 10, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 10, "", 9, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - "gRandomizeLacsRewardCount", 1, 9, "", 9, true, true, false); + RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 9, "", 9, true, true, false); break; } break; @@ -4316,25 +4316,25 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox("gRandomizeLacsRewardOptions", randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeLacsRewardOptions", RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - "gRandomizeLacsDungeonCount", 1, 8, "", 8, true, true, false); + RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 8, "", 8, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - "gRandomizeLacsDungeonCount", 1, 9, "", 8, true, true, false); + RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 9, "", 8, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - "gRandomizeLacsDungeonCount", 1, 8, "", 8, true, true, false); + RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 8, "", 8, true, true, false); break; } break; case RO_GANON_BOSS_KEY_LACS_TOKENS: UIWidgets::PaddedEnhancementSliderInt("Token Count: %d", "##RandoLacsTokenCount", - "gRandomizeLacsTokenCount", 1, 100, "", 100, true, true, false); + RANDOMIZER_SEED_CVAR("LacsTokenCount"), 1, 100, "", 100, true, true, false); break; default: break; @@ -4352,7 +4352,7 @@ void RandomizerSettingsWindow::DrawElement() { } ImGui::EndDisabled(); - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (ImGui::BeginTabItem("Gameplay")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoGameplay", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { @@ -4370,57 +4370,57 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8)); // Cuccos to return - int cuccos = CVarGetInteger("gRandomizeCuccosToReturn", 7); + int cuccos = CVarGetInteger(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 7); ImGui::Text("Cuccos to return: %d", cuccos); UIWidgets::InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7); + UIWidgets::EnhancementSliderInt("", "##RandoCuccosToReturn", RANDOMIZER_SEED_CVAR("CuccosToReturn"), 0, 7, "", 7); UIWidgets::PaddedSeparator(); // Big Poe Target Count - int poes = CVarGetInteger("gRandomizeBigPoeTargetCount", 10); + int poes = CVarGetInteger(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 10); ImGui::Text("Big Poe Target Count: %d", poes); UIWidgets::InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10); + UIWidgets::EnhancementSliderInt("", "##RandoBigPoeTargetCount", RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1, 10, "", 10); UIWidgets::PaddedSeparator(); // Skip child stealth // Disabled when Skip Child Zelda is active - bool disableChildStealth = CVarGetInteger("gRandomizeSkipChildZelda", 0); + bool disableChildStealth = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); static const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; - UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); + UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipChildStealth"), disableChildStealth, disableChildStealthText); UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); UIWidgets::PaddedSeparator(); // Skip child zelda - UIWidgets::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); + UIWidgets::EnhancementCheckbox("Skip Child Zelda", RANDOMIZER_SEED_CVAR("SkipChildZelda")); UIWidgets::InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."); UIWidgets::PaddedSeparator(); // Skip Epona race - UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace"); + UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipEponaRace")); UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); UIWidgets::PaddedSeparator(); // Skip tower escape - UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape"); + UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipTowerEscape")); UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); UIWidgets::PaddedSeparator(); // Complete mask quest - UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), "gRandomizeCompleteMaskQuest"); + UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), RANDOMIZER_SEED_CVAR("CompleteMaskQuest")); UIWidgets::InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); UIWidgets::PaddedSeparator(); // Skip Scarecrow Song - UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), "gRandomizeSkipScarecrowsSong"); + UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipScarecrowsSong")); UIWidgets::InsertHelpHoverText( "Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will automatically summon him." ); @@ -4448,7 +4448,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Minimal - Most excess items are removed." ); - UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, RO_ITEM_POOL_BALANCED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ItemPool"), randoItemPool, RO_ITEM_POOL_BALANCED); UIWidgets::PaddedSeparator(); // Ice Traps @@ -4467,7 +4467,7 @@ void RandomizerSettingsWindow::DrawElement() { "Onslaught - All junk items will be replaced by Ice Traps, even those " "in the base pool." ); - UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, RO_ICE_TRAPS_NORMAL); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("IceTraps"), randoIceTraps, RO_ICE_TRAPS_NORMAL); UIWidgets::PaddedSeparator(); @@ -4485,8 +4485,8 @@ void RandomizerSettingsWindow::DrawElement() { "Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n" "\n" "Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n"); - UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, RO_GOSSIP_STONES_NEED_NOTHING); - if (CVarGetInteger("gRandomizeGossipStoneHints", RO_GOSSIP_STONES_NEED_NOTHING) != RO_GOSSIP_STONES_NONE) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GossipStoneHints"), randoGossipStoneHints, RO_GOSSIP_STONES_NEED_NOTHING); + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) != RO_GOSSIP_STONES_NONE) { // Hint Clarity UIWidgets::Spacer(0); ImGui::Indent(); @@ -4503,7 +4503,7 @@ void RandomizerSettingsWindow::DrawElement() { "Clear - Hints are clearly written and are unique for each item.\n" "Ex: Kokiri Sword > the Kokiri Sword" ); - UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, RO_HINT_CLARITY_CLEAR); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("HintClarity"), randoHintClarity, RO_HINT_CLARITY_CLEAR); // Hint Distribution UIWidgets::Spacer(0); @@ -4519,7 +4519,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Very Strong - Many powerful hints." ); - UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, RO_HINT_DIST_BALANCED); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("HintDistribution"), randoHintDistribution, RO_HINT_DIST_BALANCED); ImGui::Unindent(); } @@ -4534,30 +4534,30 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::Indent(); //Altar, Light Arrows, and Warp Songs are enabled by default - UIWidgets::PaddedEnhancementCheckbox("Altar Text", "gRandomizeAltarHint", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Altar Text", RANDOMIZER_SEED_CVAR("AltarHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Reading the Temple of Time altar as child will tell you the locations of the Spiritual Stones.\n" "Reading the Temple of Time altar as adult will tell you the locations of the Medallions, as well as the conditions for building the Rainbow Bridge and getting the Boss Key for Ganon's Castle."); - UIWidgets::PaddedEnhancementCheckbox("Light Arrows", "gRandomizeLAHint", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Light Arrows", RANDOMIZER_SEED_CVAR("LAHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Talking to Ganondorf in his boss room or Sheik inside Ganon's Castle (when trials are enabled) will tell you the location of the Light Arrows." "If this option is enabled and Ganondorf is reachable without Light Arrows, Gossip Stones will never hint the Light Arrows."); - UIWidgets::PaddedEnhancementCheckbox("Dampe's Diary (Hookshot)", "gRandomizeDampeHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("Dampe's Diary (Hookshot)", RANDOMIZER_SEED_CVAR("DampeHint"), true, false); UIWidgets::InsertHelpHoverText("Reading the diary of Dampé the gravekeeper as adult will tell you the location of one of the Hookshots."); - UIWidgets::PaddedEnhancementCheckbox("Greg the Green Rupee", "gRandomizeGregHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("Greg the Green Rupee", RANDOMIZER_SEED_CVAR("GregHint"), true, false); UIWidgets::InsertHelpHoverText("Talking to the chest game owner after buying a key will tell you the location of Greg the Green Rupee."); - UIWidgets::PaddedEnhancementCheckbox("Saria (Magic)", "gRandomizeSariaHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("Saria (Magic)", RANDOMIZER_SEED_CVAR("SariaHint"), true, false); UIWidgets::InsertHelpHoverText("Talking to Saria either in person or through Saria's Song will tell you the location of a progressive magic meter."); - UIWidgets::PaddedEnhancementCheckbox("Frog Ocarina Game", "gRandomizeFrogsHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("Frog Ocarina Game", RANDOMIZER_SEED_CVAR("FrogsHint"), true, false); UIWidgets::InsertHelpHoverText("Standing near the pedestal for the frogs in Zora's River will tell you the reward for the frogs' ocarina game."); - UIWidgets::PaddedEnhancementCheckbox("Warp Song text", "gRandomizeWarpSongText", true, false, !CVarGetInteger("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF), + UIWidgets::PaddedEnhancementCheckbox("Warp Song text", RANDOMIZER_SEED_CVAR("WarpSongText"), true, false, !CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF), "This option is disabled since warp songs are not shuffled.", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Playing a warp song will tell you where it leads. (If warp song destinations are vanilla, this is always enabled.)"); - UIWidgets::PaddedEnhancementCheckbox("Scrub Item text", "gRandomizeScrubText", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Scrub Item text", RANDOMIZER_SEED_CVAR("ScrubText"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::InsertHelpHoverText("Business scrubs will reveal the identity of what they're selling."); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 10", "gRandomize10GSHint", true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 20", "gRandomize20GSHint", true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 30", "gRandomize30GSHint", true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 40", "gRandomize40GSHint", true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 50", "gRandomize50GSHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 10", RANDOMIZER_SEED_CVAR("10GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 20", RANDOMIZER_SEED_CVAR("20GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 30", RANDOMIZER_SEED_CVAR("30GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 40", RANDOMIZER_SEED_CVAR("40GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 50", RANDOMIZER_SEED_CVAR("50GSHint"), true, false); ImGui::Unindent(); @@ -4572,13 +4572,13 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); + UIWidgets::EnhancementCheckbox("Full Wallets", RANDOMIZER_SEED_CVAR("FullWallets")); UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); UIWidgets::PaddedSeparator(); // Bombchus in Logic - UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); + UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), RANDOMIZER_SEED_CVAR("BombchusInLogic")); UIWidgets::InsertHelpHoverText( "Bombchus are properly considered in logic.\n" "\n" @@ -4592,14 +4592,14 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Enable Bombchu Drops - UIWidgets::EnhancementCheckbox("Enable Bombchu Drops", "gRandomizeEnableBombchuDrops"); + UIWidgets::EnhancementCheckbox("Enable Bombchu Drops", RANDOMIZER_SEED_CVAR("EnableBombchuDrops")); UIWidgets::InsertHelpHoverText( "Once you obtain bombchus for the first time, refills can be found in bushes and other places where bomb drops can normally spawn." ); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox("Blue Fire Arrows", "gRandomizeBlueFireArrows"); + UIWidgets::EnhancementCheckbox("Blue Fire Arrows", RANDOMIZER_SEED_CVAR("BlueFireArrows")); UIWidgets::InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress." @@ -4607,7 +4607,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox("Sunlight Arrows", "gRandomizeSunlightArrows"); + UIWidgets::EnhancementCheckbox("Sunlight Arrows", RANDOMIZER_SEED_CVAR("SunlightArrows")); UIWidgets::InsertHelpHoverText( "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress." @@ -4624,7 +4624,7 @@ void RandomizerSettingsWindow::DrawElement() { } ImGui::EndDisabled(); - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); static bool locationsTabOpen = false; if (ImGui::BeginTabItem("Locations")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); @@ -4632,7 +4632,7 @@ void RandomizerSettingsWindow::DrawElement() { locationsTabOpen = true; RandomizerCheckObjects::UpdateImGuiVisibility(); // todo: this efficently when we build out cvar array support - std::stringstream excludedLocationStringStream(CVarGetString("gRandomizeExcludedLocations", "")); + std::stringstream excludedLocationStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), "")); std::string excludedLocationString; excludedLocations.clear(); while (getline(excludedLocationStringStream, excludedLocationString, ',')) { @@ -4682,7 +4682,7 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += std::to_string(excludedLocationIt); excludedLocationString += ","; } - CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), excludedLocationString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -4724,9 +4724,9 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += ","; } if (excludedLocationString == "") { - CVarClear("gRandomizeExcludedLocations"); + CVarClear(RANDOMIZER_SEED_CVAR("ExcludedLocations")); } else { - CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), excludedLocationString.c_str()); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -4755,13 +4755,13 @@ void RandomizerSettingsWindow::DrawElement() { tricksTabOpen = true; //RandomizerTricks::UpdateImGuiVisibility(); // todo: this efficently when we build out cvar array support - std::stringstream enabledTrickStringStream(CVarGetString("gRandomizeEnabledTricks", "")); + std::stringstream enabledTrickStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), "")); std::string enabledTrickString; enabledTricks.clear(); while (getline(enabledTrickStringStream, enabledTrickString, ',')) { enabledTricks.insert((RandomizerTrick)std::stoi(enabledTrickString)); } - std::stringstream enabledGlitchStringStream(CVarGetString("gRandomizeEnabledGlitches", "")); + std::stringstream enabledGlitchStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledGlitches"), "")); std::string enabledGlitchString; enabledGlitches.clear(); while (getline(enabledGlitchStringStream, enabledGlitchString, ',')) { @@ -4785,10 +4785,10 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Vanilla - Places all items and dungeon rewards in their vanilla locations." ); - UIWidgets::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, RO_LOGIC_GLITCHLESS); - if (CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_GLITCHLESS) { + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LogicRules"), randoLogicRules, RO_LOGIC_GLITCHLESS); + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_GLITCHLESS) { ImGui::SameLine(); - UIWidgets::EnhancementCheckbox(Settings::LocationsReachable.GetName().c_str(), "gRandomizeAllLocationsReachable", false, "", UIWidgets::CheckboxGraphics::Cross, RO_GENERIC_ON); + UIWidgets::EnhancementCheckbox(Settings::LocationsReachable.GetName().c_str(), RANDOMIZER_SEED_CVAR("AllLocationsReachable"), false, "", UIWidgets::CheckboxGraphics::Cross, RO_GENERIC_ON); UIWidgets::InsertHelpHoverText( "When this options is enabled, the randomizer will " "guarantee that every item is obtainable and every " @@ -4797,7 +4797,7 @@ void RandomizerSettingsWindow::DrawElement() { "will be guaranteed reachable." ); } - if (CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { ImGui::SameLine(); ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Heads up! This will disable all rando settings except for entrance shuffle and starter items"); } @@ -4805,7 +4805,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Enable Glitch-Useful Cutscenes - UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), "gRandomizeEnableGlitchCutscenes"); + UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes")); UIWidgets::InsertHelpHoverText( "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); @@ -4814,7 +4814,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::EndTable(); } - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // Tricks static std::unordered_map areaTreeDisabled { @@ -4897,7 +4897,7 @@ void RandomizerSettingsWindow::DrawElement() { }; static ImGuiTextFilter trickSearch; trickSearch.Draw("Filter (inc,-exc)", 490.0f); - if (CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { ImGui::SameLine(); if (ImGui::Button("Disable All")) { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { @@ -4913,7 +4913,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarClear("gRandomizeEnabledTricks"); + CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -4930,7 +4930,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } @@ -4952,7 +4952,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::PopItemFlag(); ImGui::TableNextRow(); - if (CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { + if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { // COLUMN 1 - DISABLED TRICKS ImGui::TableNextColumn(); @@ -5007,7 +5007,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5043,7 +5043,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } DrawTagChips(*rtObject.rtTags); @@ -5117,7 +5117,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarClear("gRandomizeEnabledTricks"); + CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5156,9 +5156,9 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } if (enabledTrickString == "") { - CVarClear("gRandomizeEnabledTricks"); + CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); } else { - CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str()); + CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5215,17 +5215,17 @@ void RandomizerSettingsWindow::DrawElement() { window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); ImGui::BeginDisabled( - CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON || - CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON || + CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA ); ImGui::Text("%s", Settings::LinksPocketItem.GetName().c_str()); - UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, RO_LINKS_POCKET_DUNGEON_REWARD); + UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LinksPocket"), randoLinksPocket, RO_LINKS_POCKET_DUNGEON_REWARD); UIWidgets::PaddedSeparator(); ImGui::EndDisabled(); - UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), "gRandomizeStartingKokiriSword"); + UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingKokiriSword")); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), "gRandomizeStartingDekuShield"); + UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingDekuShield")); UIWidgets::PaddedSeparator(); @@ -5236,13 +5236,13 @@ void RandomizerSettingsWindow::DrawElement() { window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); - UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina"); + ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingOcarina")); UIWidgets::PaddedSeparator(); ImGui::EndDisabled(); - UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), "gRandomizeStartingConsumables"); + UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingConsumables")); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementSliderInt("Gold Skulltula Tokens: %d", "##RandoStartingSkulltulaToken", "gRandomizeStartingSkulltulaToken", 0, 100, "", 0); + UIWidgets::EnhancementSliderInt("Gold Skulltula Tokens: %d", "##RandoStartingSkulltulaToken", RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), 0, 100, "", 0); UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -5251,22 +5251,22 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingSongs", ImVec2(0, -8)); - UIWidgets::EnhancementCheckbox(Settings::StartingZeldasLullaby.GetName().c_str(), "gRandomizeStartingZeldasLullaby"); - UIWidgets::EnhancementCheckbox(Settings::StartingEponasSong.GetName().c_str(), "gRandomizeStartingEponasSong"); - UIWidgets::EnhancementCheckbox(Settings::StartingSariasSong.GetName().c_str(), "gRandomizeStartingSariasSong"); - UIWidgets::EnhancementCheckbox(Settings::StartingSunsSong.GetName().c_str(), "gRandomizeStartingSunsSong"); - UIWidgets::EnhancementCheckbox(Settings::StartingSongOfTime.GetName().c_str(), "gRandomizeStartingSongOfTime"); - UIWidgets::EnhancementCheckbox(Settings::StartingSongOfStorms.GetName().c_str(), "gRandomizeStartingSongOfStorms"); + UIWidgets::EnhancementCheckbox(Settings::StartingZeldasLullaby.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingZeldasLullaby")); + UIWidgets::EnhancementCheckbox(Settings::StartingEponasSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingEponasSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSariasSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSariasSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSunsSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSunsSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSongOfTime.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSongOfTime")); + UIWidgets::EnhancementCheckbox(Settings::StartingSongOfStorms.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSongOfStorms")); UIWidgets::PaddedSeparator(); ImGui::Text("Warp Songs"); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::StartingMinuetOfForest.GetName().c_str(), "gRandomizeStartingMinuetOfForest"); - UIWidgets::EnhancementCheckbox(Settings::StartingBoleroOfFire.GetName().c_str(), "gRandomizeStartingBoleroOfFire"); - UIWidgets::EnhancementCheckbox(Settings::StartingSerenadeOfWater.GetName().c_str(), "gRandomizeStartingSerenadeOfWater"); - UIWidgets::EnhancementCheckbox(Settings::StartingRequiemOfSpirit.GetName().c_str(), "gRandomizeStartingRequiemOfSpirit"); - UIWidgets::EnhancementCheckbox(Settings::StartingNocturneOfShadow.GetName().c_str(), "gRandomizeStartingNocturneOfShadow"); - UIWidgets::EnhancementCheckbox(Settings::StartingPreludeOfLight.GetName().c_str(), "gRandomizeStartingPreludeOfLight"); + UIWidgets::EnhancementCheckbox(Settings::StartingMinuetOfForest.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingMinuetOfForest")); + UIWidgets::EnhancementCheckbox(Settings::StartingBoleroOfFire.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingBoleroOfFire")); + UIWidgets::EnhancementCheckbox(Settings::StartingSerenadeOfWater.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater")); + UIWidgets::EnhancementCheckbox(Settings::StartingRequiemOfSpirit.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit")); + UIWidgets::EnhancementCheckbox(Settings::StartingNocturneOfShadow.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow")); + UIWidgets::EnhancementCheckbox(Settings::StartingPreludeOfLight.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingPreludeOfLight")); UIWidgets::PaddedSeparator(); ImGui::EndChild(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index d55110861..f3582a5cb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -3,6 +3,7 @@ #include #include #include "z64.h" +#include "soh/OTRGlobals.h" // RandomizerCheck, RCVORMQ, RCTYPE, RCAREA, ActorId, SceneId, ActorParams, OG ItemID, "Short name", "Spoiler name", vanillaCompletion std::map rcObjects = { @@ -884,57 +885,57 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { (!RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea) || locationIt.vOrMQ == RCVORMQ_BOTH || locationIt.vOrMQ == RCVORMQ_MQ && - ((CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && (CVarGetInteger("gRandomizeMqDungeonCount", 12) > 0) || // at least one MQ dungeon - CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || + ((CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12) > 0) || // at least one MQ dungeon + CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || locationIt.vOrMQ == RCVORMQ_VANILLA && - (CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || CVarGetInteger("gRandomizeMqDungeonCount", 12) < 12) // at least one vanilla dungeon + (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon ) && - (locationIt.rcType != RCTYPE_SHOP || CVarGetInteger("gRandomizeShopsanity", RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && - (locationIt.rcType != RCTYPE_SCRUB || CVarGetInteger("gRandomizeShuffleScrubs", RO_SCRUBS_OFF) != RO_SCRUBS_OFF || + (locationIt.rcType != RCTYPE_SHOP || CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && + (locationIt.rcType != RCTYPE_SCRUB || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_OFF) != RO_SCRUBS_OFF || locationIt.rc == RC_HF_DEKU_SCRUB_GROTTO || locationIt.rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT || locationIt.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE) && // The 3 scrubs that are always randomized - (locationIt.rcType != RCTYPE_MERCHANT || CVarGetInteger("gRandomizeShuffleMerchants", RO_SHUFFLE_MERCHANTS_OFF) != RO_SHUFFLE_MERCHANTS_OFF) && - (locationIt.rcType != RCTYPE_SONG_LOCATION || CVarGetInteger("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_SONG_LOCATIONS) && // song locations + (locationIt.rcType != RCTYPE_MERCHANT || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF) != RO_SHUFFLE_MERCHANTS_OFF) && + (locationIt.rcType != RCTYPE_SONG_LOCATION || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_SONG_LOCATIONS) && // song locations ((locationIt.rcType != RCTYPE_BOSS_HEART_OR_OTHER_REWARD && locationIt.rc != RC_SONG_FROM_IMPA && locationIt.rc != RC_SHEIK_IN_ICE_CAVERN) || - CVarGetInteger("gRandomizeShuffleSongs", RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_DUNGEON_REWARDS) && // song dungeon rewards - (locationIt.rcType != RCTYPE_DUNGEON_REWARD || CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON) && // dungeon rewards end of dungeons - (locationIt.rcType != RCTYPE_OCARINA || CVarGetInteger("gRandomizeShuffleOcarinas", RO_GENERIC_NO)) && // ocarina locations + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_DUNGEON_REWARDS) && // song dungeon rewards + (locationIt.rcType != RCTYPE_DUNGEON_REWARD || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON) && // dungeon rewards end of dungeons + (locationIt.rcType != RCTYPE_OCARINA || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), RO_GENERIC_NO)) && // ocarina locations (locationIt.rc != RC_HC_ZELDAS_LETTER) && // don't show until we support shuffling letter (locationIt.rcType != RCTYPE_GOSSIP_STONE) && // don't show gossip stones (maybe gossipsanity will be a thing eventually?) (locationIt.rcType != RCTYPE_LINKS_POCKET) && // links pocket can be set to nothing if needed (locationIt.rcType != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them (locationIt.rcType != RCTYPE_SKULL_TOKEN || - (CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_ALL) || - ((CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_OVERWORLD) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) || - ((CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea)) + (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_ALL) || + ((CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_OVERWORLD) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) || + ((CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea)) ) && - (locationIt.rcType != RCTYPE_COW || CVarGetInteger("gRandomizeShuffleCows", RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_ADULT_TRADE || CVarGetInteger("gRandomizeShuffleAdultTrade", RO_GENERIC_NO)) && - (locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST || CVarGetInteger("gRandomizeShuffleKokiriSword", RO_GENERIC_NO)) && - (locationIt.rc != RC_ZR_MAGIC_BEAN_SALESMAN || CVarGetInteger("gRandomizeShuffleBeans", RO_GENERIC_NO)) && - (locationIt.rc != RC_HC_MALON_EGG || CVarGetInteger("gRandomizeShuffleWeirdEgg", RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_FROG_SONG || CVarGetInteger("gRandomizeShuffleFrogSongRupees", RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_MAP_COMPASS || CVarGetInteger("gRandomizeStartingMapsCompasses", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_SMALL_KEY || CVarGetInteger("gRandomizeKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_BOSS_KEY || CVarGetInteger("gRandomizeBossKeysanity", RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_GANON_BOSS_KEY || CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_VANILLA) && // vanilla ganon boss key + (locationIt.rcType != RCTYPE_COW || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleCows"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_ADULT_TRADE || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), RO_GENERIC_NO)) && + (locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), RO_GENERIC_NO)) && + (locationIt.rc != RC_ZR_MAGIC_BEAN_SALESMAN || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBeans"), RO_GENERIC_NO)) && + (locationIt.rc != RC_HC_MALON_EGG || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_FROG_SONG || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_MAP_COMPASS || CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_SMALL_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_BOSS_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_GANON_BOSS_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_VANILLA) && // vanilla ganon boss key (locationIt.rc != RC_TOT_LIGHT_ARROWS_CUTSCENE || - (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_DUNGEONS && - CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_MEDALLIONS && - CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_REWARDS && - CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_STONES && - CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_TOKENS && - CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_VANILLA) + (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_DUNGEONS && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_MEDALLIONS && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_REWARDS && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_STONES && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_TOKENS && + CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_VANILLA) ) && // LACS ganon boss key - (locationIt.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_KAK_TOKENS) && // 100 skull reward ganon boss key + (locationIt.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_KAK_TOKENS) && // 100 skull reward ganon boss key (locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD || - (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_OPEN && locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) || - (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_FAST && - ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger("gRandomizeShuffleGerudoToken", RO_GENERIC_NO) == RO_GENERIC_YES) || - (locationIt.rc == RC_GF_NORTH_F1_CARPENTER && CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) + (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_OPEN && locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) || + (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_FAST && + ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || + (locationIt.rc == RC_GF_NORTH_F1_CARPENTER && CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) ) || - (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL && - ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger("gRandomizeShuffleGerudoToken", RO_GENERIC_NO) == RO_GENERIC_YES) || - (locationIt.rcType == RCTYPE_GF_KEY && CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) + (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || + (locationIt.rcType == RCTYPE_GF_KEY && CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) ) ) ); diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index a4af676e0..e78ca1bdc 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -65,6 +65,22 @@ private: uint32_t IsGameMasterQuest(); #endif +#define RANDOMIZER_CVAR(var) "gRandoEnhancements." var +#define RANDOMIZER_SEED_CVAR(var) "gRandoSettings." var +#define COSMETIC_CVAR(var) "gCosmetics." var +#define AUDIO_CVAR(var) "gAudioEditor." var +#define REPL_SEQ_CVAR(var) AUDIO_CVAR("ReplacedSequences." var) +#define EXCL_SEQ_CVAR(var) AUDIO_CVAR("Excluded." var) +#define CHEAT_CVAR(var) "gCheats." var +#define ENHANCEMENT_CVAR(var) "gEnhancements." var +#define SETTING_CVAR(var) "gSettings." var +#define WINDOW_CVAR(var) "gOpenWindows." var +#define TRACKER_CVAR(var) "gTrackers." var +#define ITEM_TRACKER_CVAR(var) TRACKER_CVAR("ItemTracker." var) +#define CHECK_TRACKER_CVAR(var) TRACKER_CVAR("CheckTracker." var) +#define ENTRANCE_TRACKER_CVAR(var) TRACKER_CVAR("EntranceTracker." var) +#define DEV_TOOLS_CVAR(var) "gDeveloperTools." + #ifndef __cplusplus void InitOTR(void); void DeinitOTR(void); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 4fb0ff1fe..ef825cb18 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1025,7 +1025,7 @@ void FileChoose_UpdateRandomizer() { return; } - if (!SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && !CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) { + if (!SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && !CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { CVarSetString("gSpoilerLog", ""); fileSelectSpoilerFileLoaded = false; } @@ -1053,7 +1053,7 @@ void FileChoose_UpdateRandomizer() { Randomizer_LoadEntranceOverrides(fileLoc, silent); fileSelectSpoilerFileLoaded = true; - if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) { + if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { remove(fileLoc); } } From 4a576f45eebbe4195162e916d8da6e342d854045 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sat, 20 Apr 2024 15:43:35 +0100 Subject: [PATCH 166/300] Fix and Clean Up Swap Age Logic (#4061) * Split and clean up swap age logic * reorganise conditions into one statement --- soh/src/code/z_parameter.c | 278 ++++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 100 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a4d61f877..449ee2854 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1436,64 +1436,62 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te return displayListHead; } -void Inventory_SwapAgeEquipment(void) { +void Rando_Inventory_SwapAgeEquipment(void) { s16 i; u16 shieldEquipValue; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (i != 0) { - gSaveContext.childEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; } else { gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; } if (i != 0) { - gSaveContext.childEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } - // When becoming adult, remove swordless flag since we'll get master sword - // (Unless Master Sword is shuffled) - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; - if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.adultEquips.equipment)) { - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; - } else { - gSaveContext.equips.buttonItems[0] = ITEM_NONE; - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + // When becoming adult, remove swordless flag since we'll get master sword + // This gets set back appropriately later in the case of master sword shuffle + Flags_UnsetInfTable(INFTABLE_SWORDLESS); + + // This section sets up the equipment on the first time going adult. + // On master sword shuffle the check for the B button is insufficient, and so checking the equipment is completely zero-ed is needed + // (Could just always use `gSaveContext.adultEquips.equipment == 0` for rando?) + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && ((IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) || (gSaveContext.adultEquips.equipment == 0))) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { gSaveContext.equips.buttonItems[1] = ITEM_NUT; gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; } else { - gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE; + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; } gSaveContext.equips.buttonItems[2] = ITEM_BOMB; gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; - gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | - (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | - (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // In Master Sword Shuffle we want to override the equip of the master sword from the vanilla code + // First check we have the Master sword in our inventory, and if not, then unequip if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] == ITEM_NONE) { + !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; + Flags_SetInfTable(INFTABLE_SWORDLESS); } - // Set the dpad to nothing gSaveContext.equips.buttonItems[4] = ITEM_NONE; gSaveContext.equips.buttonItems[5] = ITEM_NONE; @@ -1505,25 +1503,25 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; } else { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.adultEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.adultEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - // In Rando, when switching to adult for the second+ time, if a sword was not previously - // equiped in MS shuffle, then we need to set the swordless flag again - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && + // In Master Sword Shuffle we want to set the swordless flag if no item is on the B button + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.equips.buttonItems[0] == ITEM_NONE) { Flags_SetInfTable(INFTABLE_SWORDLESS); } @@ -1531,90 +1529,43 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; } } else { - // When becoming child, set swordless flag if player doesn't have kokiri sword - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } - - // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. - // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; - } for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; if (i != 0) { - gSaveContext.adultEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; - // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) { + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - // Equips kokiri sword in the inventory screen only if kokiri sword exists in inventory and a sword has been equipped already - if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) && !Flags_GetInfTable(INFTABLE_SWORDLESS)) { - gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } - } else if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; - - if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; - } - - if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && - (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || - ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && - (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); - gSaveContext.equips.buttonItems[i] = - gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; - } - } - - // In Rando, when switching to child from a swordless adult, and child Link previously had a - // sword equiped, then we need to unset the swordless flag to match - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] != ITEM_NONE) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } else if (IS_RANDO && Randomizer_GetSettingValue(RSK_STARTING_AGE) == RO_AGE_ADULT) { - /*If in rando and starting age is adult, childEquips is not initialized and buttonItems[0] - will be ITEM_NONE. When changing age from adult -> child, reset equips to "default" - (only kokiri tunic/boots equipped, no sword, no C-button items, no D-Pad items). - When becoming child, set swordless flag if player doesn't have kokiri sword - Only in rando to keep swordless link bugs in vanilla*/ - if (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + } + // In Rando we need an extra case to handle starting as adult. We can use the fact that the childEquips will be uninitialised (i.e. 0) at this point + else if (gSaveContext.childEquips.equipment == 0) { //zero out items for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { @@ -1629,20 +1580,147 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && - (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { + // When becoming child in rando, set swordless flag and clear B button if player doesn't have kokiri sword + // Otherwise, equip sword and unset flag + if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI)) { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; Flags_SetInfTable(INFTABLE_SWORDLESS); - if (gSaveContext.childEquips.equipment == 0) { - // force equip kokiri tunic and boots in scenario gSaveContext.childEquips.equipment is uninitialized - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - gSaveContext.equips.equipment |= (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); - } + } else { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI; + Flags_UnsetInfTable(INFTABLE_SWORDLESS); } } - CVarSetInteger("gSwitchTimeline", 0); + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; - if (shieldEquipValue != 0) { + if (shieldEquipValue) { + shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; + if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { + gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; + } + } +} + +void Inventory_SwapAgeEquipment(void) { + s16 i; + u16 shieldEquipValue; + + // Mod Enhancments can utilise the rando flow path + if (IS_RANDO || CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) { + Rando_Inventory_SwapAgeEquipment(); + CVarSetInteger("gSwitchTimeline", 0); + return; + } + + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + if (i != 0) { + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; + } else { + gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; + } + + if (i != 0) { + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + + if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { + gSaveContext.equips.buttonItems[1] = ITEM_NUT; + gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; + } else { + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; + } + + gSaveContext.equips.buttonItems[2] = ITEM_BOMB; + gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; + gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; + gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; + gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // Set the dpad to nothing + gSaveContext.equips.buttonItems[4] = ITEM_NONE; + gSaveContext.equips.buttonItems[5] = ITEM_NONE; + gSaveContext.equips.buttonItems[6] = ITEM_NONE; + gSaveContext.equips.buttonItems[7] = ITEM_NONE; + gSaveContext.equips.cButtonSlots[3] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[4] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[5] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; + } + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + + if (i != 0) { + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); + } + } + + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; + if (shieldEquipValue) { shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; From d08d5a54c91f4a022727ae8c9078484b25963e15 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:01:16 +0100 Subject: [PATCH 167/300] Fix Pause Warp Enhancement (#4036) --- soh/soh/Enhancements/pausewarp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/pausewarp.c b/soh/soh/Enhancements/pausewarp.c index e0fd97e24..5538e7ad4 100644 --- a/soh/soh/Enhancements/pausewarp.c +++ b/soh/soh/Enhancements/pausewarp.c @@ -85,7 +85,8 @@ void PauseWarp_HandleSelection() { if (gSaveContext.inventory.items[SLOT_OCARINA] != ITEM_NONE) { int aButtonPressed = CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_A); int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST]; - if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE) { + if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE && + gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) { ActivateWarp(&gPlayState->pauseCtx, song); } } From 067782fa912fd2ca9b0c318292a2d9f5a4e40c74 Mon Sep 17 00:00:00 2001 From: Archez Date: Sat, 20 Apr 2024 11:03:41 -0400 Subject: [PATCH 168/300] clean up cmake configure files (#4002) --- .gitignore | 2 +- soh/CMakeLists.txt | 16 ++-------------- soh/{src/boot => }/properties.h.in | 0 soh/src/boot/build.c.in | 1 + 4 files changed, 4 insertions(+), 15 deletions(-) rename soh/{src/boot => }/properties.h.in (100%) diff --git a/.gitignore b/.gitignore index 3848a1bd8..09f29ab48 100644 --- a/.gitignore +++ b/.gitignore @@ -448,5 +448,5 @@ _packages */extract_assets_cmake* /build* -soh/build.c +soh/src/boot/build.c soh/properties.h diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index f653c5de5..4ed9fec72 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -105,8 +105,8 @@ set(PROJECT_NAME soh) ################################################################################ # Sources ################################################################################ -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c.in ${CMAKE_BINARY_DIR}/build.c @ONLY) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/properties.h.in ${CMAKE_CURRENT_SOURCE_DIR}/properties.h @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c.in ${CMAKE_CURRENT_SOURCE_DIR}/src/boot/build.c @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/properties.h.in ${CMAKE_CURRENT_SOURCE_DIR}/properties.h @ONLY) set(Header_Files "resource.h") source_group("headers" FILES ${Header_Files}) @@ -217,8 +217,6 @@ source_group("soh\\resource\\importer\\scenecommand" REGULAR_EXPRESSION "soh/res # src (decomp) {{{ file(GLOB_RECURSE src__ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.c" "src/*.h") -list(APPEND src__ ${CMAKE_BINARY_DIR}/build.c) -list(APPEND src__ ${CMAKE_CURRENT_SOURCE_DIR}/properties.h) list(APPEND src__ ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc) list(FILTER src__ EXCLUDE REGEX "src/dmadata/*") list(FILTER src__ EXCLUDE REGEX "src/elf_message/*") @@ -238,7 +236,6 @@ list(REMOVE_ITEM src__ "src/libultra/gu/sqrtf.c") list(REMOVE_ITEM src__ "src/libultra/gu/us2dex.c") source_group("src" REGULAR_EXPRESSION "src/*") -source_group("src\\build" FILES ${CMAKE_BINARY_DIR}/build.c ${CMAKE_CURRENT_SOURCE_DIR}/properties.h ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc) source_group("src\\boot" REGULAR_EXPRESSION "src/boot/*") source_group("src\\buffers" REGULAR_EXPRESSION "src/buffers/*") source_group("src\\code" REGULAR_EXPRESSION "src/code/*") @@ -650,15 +647,6 @@ endif() ################################################################################ # Pre build events ################################################################################ -if (CMAKE_SYSTEM_NAME STREQUAL "Windows") - add_custom_command_if( - TARGET ${PROJECT_NAME} - PRE_BUILD - COMMANDS - COMMAND $ copy /b $build.c +,, - ) -endif() - if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS") add_custom_command( TARGET ${PROJECT_NAME} diff --git a/soh/src/boot/properties.h.in b/soh/properties.h.in similarity index 100% rename from soh/src/boot/properties.h.in rename to soh/properties.h.in diff --git a/soh/src/boot/build.c.in b/soh/src/boot/build.c.in index 4fc6a17f4..4d6a07ce6 100644 --- a/soh/src/boot/build.c.in +++ b/soh/src/boot/build.c.in @@ -4,6 +4,7 @@ const char gBuildVersion[] = "@PROJECT_BUILD_NAME@ (@CMAKE_PROJECT_VERSION_MAJOR const u16 gBuildVersionMajor = @CMAKE_PROJECT_VERSION_MAJOR@; const u16 gBuildVersionMinor = @CMAKE_PROJECT_VERSION_MINOR@; const u16 gBuildVersionPatch = @CMAKE_PROJECT_VERSION_PATCH@; + const char gBuildTeam[] = "@PROJECT_TEAM@"; const char gBuildDate[] = __DATE__ " " __TIME__; const char gBuildMakeOption[] = ""; From e6798d98619f30af2639ed6afe094504b4a0875c Mon Sep 17 00:00:00 2001 From: Archez Date: Sat, 20 Apr 2024 11:04:11 -0400 Subject: [PATCH 169/300] bump lus and create fb call (#4060) --- libultraship | 2 +- soh/src/code/game.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libultraship b/libultraship index b135db823..26ecbc197 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968 +Subproject commit 26ecbc19784347773f750aa838190e45172b63e6 diff --git a/soh/src/code/game.c b/soh/src/code/game.c index b46aa4ebd..d7c2e5256 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -14,7 +14,7 @@ FaultClient sGameFaultClient; u16 sLastButtonPressed; // Forward declared, because this in a C++ header. -int gfx_create_framebuffer(uint32_t width, uint32_t height); +int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height, uint8_t resize); void gfx_texture_cache_clear(); @@ -247,7 +247,7 @@ void GameState_Update(GameState* gameState) { if (fbTest == -1) { - fbTest = gfx_create_framebuffer(64, 112); + fbTest = gfx_create_framebuffer(64, 112, SCREEN_WIDTH, SCREEN_HEIGHT, true); //fbTest = gfx_create_framebuffer(256, 512); } From 2accfc3c9b2be0a83a76662f217710ab3738d410 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sat, 20 Apr 2024 11:31:05 -0400 Subject: [PATCH 170/300] ci: bump macports version (#4039) --- .github/workflows/generate-builds.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 3e1c68852..96ae2f270 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -92,8 +92,8 @@ jobs: if [ -d /opt/local/ ]; then echo "MacPorts already installed" else - wget https://github.com/macports/macports-base/releases/download/v2.9.1/MacPorts-2.9.1-12-Monterey.pkg - sudo installer -pkg ./MacPorts-2.9.1-12-Monterey.pkg -target / + wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-12-Monterey.pkg + sudo installer -pkg ./MacPorts-2.9.3-12-Monterey.pkg -target / fi echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH - name: Install dependencies From 16bf03a9bda21aa4f96ceb0e2596d24961f0cc3b Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Sat, 20 Apr 2024 08:33:59 -0800 Subject: [PATCH 171/300] Add console commands for randomizing sfx and cosmetic groups (#3962) * Add console commands for randomizing sfx and cosmetic groups * Update naming and use constexpr * Update soh/soh/Enhancements/debugconsole.cpp --------- Co-authored-by: Archez --- soh/soh/Enhancements/audio/AudioCollection.h | 1 + soh/soh/Enhancements/audio/AudioEditor.cpp | 14 + soh/soh/Enhancements/audio/AudioEditor.h | 3 + .../cosmetics/CosmeticsEditor.cpp | 416 +++++++++--------- .../Enhancements/cosmetics/CosmeticsEditor.h | 25 ++ soh/soh/Enhancements/debugconsole.cpp | 86 +++- soh/soh/SohMenuBar.cpp | 16 +- 7 files changed, 338 insertions(+), 223 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioCollection.h b/soh/soh/Enhancements/audio/AudioCollection.h index 1d53777e7..f3fd964bc 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.h +++ b/soh/soh/Enhancements/audio/AudioCollection.h @@ -1,3 +1,4 @@ +#pragma once #ifdef __cplusplus #include #include diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index 8c0d415a3..68077a968 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -714,6 +714,13 @@ void AudioEditor_RandomizeAll() { ReplayCurrentBGM(); } +void AudioEditor_RandomizeGroup(SeqType group) { + RandomizeGroup(group); + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + ReplayCurrentBGM(); +} + void AudioEditor_ResetAll() { for (auto type : allTypes) { ResetGroup(AudioCollection::Instance->GetAllSequences(), type); @@ -723,6 +730,13 @@ void AudioEditor_ResetAll() { ReplayCurrentBGM(); } +void AudioEditor_ResetGroup(SeqType group) { + ResetGroup(AudioCollection::Instance->GetAllSequences(), group); + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + ReplayCurrentBGM(); +} + void AudioEditor_LockAll() { for (auto type : allTypes) { LockGroup(AudioCollection::Instance->GetAllSequences(), type); diff --git a/soh/soh/Enhancements/audio/AudioEditor.h b/soh/soh/Enhancements/audio/AudioEditor.h index 9cca94efe..38a681539 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.h +++ b/soh/soh/Enhancements/audio/AudioEditor.h @@ -8,6 +8,7 @@ #define IMGUI_DEFINE_MATH_OPERATORS #endif #include +#include "AudioCollection.h" class AudioEditor : public LUS::GuiWindow { public: @@ -20,7 +21,9 @@ class AudioEditor : public LUS::GuiWindow { }; void AudioEditor_RandomizeAll(); +void AudioEditor_RandomizeGroup(SeqType group); void AudioEditor_ResetAll(); +void AudioEditor_ResetGroup(SeqType group); void AudioEditor_LockAll(); void AudioEditor_UnlockAll(); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 4f04bc64b..52f319b3e 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -57,46 +57,24 @@ u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); #define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL" static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL; -// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize -// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor` -typedef enum { - GROUP_LINK, - GROUP_MIRRORSHIELD, - GROUP_SWORDS, - GROUP_GLOVES, - GROUP_EQUIPMENT, - GROUP_CONSUMABLE, - GROUP_HUD, - GROUP_KALEIDO, - GROUP_TITLE, - GROUP_NPC, - GROUP_WORLD, - GROUP_MAGIC, - GROUP_ARROWS, - GROUP_SPIN_ATTACK, - GROUP_TRAILS, - GROUP_NAVI, - GROUP_IVAN, -} CosmeticGroup; - std::map groupLabels = { - { GROUP_LINK, "Link" }, - { GROUP_MIRRORSHIELD, "Mirror Shield" }, - { GROUP_SWORDS, "Swords" }, - { GROUP_GLOVES, "Gloves" }, - { GROUP_EQUIPMENT, "Equipment" }, - { GROUP_CONSUMABLE, "Consumables" }, - { GROUP_HUD, "HUD" }, - { GROUP_KALEIDO, "Pause Menu" }, - { GROUP_TITLE, "Title Screen" }, - { GROUP_NPC, "NPCs" }, - { GROUP_WORLD, "World" }, - { GROUP_MAGIC, "Magic Effects" }, - { GROUP_ARROWS, "Arrow Effects" }, - { GROUP_SPIN_ATTACK, "Spin Attack" }, - { GROUP_TRAILS, "Trails" }, - { GROUP_NAVI, "Navi" }, - { GROUP_IVAN, "Ivan" } + { COSMETICS_GROUP_LINK, "Link" }, + { COSMETICS_GROUP_MIRRORSHIELD, "Mirror Shield" }, + { COSMETICS_GROUP_SWORDS, "Swords" }, + { COSMETICS_GROUP_GLOVES, "Gloves" }, + { COSMETICS_GROUP_EQUIPMENT, "Equipment" }, + { COSMETICS_GROUP_CONSUMABLE, "Consumables" }, + { COSMETICS_GROUP_HUD, "HUD" }, + { COSMETICS_GROUP_KALEIDO, "Pause Menu" }, + { COSMETICS_GROUP_TITLE, "Title Screen" }, + { COSMETICS_GROUP_NPC, "NPCs" }, + { COSMETICS_GROUP_WORLD, "World" }, + { COSMETICS_GROUP_MAGIC, "Magic Effects" }, + { COSMETICS_GROUP_ARROWS, "Arrow Effects" }, + { COSMETICS_GROUP_SPIN_ATTACK, "Spin Attack" }, + { COSMETICS_GROUP_TRAILS, "Trails" }, + { COSMETICS_GROUP_NAVI, "Navi" }, + { COSMETICS_GROUP_IVAN, "Ivan" } }; typedef struct { @@ -194,180 +172,180 @@ typedef struct { colors were darker than the gDPSetPrimColor. You will see many more examples of this below in the `ApplyOrResetCustomGfxPatches` method */ static std::map cosmeticOptions = { - COSMETIC_OPTION("Link_KokiriTunic", "Kokiri Tunic", GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), - COSMETIC_OPTION("Link_GoronTunic", "Goron Tunic", GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), - COSMETIC_OPTION("Link_ZoraTunic", "Zora Tunic", GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), - COSMETIC_OPTION("Link_Hair", "Hair", GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), - COSMETIC_OPTION("Link_Linen", "Linen", GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Link_Boots", "Boots", GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), + COSMETIC_OPTION("Link_KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), + COSMETIC_OPTION("Link_GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), + COSMETIC_OPTION("Link_ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("Link_Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), + COSMETIC_OPTION("Link_Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Link_Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), - COSMETIC_OPTION("MirrorShield_Body", "Body", GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), - COSMETIC_OPTION("MirrorShield_Mirror", "Mirror", GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("MirrorShield_Emblem", "Emblem", GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield_Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), + COSMETIC_OPTION("MirrorShield_Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield_Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), - COSMETIC_OPTION("Swords_KokiriBlade", "Kokiri Sword Blade", GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_KokiriHilt", "Kokiri Sword Hilt", GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords_MasterBlade", "Master Sword Blade", GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_MasterHilt", "Master Sword Hilt", GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords_BiggoronBlade", "Biggoron Sword Blade", GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_BiggoronHilt", "Biggoron Sword Hilt", GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords_KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords_KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords_MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords_MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords_BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords_BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Gloves_GoronBracelet", "Goron Bracelet", GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), - COSMETIC_OPTION("Gloves_SilverGauntlets", "Silver Gauntlets", GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Gloves_GoldenGauntlets", "Golden Gauntlets", GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), - COSMETIC_OPTION("Gloves_GauntletsGem", "Gauntlets Gem", GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), + COSMETIC_OPTION("Gloves_GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Gloves_SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Gloves_GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), + COSMETIC_OPTION("Gloves_GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), - COSMETIC_OPTION("Equipment_BoomerangBody", "Boomerang Body", GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Equipment_BoomerangGem", "Boomerang Gem", GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), - // COSMETIC_OPTION("Equipment_SlingshotBody", "Slingshot Body", GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Equipment_SlingshotString", "Slingshot String", GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_HammerHead", "Hammer Head", GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), - COSMETIC_OPTION("Equipment_HammerHandle", "Hammer Handle", GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), - // COSMETIC_OPTION("Equipment_HookshotChain", "Hookshot Chain", GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Equipment_HookshotTip", "Hookshot Tip", GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - COSMETIC_OPTION("HookshotReticle_Target", "Hookshotable Reticle", GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, false, false), - COSMETIC_OPTION("HookshotReticle_NonTarget", "Non-Hookshotable Reticle", GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, false, false), - COSMETIC_OPTION("Equipment_BowTips", "Bow Tips", GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Equipment_BowString", "Bow String", GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_BowBody", "Bow Body", GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), - COSMETIC_OPTION("Equipment_BowHandle", "Bow Handle", GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_ChuFace", "Bombchu Face", GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), - COSMETIC_OPTION("Equipment_ChuBody", "Bombchu Body", GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), - COSMETIC_OPTION("Equipment_BunnyHood", "Bunny Hood", GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), + COSMETIC_OPTION("Equipment_BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment_BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), + // COSMETIC_OPTION("Equipment_SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Equipment_SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment_HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), + COSMETIC_OPTION("Equipment_HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), + // COSMETIC_OPTION("Equipment_HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Equipment_HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement + COSMETIC_OPTION("HookshotReticle_Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, false, false), + COSMETIC_OPTION("HookshotReticle_NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, false, false), + COSMETIC_OPTION("Equipment_BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment_BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment_BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), + COSMETIC_OPTION("Equipment_BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment_ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), + COSMETIC_OPTION("Equipment_ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), + COSMETIC_OPTION("Equipment_BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), - COSMETIC_OPTION("Consumable_Hearts", "Hearts", GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), - COSMETIC_OPTION("Consumable_HeartBorder", "Heart Border", GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), - COSMETIC_OPTION("Consumable_DDHearts", "DD Hearts", GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable_DDHeartBorder", "DD Heart Border", GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_Magic", "Magic", GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable_MagicActive", "Magic Active", GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), - COSMETIC_OPTION("Consumable_MagicBorder", "Magic Border", GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable_MagicBorderActive", "Magic Border Active", GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable_GreenRupee", "Green Rupee", GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable_BlueRupee", "Blue Rupee", GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_RedRupee", "Red Rupee", GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable_PurpleRupee", "Purple Rupee", GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_GoldRupee", "Gold Rupee", GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), - COSMETIC_OPTION("Consumable_SilverRupee", "Silver Rupee", GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable_Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), + COSMETIC_OPTION("Consumable_HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), + COSMETIC_OPTION("Consumable_DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable_DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable_Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable_MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable_MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), + COSMETIC_OPTION("Consumable_MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), + COSMETIC_OPTION("Consumable_GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable_BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable_RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable_PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable_GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), + COSMETIC_OPTION("Consumable_SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_AButton", "A Button", GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_BButton", "B Button", GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_CButtons", "C Buttons", GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_CUpButton", "C Up Button", GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CDownButton", "C Down Button", GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CLeftButton", "C Left Button", GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CRightButton", "C Right Button", GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_StartButton", "Start Button", GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_Dpad", "Dpad", GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_KeyCount", "Key Count", GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_StoneOfAgony", "Stone of Agony", GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_Minimap", "Minimap", GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_MinimapPosition", "Minimap Position", GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_MinimapEntrance", "Minimap Entrance", GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_EnemyHealthBar", "Enemy Health Bar", GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), - COSMETIC_OPTION("Hud_EnemyHealthBorder", "Enemy Health Border", GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), - COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), + COSMETIC_OPTION("Hud_AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), + COSMETIC_OPTION("Hud_BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), + COSMETIC_OPTION("Hud_CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), + COSMETIC_OPTION("Hud_CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Hud_Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Hud_KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), + COSMETIC_OPTION("Hud_StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Hud_Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Hud_MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Hud_EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), + COSMETIC_OPTION("Hud_EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), + COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), - COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), - COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color", GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), - COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusA", "Quest Status Color", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_QuestStatusB", "Quest Status Color B", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusC", "Quest Status Color C", GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusD", "Quest Status Color D", GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), + COSMETIC_OPTION("Kal_QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kal_QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kal_QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectA", "Map Color", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveA", "Save Color", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_SaveB", "Save Color B", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveC", "Save Color C", GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveD", "Save Color D", GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Kal_SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kal_SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kal_SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kal_SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Kal_NamePanel", "Name Panel", GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), + COSMETIC_OPTION("Kal_NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), - COSMETIC_OPTION("Title_FileChoose", "File Choose", GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoBlue", "N64 Blue", GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoGreen", "N64 Green", GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoYellow", "N64 Yellow", GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), - // COSMETIC_OPTION("Title_FirePrimary", "Title Fire Primary", GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), // Todo (Cosmetics): Kinda complicated - // COSMETIC_OPTION("Title_FireSecondary", "Title Fire Secondary", GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), // Todo (Cosmetics): Kinda complicated + COSMETIC_OPTION("Title_FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), + COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Title_N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), + COSMETIC_OPTION("Title_N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Title_N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), + // COSMETIC_OPTION("Title_FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), // Todo (Cosmetics): Kinda complicated + // COSMETIC_OPTION("Title_FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), // Todo (Cosmetics): Kinda complicated - COSMETIC_OPTION("Arrows_NormalPrimary", "Normal Primary", GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows_NormalSecondary", "Normal Secondary", GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("Arrows_FirePrimary", "Fire Primary", GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows_FireSecondary", "Fire Secondary", GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Arrows_IcePrimary", "Ice Primary", GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), - COSMETIC_OPTION("Arrows_IceSecondary", "Ice Secondary", GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Arrows_LightPrimary", "Light Primary", GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Arrows_LightSecondary", "Light Secondary", GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), + COSMETIC_OPTION("Arrows_NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows_NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("Arrows_FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows_FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Arrows_IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), + COSMETIC_OPTION("Arrows_IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Arrows_LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Arrows_LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), - // COSMETIC_OPTION("Magic_DinsPrimary", "Din's Primary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gDF_Col - // COSMETIC_OPTION("Magic_DinsSecondary", "Din's Secondary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gDF_Env - // COSMETIC_OPTION("Magic_FaroresPrimary", "Farore's Primary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic_FaroresSecondary", "Farore's Secondary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic_NayrusPrimary", "Nayru's Primary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gNL_Diamond_Col / gNL_Orb_Col - // COSMETIC_OPTION("Magic_NayrusSecondary", "Nayru's Secondary", GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gNL_Diamond_Env / gNL_Orb_Env + // COSMETIC_OPTION("Magic_DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gDF_Col + // COSMETIC_OPTION("Magic_DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gDF_Env + // COSMETIC_OPTION("Magic_FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Magic_FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Magic_NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gNL_Diamond_Col / gNL_Orb_Col + // COSMETIC_OPTION("Magic_NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gNL_Diamond_Env / gNL_Orb_Env - COSMETIC_OPTION("SpinAttack_Level1Primary", "Level 1 Primary", GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), - COSMETIC_OPTION("SpinAttack_Level1Secondary", "Level 1 Secondary", GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), - COSMETIC_OPTION("SpinAttack_Level2Primary", "Level 2 Primary", GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("SpinAttack_Level2Secondary", "Level 2 Secondary", GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), + COSMETIC_OPTION("SpinAttack_Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), + COSMETIC_OPTION("SpinAttack_Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), + COSMETIC_OPTION("SpinAttack_Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("SpinAttack_Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Trails_Bombchu", "Bombchu", GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Trails_Boomerang", "Boomerang", GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), - COSMETIC_OPTION("Trails_KokiriSword", "Kokiri Sword", GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails_MasterSword", "Master Sword", GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails_BiggoronSword", "Biggoron Sword", GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails_Stick", "Stick", GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails_Hammer", "Hammer", GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails_Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Trails_Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), + COSMETIC_OPTION("Trails_KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails_MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails_BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails_Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails_Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World_BlockOfTime", "Block of Time", GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World_Moon", "Moon", GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), - COSMETIC_OPTION("World_GossipStone", "Gossip Stone", GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), - COSMETIC_OPTION("World_RedIce", "Red Ice", GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World_BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("World_Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), + COSMETIC_OPTION("World_GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), + COSMETIC_OPTION("World_RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_IdlePrimary", "Idle Primary", GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Navi_IdleSecondary", "Idle Secondary", GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), - COSMETIC_OPTION("Navi_NPCPrimary", "NPC Primary", GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Navi_NPCSecondary", "NPC Secondary", GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), - COSMETIC_OPTION("Navi_EnemyPrimary", "Enemy Primary", GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_EnemySecondary", "Enemy Secondary", GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), - COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + COSMETIC_OPTION("Navi_IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Navi_IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), + COSMETIC_OPTION("Navi_NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Navi_NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), + COSMETIC_OPTION("Navi_EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi_EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), + COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), - COSMETIC_OPTION("Ivan_IdlePrimary", "Ivan Idle Primary", GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Ivan_IdleSecondary", "Ivan Idle Secondary", GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Ivan_IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Ivan_IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), - COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC_IceKeesePrimary", "Ice Keese Primary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_IceKeeseSecondary", "Ice Keese Secondary", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC_IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC_IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Health fairy - COSMETIC_OPTION("NPC_Dog1", "Dog 1", GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), - COSMETIC_OPTION("NPC_Dog2", "Dog 2", GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), - COSMETIC_OPTION("NPC_GoldenSkulltula", "Golden Skulltula", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_Kokiri", "Kokiri", GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), - COSMETIC_OPTION("NPC_Gerudo", "Gerudo", GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), - COSMETIC_OPTION("NPC_MetalTrap", "Metal Trap", GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC_IronKnuckles", "Iron Knuckles", GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), + COSMETIC_OPTION("NPC_Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), + COSMETIC_OPTION("NPC_Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), + COSMETIC_OPTION("NPC_GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC_Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), + COSMETIC_OPTION("NPC_Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), + COSMETIC_OPTION("NPC_MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC_IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), }; static const char* MarginCvarList[] { @@ -1778,19 +1756,19 @@ void CosmeticsEditorWindow::DrawElement() { if (ImGui::BeginTabBar("CosmeticsContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Link & Items")) { - DrawCosmeticGroup(GROUP_LINK); - DrawCosmeticGroup(GROUP_GLOVES); - DrawCosmeticGroup(GROUP_MIRRORSHIELD); - DrawCosmeticGroup(GROUP_EQUIPMENT); - DrawCosmeticGroup(GROUP_SWORDS); - DrawCosmeticGroup(GROUP_CONSUMABLE); + DrawCosmeticGroup(COSMETICS_GROUP_LINK); + DrawCosmeticGroup(COSMETICS_GROUP_GLOVES); + DrawCosmeticGroup(COSMETICS_GROUP_MIRRORSHIELD); + DrawCosmeticGroup(COSMETICS_GROUP_EQUIPMENT); + DrawCosmeticGroup(COSMETICS_GROUP_SWORDS); + DrawCosmeticGroup(COSMETICS_GROUP_CONSUMABLE); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Effects")) { - // DrawCosmeticGroup(GROUP_MAGIC); // Cosmetics TODO: Implement magic effect colors - DrawCosmeticGroup(GROUP_ARROWS); - DrawCosmeticGroup(GROUP_SPIN_ATTACK); - DrawCosmeticGroup(GROUP_TRAILS); + // DrawCosmeticGroup(COSMETICS_GROUP_MAGIC); // Cosmetics TODO: Implement magic effect colors + DrawCosmeticGroup(COSMETICS_GROUP_ARROWS); + DrawCosmeticGroup(COSMETICS_GROUP_SPIN_ATTACK); + DrawCosmeticGroup(COSMETICS_GROUP_TRAILS); if (UIWidgets::EnhancementSliderInt("Trails Duration: %d", "##Trails_Duration", "gCosmetics.Trails_Duration.Value", 2, 20, "", 4)) { CVarSetInteger("gCosmetics.Trails_Duration.Changed", 1); } @@ -1803,10 +1781,10 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem("World & NPCs")) { - DrawCosmeticGroup(GROUP_WORLD); - DrawCosmeticGroup(GROUP_NAVI); - DrawCosmeticGroup(GROUP_IVAN); - DrawCosmeticGroup(GROUP_NPC); + DrawCosmeticGroup(COSMETICS_GROUP_WORLD); + DrawCosmeticGroup(COSMETICS_GROUP_NAVI); + DrawCosmeticGroup(COSMETICS_GROUP_IVAN); + DrawCosmeticGroup(COSMETICS_GROUP_NPC); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Silly")) { @@ -1814,8 +1792,8 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem("HUD")) { - DrawCosmeticGroup(GROUP_HUD); - DrawCosmeticGroup(GROUP_TITLE); + DrawCosmeticGroup(COSMETICS_GROUP_HUD); + DrawCosmeticGroup(COSMETICS_GROUP_TITLE); ImGui::EndTabItem(); } @@ -1825,7 +1803,7 @@ void CosmeticsEditorWindow::DrawElement() { } if (ImGui::BeginTabItem("Pause Menu")) { - DrawCosmeticGroup(GROUP_KALEIDO); + DrawCosmeticGroup(COSMETICS_GROUP_KALEIDO); ImGui::EndTabItem(); } ImGui::EndTabBar(); @@ -1885,6 +1863,19 @@ void CosmeticsEditor_RandomizeAll() { ApplyOrResetCustomGfxPatches(); } +void CosmeticsEditor_RandomizeGroup(CosmeticGroup group) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && + (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) && + cosmeticOption.group == group) { + RandomizeColor(cosmeticOption); + } + } + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + ApplyOrResetCustomGfxPatches(); +} + void CosmeticsEditor_ResetAll() { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (!CVarGetInteger(cosmeticOption.lockedCvar, 0)) { @@ -1895,3 +1886,14 @@ void CosmeticsEditor_ResetAll() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } + +void CosmeticsEditor_ResetGroup(CosmeticGroup group) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && cosmeticOption.group == group) { + ResetColor(cosmeticOption); + } + } + + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + ApplyOrResetCustomGfxPatches(); +} diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index b22a51ba7..9599a521f 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -8,6 +8,29 @@ ResourceMgr_UnpatchGfxByName(path, name); \ } +// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize +// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor` +typedef enum { + COSMETICS_GROUP_LINK, + COSMETICS_GROUP_MIRRORSHIELD, + COSMETICS_GROUP_SWORDS, + COSMETICS_GROUP_GLOVES, + COSMETICS_GROUP_EQUIPMENT, + COSMETICS_GROUP_CONSUMABLE, + COSMETICS_GROUP_HUD, + COSMETICS_GROUP_KALEIDO, + COSMETICS_GROUP_TITLE, + COSMETICS_GROUP_NPC, + COSMETICS_GROUP_WORLD, + COSMETICS_GROUP_MAGIC, + COSMETICS_GROUP_ARROWS, + COSMETICS_GROUP_SPIN_ATTACK, + COSMETICS_GROUP_TRAILS, + COSMETICS_GROUP_NAVI, + COSMETICS_GROUP_IVAN, + COSMETICS_GROUP_MAX +} CosmeticGroup; + typedef struct { const std::string Name; const std::string ToolTip; @@ -26,7 +49,9 @@ static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | Im void InitCosmeticsEditor();//Init the menu itself ImVec4 GetRandomValue(int MaximumPossible); void CosmeticsEditor_RandomizeAll(); +void CosmeticsEditor_RandomizeGroup(CosmeticGroup group); void CosmeticsEditor_ResetAll(); +void CosmeticsEditor_ResetGroup(CosmeticGroup group); void ApplyOrResetCustomGfxPatches(bool manualChange = true); class CosmeticsEditorWindow : public LUS::GuiWindow { diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 2c910a067..bbf72a6d3 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1289,6 +1289,26 @@ static bool GenerateRandoHandler(std::shared_ptr Console, const st return 1; } +static constexpr std::array, COSMETICS_GROUP_MAX> cosmetic_groups = {{ + {"link", COSMETICS_GROUP_LINK}, + {"mirror_shield", COSMETICS_GROUP_MIRRORSHIELD}, + {"swords", COSMETICS_GROUP_SWORDS}, + {"gloves", COSMETICS_GROUP_GLOVES}, + {"equipment", COSMETICS_GROUP_EQUIPMENT}, + {"consumable", COSMETICS_GROUP_CONSUMABLE}, + {"hud", COSMETICS_GROUP_HUD}, + {"kaleido", COSMETICS_GROUP_KALEIDO}, + {"title", COSMETICS_GROUP_TITLE}, + {"npc", COSMETICS_GROUP_NPC}, + {"world", COSMETICS_GROUP_WORLD}, + {"magic", COSMETICS_GROUP_MAGIC}, + {"arrows", COSMETICS_GROUP_ARROWS}, + {"spin_attack", COSMETICS_GROUP_SPIN_ATTACK}, + {"trials", COSMETICS_GROUP_TRAILS}, + {"navi", COSMETICS_GROUP_NAVI}, + {"ivan", COSMETICS_GROUP_IVAN}, +}}; + static bool CosmeticsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); @@ -1296,9 +1316,31 @@ static bool CosmeticsHandler(std::shared_ptr Console, const std::v } if (args[1].compare("reset") == 0) { - CosmeticsEditor_ResetAll(); + if (args.size() == 2) { + CosmeticsEditor_ResetAll(); + } else { + for (const auto& [key, value] : cosmetic_groups) { + if (args[2].compare(key) == 0) { + CosmeticsEditor_ResetGroup(value); + return 0; + } + } + ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name"); + return 1; + } } else if (args[1].compare("randomize") == 0) { - CosmeticsEditor_RandomizeAll(); + if (args.size() == 2) { + CosmeticsEditor_RandomizeAll(); + } else { + for (const auto& [key, value] : cosmetic_groups) { + if (args[2].compare(key) == 0) { + CosmeticsEditor_RandomizeGroup(value); + return 0; + } + } + ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name"); + return 1; + } } else { ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'"); return 1; @@ -1307,6 +1349,18 @@ static bool CosmeticsHandler(std::shared_ptr Console, const std::v return 0; } +static std::map sfx_groups = { + {"bgm", SEQ_BGM_WORLD}, + {"fanfares", SEQ_FANFARE}, + {"events", SEQ_BGM_EVENT}, + {"battle", SEQ_BGM_BATTLE}, + {"ocarina", SEQ_OCARINA}, + {"instruments", SEQ_INSTRUMENT}, + {"sfx", SEQ_SFX}, + {"voices", SEQ_VOICE}, + {"custom", SEQ_BGM_CUSTOM}, +}; + static bool SfxHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); @@ -1314,9 +1368,31 @@ static bool SfxHandler(std::shared_ptr Console, const std::vector< } if (args[1].compare("reset") == 0) { - AudioEditor_ResetAll(); + if (args.size() == 2) { + AudioEditor_ResetAll(); + } else { + for (const auto& [key, value] : sfx_groups) { + if (args[2].compare(key) == 0) { + AudioEditor_ResetGroup(value); + return 0; + } + } + ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name"); + return 1; + } } else if (args[1].compare("randomize") == 0) { - AudioEditor_RandomizeAll(); + if (args.size() == 2) { + AudioEditor_RandomizeAll(); + } else { + for (const auto& [key, value] : sfx_groups) { + if (args[2].compare(key) == 0) { + AudioEditor_RandomizeGroup(value); + return 0; + } + } + ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name"); + return 1; + } } else { ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'"); return 1; @@ -1506,10 +1582,12 @@ void DebugConsole_Init(void) { CMD_REGISTER("cosmetics", {CosmeticsHandler, "Change cosmetics.", { {"reset|randomize", LUS::ArgumentType::TEXT}, + {"group name", LUS::ArgumentType::TEXT, true}, }}); CMD_REGISTER("sfx", {SfxHandler, "Change SFX.", { {"reset|randomize", LUS::ArgumentType::TEXT}, + {"group_name", LUS::ArgumentType::TEXT, true}, }}); CVarSave(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 9adbabadf..23aa82362 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -41,14 +41,6 @@ extern bool isBetaQuestEnabled; extern "C" PlayState* gPlayState; -enum SeqPlayers { - /* 0 */ SEQ_BGM_MAIN, - /* 1 */ SEQ_FANFARE, - /* 2 */ SEQ_SFX, - /* 3 */ SEQ_BGM_SUB, - /* 4 */ SEQ_MAX -}; - std::string GetWindowButtonText(const char* text, bool menuOpen) { char buttonText[100] = ""; if (menuOpen) { @@ -192,16 +184,16 @@ void DrawSettingsMenu() { if (ImGui::BeginMenu("Audio")) { UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %.1f %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true); if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %.1f %%", "##Main_Music_Vol", "gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); } if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %.1f %%", "##Sub_Music_Vol", "gSubMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); } if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %.1f %%", "##Sound_Effect_Vol", "gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); } if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %.1f %%", "##Fanfare_Vol", "gFanfareVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); } static std::unordered_map audioBackendNames = { From 694a876a7045a8a0b4a69d6aae0510b6dcef86db Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sat, 20 Apr 2024 11:34:02 -0700 Subject: [PATCH 172/300] Step 2 of CVar macro/sectionalizing: Trackers/Windows (#3238) * Add all macros. Replace all randomizer seed setting CVars with appropriate macro. Cleaned up non-gameplay-critical things that are part of Spock Race rando presets (like RTA timing, displaying timer, displaying the glitch lineup tick, or Fast File Select). * Wrong slash... * Fix DEVELOPER_CVAR macro. Add GENERAL_CVAR macro. * Change Item Tracker CVars, including open window CVar. * Swapped open window CVars. * Swapped Entrance Tracker CVars. * Swapped Check Tracker CVars. Changed Item Tracker "HudEditMode" to "Draggable". * Renamed `RANDOMIZER_CVAR` to `RANDO_ENHANCEMENT_CVAR`. Swapped rando enhancement CVars. * Mirroring last commit from part 1 in randomizer.cpp * Another mirror from pt 1 --- soh/soh/Enhancements/controls/InputViewer.cpp | 3 +- soh/soh/Enhancements/presets.h | 14 +- soh/soh/Enhancements/randomizer/draw.cpp | 4 +- .../randomizer/randomizer_check_tracker.cpp | 186 +++++++-------- .../randomizer_entrance_tracker.cpp | 44 ++-- .../randomizer/randomizer_item_tracker.cpp | 220 +++++++++--------- soh/soh/OTRGlobals.cpp | 4 +- soh/soh/OTRGlobals.h | 5 +- soh/soh/SohGui.cpp | 36 +-- soh/soh/SohMenuBar.cpp | 44 ++-- soh/src/code/code_800EC960.c | 2 +- 11 files changed, 282 insertions(+), 280 deletions(-) diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 6b25589c6..084383bbd 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -3,6 +3,7 @@ #include "public/bridge/consolevariablebridge.h" #include "libultraship/libultra/controller.h" #include "Context.h" +#include "soh/OTRGlobals.h" #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif @@ -59,7 +60,7 @@ void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTex } void InputViewer::DrawElement() { - if (CVarGetInteger("gOpenWindows.InputViewer", 0)) { + if (CVarGetInteger(WINDOW_CVAR("InputViewer"), 0)) { static bool sButtonTexturesLoaded = false; if (!sButtonTexturesLoaded) { LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index d0b7a05f4..820873381 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -283,10 +283,10 @@ const std::vector enhancementsCvars = { const std::vector cheatCvars = { "gConsoleEnabled", - "gActorViewerEnabled", - "gCollisionViewerEnabled", - "gDLViewerEnabled", - "gSaveEditorEnabled", + WINDOW_CVAR("ActorViewer"), + WINDOW_CVAR("CollisionViewer"), + WINDOW_CVAR("DLViewer"), + WINDOW_CVAR("SaveEditor"), "gEnableWalkModify", "gWalkSpeedToggle", "gWalkModifierOne", @@ -485,10 +485,10 @@ const std::vector randomizerCvars = { RANDOMIZER_SEED_CVAR("TriforceHunt"), RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), RANDOMIZER_SEED_CVAR("SariaHint"), - "gRandomizeRupeeNames", + RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), RANDOMIZER_SEED_CVAR("FrogsHint"), - "gRandoRelevantNavi", - "gRandoQuestItemFanfares", + RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), + RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), }; const std::vector vanillaPlusPresetEntries = { diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 570ac5801..d957778fc 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -24,7 +24,7 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GERUDO_FORTRESS_SMALL_KEY ? Randomizer_GetSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA : DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY); - s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger("gRandoMatchKeyColors", 1); + s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), 1); s16 color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_SMALL_KEY; s16 colors[9][3] = { { 4, 195, 46 }, // Forest Temple @@ -63,7 +63,7 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GANONS_CASTLE_BOSS_KEY ? DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY) : DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY); - s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger("gRandoMatchKeyColors", 1); + s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), 1); s16 color_slot; color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY; s16 colors[6][3] = { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 917e93a11..d991c464f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -869,14 +869,14 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { void CheckTrackerWindow::DrawElement() { ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver); - if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { - if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { + if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(CHECK_TRACKER_CVAR("ShowOnlyPaused"), 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { return; } - if (CVarGetInteger("gCheckTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - int comboButton1Mask = buttons[CVarGetInteger("gCheckTrackerComboButton1", TRACKER_COMBO_BUTTON_L)]; - int comboButton2Mask = buttons[CVarGetInteger("gCheckTrackerComboButton2", TRACKER_COMBO_BUTTON_R)]; + if (CVarGetInteger(CHECK_TRACKER_CVAR("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + int comboButton1Mask = buttons[CVarGetInteger(CHECK_TRACKER_CVAR("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; + int comboButton2Mask = buttons[CVarGetInteger(CHECK_TRACKER_CVAR("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; OSContPad* trackerButtonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = trackerButtonsPressed != nullptr && trackerButtonsPressed[0].button & comboButton1Mask && @@ -916,7 +916,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::TableNextRow(0, headerHeight); ImGui::TableNextColumn(); UIWidgets::EnhancementCheckbox( - "Show Hidden Items", "gCheckTrackerOptionShowHidden", false, + "Show Hidden Items", CHECK_TRACKER_CVAR("ShowHidden"), false, "When active, items will show hidden checks by default when updated to this state."); UIWidgets::PaddedSeparator(); if (ImGui::Button("Expand All")) { @@ -955,17 +955,17 @@ void CheckTrackerWindow::DrawElement() { RainbowTick(); bool doDraw = false; bool thisAreaFullyChecked = false; - bool showHidden = CVarGetInteger("gCheckTrackerOptionShowHidden", 0); - bool hideIncomplete = CVarGetInteger("gCheckTrackerAreaIncompleteHide", 0); - bool hideComplete = CVarGetInteger("gCheckTrackerAreaCompleteHide", 0); + bool showHidden = CVarGetInteger(CHECK_TRACKER_CVAR("ShowHidden"), 0); + bool hideIncomplete = CVarGetInteger(CHECK_TRACKER_CVAR("AreaIncomplete.Hide"), 0); + bool hideComplete = CVarGetInteger(CHECK_TRACKER_CVAR("AreaComplete.Hide"), 0); bool collapseLogic; bool doingCollapseOrExpand = optExpandAll || optCollapseAll; bool isThisAreaSpoiled; RandomizerCheckArea lastArea = RCAREA_INVALID; - Color_RGBA8 areaCompleteColor = CVarGetColor("gCheckTrackerAreaMainCompleteColor", Color_Main_Default); - Color_RGBA8 areaIncompleteColor = CVarGetColor("gCheckTrackerAreaMainIncompleteColor", Color_Main_Default); - Color_RGBA8 extraCompleteColor = CVarGetColor("gCheckTrackerAreaExtraCompleteColor", Color_Area_Complete_Extra_Default); - Color_RGBA8 extraIncompleteColor = CVarGetColor("gCheckTrackerAreaExtraIncompleteColor", Color_Area_Incomplete_Extra_Default); + Color_RGBA8 areaCompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.MainColor"), Color_Main_Default); + Color_RGBA8 areaIncompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), Color_Main_Default); + Color_RGBA8 extraCompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); + Color_RGBA8 extraIncompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string stemp; @@ -1020,7 +1020,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f)); - isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0); + isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger(CHECK_TRACKER_CVAR("MQSpoilers"), 0); if (isThisAreaSpoiled) { if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { @@ -1098,12 +1098,12 @@ void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flag ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NoFocusOnAppearing; } - if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar; - if (!CVarGetInteger("gCheckTrackerHudEditMode", 0)) { + if (!CVarGetInteger(CHECK_TRACKER_CVAR("Draggable"), 0)) { windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; } } @@ -1363,52 +1363,52 @@ void DrawLocation(RandomizerCheckObject rcObj) { Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string txt; - bool showHidden = CVarGetInteger("gCheckTrackerOptionShowHidden", 0); + bool showHidden = CVarGetInteger(CHECK_TRACKER_CVAR("ShowHidden"), 0); RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rcObj.rc]; RandomizerCheckStatus status = checkData.status; bool skipped = checkData.skipped; if (status == RCSHOW_COLLECTED) { - if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Collected.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default) : - CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Collected.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default); } else if (status == RCSHOW_SAVED) { - if (!showHidden && CVarGetInteger("gCheckTrackerSavedHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Saved.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default) : - CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Saved.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default); } else if (skipped) { - if (!showHidden && CVarGetInteger("gCheckTrackerSkippedHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Skipped.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default) : - CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Skipped.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default); } else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) { - if (!showHidden && CVarGetInteger("gCheckTrackerSeenHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Seen.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default) : - CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Seen.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default); } else if (status == RCSHOW_SCUMMED) { - if (!showHidden && CVarGetInteger("gCheckTrackerScummedHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Scummed.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default) : - CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Scummed.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default); } else if (status == RCSHOW_UNCHECKED) { - if (!showHidden && CVarGetInteger("gCheckTrackerUncheckedHide", 0)) { + if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Unchecked.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default) : - CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default); - extraColor = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default) : + CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); } //Main Text @@ -1503,15 +1503,15 @@ void DrawLocation(RandomizerCheckObject rcObj) { } static std::set rainbowCVars = { - "gCheckTrackerAreaMainIncompleteColor", "gCheckTrackerAreaExtraIncompleteColor", - "gCheckTrackerAreaMainCompleteColor", "gCheckTrackerAreaExtraCompleteColor", - "gCheckTrackerUncheckedMainColor", "gCheckTrackerUncheckedExtraColor", - "gCheckTrackerSkippedMainColor", "gCheckTrackerSkippedExtraColor", - "gCheckTrackerSeenMainColor", "gCheckTrackerSeenExtraColor", - "gCheckTrackerHintedMainColor", "gCheckTrackerHintedExtraColor", - "gCheckTrackerCollectedMainColor", "gCheckTrackerCollectedExtraColor", - "gCheckTrackerScummedMainColor", "gCheckTrackerScummedExtraColor", - "gCheckTrackerSavedMainColor", "gCheckTrackerSavedExtraColor", + CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), + CHECK_TRACKER_CVAR("AreaComplete.MainColor"), CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), + CHECK_TRACKER_CVAR("Unchecked.MainColor"), CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), + CHECK_TRACKER_CVAR("Skipped.MainColor"), CHECK_TRACKER_CVAR("Skipped.ExtraColor"), + CHECK_TRACKER_CVAR("Seen.MainColor"), CHECK_TRACKER_CVAR("Seen.ExtraColor"), + CHECK_TRACKER_CVAR("Hinted.MainColor"), CHECK_TRACKER_CVAR("Hinted.ExtraColor"), + CHECK_TRACKER_CVAR("Collected.MainColor"), CHECK_TRACKER_CVAR("Collected.ExtraColor"), + CHECK_TRACKER_CVAR("Scummed.MainColor"), CHECK_TRACKER_CVAR("Scummed.ExtraColor"), + CHECK_TRACKER_CVAR("Saved.MainColor"), CHECK_TRACKER_CVAR("Saved.ExtraColor"), }; int hue = 0; @@ -1606,33 +1606,33 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - if (UIWidgets::EnhancementColor("BG Color", "gCheckTrackerBgColor", + if (UIWidgets::EnhancementColor("BG Color", CHECK_TRACKER_CVAR("BgColor"), ImVec4(Color_Background.r, Color_Background.g, Color_Background.b, Color_Background.a), ImVec4(Color_Bg_Default.r, Color_Bg_Default.g, Color_Bg_Default.b, Color_Bg_Default.a), false, true)) { - Color_Background = CVarGetColor("gCheckTrackerBgColor", Color_Bg_Default); + Color_Background = CVarGetColor(CHECK_TRACKER_CVAR("BgColor"), Color_Bg_Default); } ImGui::PopItemWidth(); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", "gCheckTrackerWindowType", windowType, TRACKER_WINDOW_WINDOW); - if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { - UIWidgets::EnhancementCheckbox("Enable Dragging", "gCheckTrackerHudEditMode"); - UIWidgets::EnhancementCheckbox("Only enable while paused", "gCheckTrackerShowOnlyPaused"); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", "gCheckTrackerDisplayType", displayType, 0); - if (CVarGetInteger("gCheckTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", "gCheckTrackerComboButton1", buttonStrings, TRACKER_COMBO_BUTTON_L); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", "gCheckTrackerComboButton2", buttonStrings, TRACKER_COMBO_BUTTON_R); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CHECK_TRACKER_CVAR("WindowType"), windowType, TRACKER_WINDOW_WINDOW); + if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + UIWidgets::EnhancementCheckbox("Enable Dragging", CHECK_TRACKER_CVAR("Draggable")); + UIWidgets::EnhancementCheckbox("Only enable while paused", CHECK_TRACKER_CVAR("ShowOnlyPaused")); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CHECK_TRACKER_CVAR("DisplayType"), displayType, 0); + if (CVarGetInteger(CHECK_TRACKER_CVAR("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CHECK_TRACKER_CVAR("ComboButton1"), buttonStrings, TRACKER_COMBO_BUTTON_L); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CHECK_TRACKER_CVAR("ComboButton2"), buttonStrings, TRACKER_COMBO_BUTTON_R); } } - UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", "gCheckTrackerOptionMQSpoilers"); + UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", CHECK_TRACKER_CVAR("MQSpoilers")); UIWidgets::Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked."); - if (UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", "gCheckTrackerOptionHideRightShopChecks", false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", CHECK_TRACKER_CVAR("HideRightShopChecks"), false, "", UIWidgets::CheckboxGraphics::Cross, true)) { hideShopRightChecks = !hideShopRightChecks; RecalculateAreaTotals(); } UIWidgets::Tooltip("If enabled, will prevent the tracker from displaying slots 1-4 in all shops."); - if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", "gCheckTrackerOptionAlwaysShowGSLocs", false, "")) { + if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", CHECK_TRACKER_CVAR("AlwaysShowGSLocs"), false, "")) { alwaysShowGS = !alwaysShowGS; RecalculateAreaTotals(); } @@ -1645,15 +1645,15 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableNextColumn(); - CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", "gCheckTrackerAreaMainIncompleteColor", "gCheckTrackerAreaExtraIncompleteColor", Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, "gCheckTrackerAreaIncompleteHide", ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", "gCheckTrackerAreaMainCompleteColor", "gCheckTrackerAreaExtraCompleteColor", Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, "gCheckTrackerAreaCompleteHide", ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", "gCheckTrackerUncheckedMainColor", "gCheckTrackerUncheckedExtraColor", Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, "gCheckTrackerUncheckedHide", "Checks you have not interacted with at all."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", "gCheckTrackerSkippedMainColor", "gCheckTrackerSkippedExtraColor", Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, "gCheckTrackerSkippedHide", ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", "gCheckTrackerSeenMainColor", "gCheckTrackerSeenExtraColor", Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, "gCheckTrackerSeenHide", "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", "gCheckTrackerScummedMainColor", "gCheckTrackerScummedExtraColor", Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, "gCheckTrackerScummedHide", "Checks you collect, but then reload before saving so you no longer have them."); - //CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", "gCheckTrackerHintedMainColor", "gCheckTrackerHintedExtraColor", Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, "gCheckTrackerHintedHide", ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", "gCheckTrackerCollectedMainColor", "gCheckTrackerCollectedExtraColor", Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, "gCheckTrackerCollectedHide", "Checks you have collected without saving or reloading yet."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", "gCheckTrackerSavedMainColor", "gCheckTrackerSavedExtraColor", Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, "gCheckTrackerSavedHide", "Checks that you saved the game while having collected."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, CHECK_TRACKER_CVAR("AreaIncomplete.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", CHECK_TRACKER_CVAR("AreaComplete.MainColor"), CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, CHECK_TRACKER_CVAR("AreaComplete.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CHECK_TRACKER_CVAR("Unchecked.MainColor"), CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CHECK_TRACKER_CVAR("Unchecked.Hide"), "Checks you have not interacted with at all."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CHECK_TRACKER_CVAR("Skipped.MainColor"), CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CHECK_TRACKER_CVAR("Skipped.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CHECK_TRACKER_CVAR("Seen.MainColor"), CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CHECK_TRACKER_CVAR("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CHECK_TRACKER_CVAR("Scummed.MainColor"), CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, "gCheckTrackerScummedHide", "Checks you collect, but then reload before saving so you no longer have them."); + //CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CHECK_TRACKER_CVAR("Hinted.MainColor"), CHECK_TRACKER_CVAR("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CHECK_TRACKER_CVAR("Hinted.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CHECK_TRACKER_CVAR("Collected.MainColor"), CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CHECK_TRACKER_CVAR("Collected.Hide"), "Checks you have collected without saving or reloading yet."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CHECK_TRACKER_CVAR("Saved.MainColor"), CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CHECK_TRACKER_CVAR("Saved.Hide"), "Checks that you saved the game while having collected."); ImGui::PopStyleVar(1); ImGui::EndTable(); @@ -1661,25 +1661,25 @@ void CheckTrackerSettingsWindow::DrawElement() { } void CheckTrackerWindow::InitElement() { - Color_Background = CVarGetColor("gCheckTrackerBgColor", Color_Bg_Default); - Color_Area_Incomplete_Main = CVarGetColor("gCheckTrackerAreaMainIncompleteColor", Color_Main_Default); - Color_Area_Incomplete_Extra = CVarGetColor("gCheckTrackerAreaExtraIncompleteColor", Color_Area_Incomplete_Extra_Default); - Color_Area_Complete_Main = CVarGetColor("gCheckTrackerAreaMainCompleteColor", Color_Main_Default); - Color_Area_Complete_Extra = CVarGetColor("gCheckTrackerAreaExtraCompleteColor", Color_Area_Complete_Extra_Default); - Color_Unchecked_Main = CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default); - Color_Unchecked_Extra = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default); - Color_Skipped_Main = CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default); - Color_Skipped_Extra = CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default); - Color_Seen_Main = CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default); - Color_Seen_Extra = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default); - Color_Hinted_Main = CVarGetColor("gCheckTrackerHintedMainColor", Color_Main_Default); - Color_Hinted_Extra = CVarGetColor("gCheckTrackerHintedExtraColor", Color_Hinted_Extra_Default); - Color_Collected_Main = CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default); - Color_Collected_Extra = CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default); - Color_Scummed_Main = CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default); - Color_Scummed_Extra = CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default); - Color_Saved_Main = CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default); - Color_Saved_Extra = CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default); + Color_Background = CVarGetColor(CHECK_TRACKER_CVAR("BgColor"), Color_Bg_Default); + Color_Area_Incomplete_Main = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), Color_Main_Default); + Color_Area_Incomplete_Extra = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); + Color_Area_Complete_Main = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.MainColor"), Color_Main_Default); + Color_Area_Complete_Extra = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); + Color_Unchecked_Main = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.MainColor"), Color_Main_Default); + Color_Unchecked_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); + Color_Skipped_Main = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.MainColor"), Color_Main_Default); + Color_Skipped_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default); + Color_Seen_Main = CVarGetColor(CHECK_TRACKER_CVAR("Seen.MainColor"), Color_Main_Default); + Color_Seen_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default); + Color_Hinted_Main = CVarGetColor(CHECK_TRACKER_CVAR("Hinted.MainColor"), Color_Main_Default); + Color_Hinted_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Hinted.ExtraColor"), Color_Hinted_Extra_Default); + Color_Collected_Main = CVarGetColor(CHECK_TRACKER_CVAR("Collected.MainColor"), Color_Main_Default); + Color_Collected_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default); + Color_Scummed_Main = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.MainColor"), Color_Main_Default); + Color_Scummed_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default); + Color_Saved_Main = CVarGetColor(CHECK_TRACKER_CVAR("Saved.MainColor"), Color_Main_Default); + Color_Saved_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default); SaveManager::Instance->AddInitFunction(InitTrackerData); sectionId = SaveManager::Instance->AddSaveFunction("trackerData", 1, SaveFile, true, -1); @@ -1695,8 +1695,8 @@ void CheckTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); - hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1); - alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0); + hideShopRightChecks = CVarGetInteger(CHECK_TRACKER_CVAR("HideRightShopChecks"), 1); + alwaysShowGS = CVarGetInteger(CHECK_TRACKER_CVAR("AlwaysShowGSLocs"), 0); LocationTable_Init(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index 13669271f..e05a5ed38 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -665,25 +665,25 @@ void EntranceTrackerWindow::DrawElement() { ImGui::TableNextColumn(); ImGui::Text("Sort By"); - UIWidgets::EnhancementRadioButton("To", "gEntranceTrackerSortBy", 0); + UIWidgets::EnhancementRadioButton("To", ENTRANCE_TRACKER_CVAR("SortBy"), 0); UIWidgets::Tooltip("Sort entrances by the original source entrance"); - UIWidgets::EnhancementRadioButton("From", "gEntranceTrackerSortBy", 1); + UIWidgets::EnhancementRadioButton("From", ENTRANCE_TRACKER_CVAR("SortBy"), 1); UIWidgets::Tooltip("Sort entrances by the overrided destination"); UIWidgets::Spacer(2.0f); ImGui::Text("List Items"); - UIWidgets::PaddedEnhancementCheckbox("Auto scroll", "gEntranceTrackerAutoScroll", true, false); + UIWidgets::PaddedEnhancementCheckbox("Auto scroll", ENTRANCE_TRACKER_CVAR("AutoScroll"), true, false); UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Highlight previous", "gEntranceTrackerHighlightPrevious", true, false); + UIWidgets::PaddedEnhancementCheckbox("Highlight previous", ENTRANCE_TRACKER_CVAR("HighlightPrevious"), true, false); UIWidgets::Tooltip("Highlight the previous entrance that Link came from"); - UIWidgets::PaddedEnhancementCheckbox("Highlight available", "gEntranceTrackerHighlightAvailable", true, false); + UIWidgets::PaddedEnhancementCheckbox("Highlight available", ENTRANCE_TRACKER_CVAR("HighlightAvailable"), true, false); UIWidgets::Tooltip("Highlight available entrances in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", "gEntranceTrackerCollapseUndiscovered", true, false); + UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", ENTRANCE_TRACKER_CVAR("CollapseUndiscovered"), true, false); UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group"); bool disableHideReverseEntrances = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_ON; static const char* disableHideReverseEntrancesText = "This option is disabled because \"Decouple Entrances\" is enabled."; - UIWidgets::PaddedEnhancementCheckbox("Hide reverse", "gEntranceTrackerHideReverseEntrances", true, false, + UIWidgets::PaddedEnhancementCheckbox("Hide reverse", ENTRANCE_TRACKER_CVAR("HideReverseEntrances"), true, false, disableHideReverseEntrances, disableHideReverseEntrancesText, UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Hide reverse entrance transitions when Decouple Entrances is off"); UIWidgets::Spacer(0); @@ -691,17 +691,17 @@ void EntranceTrackerWindow::DrawElement() { ImGui::TableNextColumn(); ImGui::Text("Group By"); - UIWidgets::EnhancementRadioButton("Area", "gEntranceTrackerGroupBy", 0); + UIWidgets::EnhancementRadioButton("Area", ENTRANCE_TRACKER_CVAR("GroupBy"), 0); UIWidgets::Tooltip("Group entrances by their area"); - UIWidgets::EnhancementRadioButton("Type", "gEntranceTrackerGroupBy", 1); + UIWidgets::EnhancementRadioButton("Type", ENTRANCE_TRACKER_CVAR("GroupBy"), 1); UIWidgets::Tooltip("Group entrances by their entrance type"); UIWidgets::Spacer(2.0f); ImGui::Text("Spoiler Reveal"); - UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", "gEntranceTrackerShowTo", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", ENTRANCE_TRACKER_CVAR("ShowTo"), true, false); UIWidgets::Tooltip("Reveal the \"To\" entrance for undiscovered entrances"); - UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", "gEntranceTrackerShowFrom", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", ENTRANCE_TRACKER_CVAR("ShowFrom"), true, false); UIWidgets::Tooltip("Reveal the \"From\" entrance for undiscovered entrances"); ImGui::EndTable(); @@ -749,8 +749,8 @@ void EntranceTrackerWindow::DrawElement() { nextTreeState = 2; } - uint8_t destToggle = CVarGetInteger("gEntranceTrackerSortBy", 0); - uint8_t groupToggle = CVarGetInteger("gEntranceTrackerGroupBy", 0); + uint8_t destToggle = CVarGetInteger(ENTRANCE_TRACKER_CVAR("SortBy"), 0); + uint8_t groupToggle = CVarGetInteger(ENTRANCE_TRACKER_CVAR("GroupBy"), 0); // Combine destToggle and groupToggle to get a range of 0-3 uint8_t groupType = destToggle + (groupToggle * 2); @@ -801,7 +801,7 @@ void EntranceTrackerWindow::DrawElement() { // However, if entrances are decoupled, then all transitions need to be displayed, so we proceed with the filtering if ((original->type == ENTRANCE_TYPE_DUNGEON || original->type == ENTRANCE_TYPE_GROTTO || original->type == ENTRANCE_TYPE_INTERIOR) && (original->oneExit != 1 && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_OFF) && - CVarGetInteger("gEntranceTrackerHideReverseEntrances", 1) == 1) { + CVarGetInteger(ENTRANCE_TRACKER_CVAR("HideReverseEntrances"), 1) == 1) { continue; } @@ -812,8 +812,8 @@ void EntranceTrackerWindow::DrawElement() { bool isDiscovered = IsEntranceDiscovered(entrance.index); - bool showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered; - bool showOverride = (!destToggle ? CVarGetInteger("gEntranceTrackerShowFrom", 0) : CVarGetInteger("gEntranceTrackerShowTo", 0)) || isDiscovered; + bool showOriginal = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0)) || isDiscovered; + bool showOverride = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0)) || isDiscovered; const char* origSrcAreaName = spoilerEntranceGroupNames[original->srcGroup].c_str(); const char* origTypeName = groupTypeNames[original->type].c_str(); @@ -826,7 +826,7 @@ void EntranceTrackerWindow::DrawElement() { const char* rplcDstName = showOverride ? override->destination.c_str() : ""; // Filter for entrances by group name, type, source/destination names, and meta tags - if ((!locationSearch.IsActive() && (showOriginal || showOverride || !CVarGetInteger("gEntranceTrackerCollapseUndiscovered", 0))) || + if ((!locationSearch.IsActive() && (showOriginal || showOverride || !CVarGetInteger(ENTRANCE_TRACKER_CVAR("CollapseUndiscovered"), 0))) || ((showOriginal && (locationSearch.PassFilter(origSrcName) || locationSearch.PassFilter(origDstName) || locationSearch.PassFilter(origSrcAreaName) || locationSearch.PassFilter(origTypeName) || locationSearch.PassFilter(original->metaTag.c_str()))) || @@ -864,8 +864,8 @@ void EntranceTrackerWindow::DrawElement() { bool isDiscovered = IsEntranceDiscovered(entrance.index); - bool showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered; - bool showOverride = (!destToggle ? CVarGetInteger("gEntranceTrackerShowFrom", 0) : CVarGetInteger("gEntranceTrackerShowTo", 0)) || isDiscovered; + bool showOriginal = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0)) || isDiscovered; + bool showOverride = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0)) || isDiscovered; const char* unknown = "???"; @@ -879,16 +879,16 @@ void EntranceTrackerWindow::DrawElement() { // Handle highlighting and auto scroll if ((original->index == lastEntranceIndex || (override->reverseIndex == lastEntranceIndex && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_OFF)) && - CVarGetInteger("gEntranceTrackerHighlightPrevious", 0)) { + CVarGetInteger(ENTRANCE_TRACKER_CVAR("HighlightPrevious"), 0)) { color = COLOR_ORANGE; } else if (LinkIsInArea(original) != -1) { - if (CVarGetInteger("gEntranceTrackerHighlightAvailable", 0)) { + if (CVarGetInteger(ENTRANCE_TRACKER_CVAR("HighlightAvailable"), 0)) { color = COLOR_GREEN; } if (doAreaScroll) { doAreaScroll = false; - if (CVarGetInteger("gEntranceTrackerAutoScroll", 0)) { + if (CVarGetInteger(ENTRANCE_TRACKER_CVAR("AutoScroll"), 0)) { ImGui::SetScrollHereY(0.0f); } } diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 08efbf99b..e38af9fa3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -413,17 +413,17 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { if (!GameInteractor::IsSaveLoaded()) { return; } - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int textSize = CVarGetInteger("gTrackers.ItemTracker.ItemTrackerTextSize", 13); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int textSize = CVarGetInteger(ITEM_TRACKER_CVAR("TextSize"), 13); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ImVec2 p = ImGui::GetCursorScreenPos(); - int32_t trackerNumberDisplayMode = CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); - int32_t trackerKeyNumberDisplayMode = CVarGetInteger("gItemTrackerKeyTrack", KEYS_COLLECTED_MAX); + int32_t trackerNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); + int32_t trackerKeyNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("KeyCounts"), KEYS_COLLECTED_MAX); float textScalingFactor = static_cast(iconSize) / 36.0f; uint32_t actualItemId = INV_CONTENT(item.id); bool hasItem = actualItemId != ITEM_NONE; - if (CVarGetInteger("gTrackers.ItemTracker.HookshotIdentifier", 0)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("HookshotIdentifier"), 0)) { if ((actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT) && hasItem) { // Calculate the scaled position for the text @@ -469,7 +469,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImU32 currentColor = IM_COL_WHITE; ImU32 maxColor = item.id == QUEST_SKULL_TOKEN ? IM_COL_RED : IM_COL_GREEN; - bool shouldAlignToLeft = CVarGetInteger("gItemTrackerCurrentOnLeft", 0) && + bool shouldAlignToLeft = CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountAlignLeft"), 0) && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_CAPACITY && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_AMMO; @@ -529,7 +529,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { uint8_t piecesTotal = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_TOTAL); ImU32 currentColor = gSaveContext.triforcePiecesCollected >= piecesRequired ? IM_COL_GREEN : IM_COL_WHITE; ImU32 maxColor = IM_COL_GREEN; - int32_t trackerTriforcePieceNumberDisplayMode = CVarGetInteger("gItemTrackerTriforcePieceTrack", TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); + int32_t trackerTriforcePieceNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("TriforcePieceCounts"), TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); currentString += std::to_string(gSaveContext.triforcePiecesCollected); currentString += "/"; @@ -559,7 +559,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { void DrawEquip(ItemTrackerItem item) { bool hasEquip = HasEquipment(item); - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -568,7 +568,7 @@ void DrawEquip(ItemTrackerItem item) { void DrawQuest(ItemTrackerItem item) { bool hasQuestItem = HasQuestItem(item); - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); ImGui::BeginGroup(); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -585,7 +585,7 @@ void DrawQuest(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) { uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); bool hasItem = actualItemId != ITEM_NONE; std::string itemName = ""; @@ -661,7 +661,7 @@ void DrawBottle(ItemTrackerItem item) { item = actualItemTrackerItemMap[actualItemId]; } - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -672,7 +672,7 @@ void DrawDungeonItem(ItemTrackerItem item) { uint32_t itemId = item.id; ImU32 dungeonColor = IM_COL_WHITE; uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false; bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; ImGui::BeginGroup(); @@ -718,7 +718,7 @@ void DrawDungeonItem(ItemTrackerItem item) { } void DrawSong(ItemTrackerItem item) { - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); ImVec2 p = ImGui::GetCursorScreenPos(); bool hasSong = HasSong(item); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); @@ -729,8 +729,8 @@ void DrawSong(ItemTrackerItem item) { void DrawNotes(bool resizeable = false) { ImGui::BeginGroup(); - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int iconSpacing = CVarGetInteger("gItemTrackerIconSpacing", 12); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); struct ItemTrackerNotes { static int TrackerNotesResizeCallback(ImGuiInputTextCallbackData* data) { @@ -775,11 +775,11 @@ void BeginFloatingWindows(std::string UniqueName, ImGuiWindowFlags flags = 0) { windowFlags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize; } - if (CVarGetInteger("gItemTrackerWindowType", TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar; - if (!CVarGetInteger("gItemTrackerHudEditMode", 0)) { + if (!CVarGetInteger(ITEM_TRACKER_CVAR("Draggable"), 0)) { windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; } } @@ -800,9 +800,9 @@ void EndFloatingWindows() { * Takes in a vector of ItemTrackerItem and draws them in rows of N items */ void DrawItemsInRows(std::vector items, int columns = 6) { - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int iconSpacing = CVarGetInteger("gItemTrackerIconSpacing", 12); - int topPadding = (CVarGetInteger("gItemTrackerWindowType", TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); + int topPadding = (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; for (int i = 0; i < items.size(); i++) { int row = i / columns; @@ -817,8 +817,8 @@ void DrawItemsInRows(std::vector items, int columns = 6) { * Takes in a vector of ItemTrackerItem and draws them evenly spread across a circle */ void DrawItemsInACircle(std::vector items) { - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int iconSpacing = CVarGetInteger("gItemTrackerIconSpacing", 12); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); ImVec2 max = ImGui::GetWindowContentRegionMax(); float radius = (iconSize + iconSpacing) * 2; @@ -827,7 +827,7 @@ void DrawItemsInACircle(std::vector items) { float angle = (float)i / items.size() * 2.0f * M_PI; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; - ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger("gItemTrackerIconSize", 36) - 8) / 2.0f, y + 4)); + ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36) - 8) / 2.0f, y + 4)); items[i].drawFunc(items[i]); } } @@ -838,8 +838,8 @@ void DrawItemsInACircle(std::vector items) { * to then call DrawItemsInRows */ std::vector GetDungeonItemsVector(std::vector dungeons, int columns = 6) { - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int iconSpacing = CVarGetInteger("gItemTrackerIconSpacing", 12); + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); std::vector dungeonItems = {}; int rowCount = 0; @@ -894,8 +894,8 @@ void UpdateVectors() { dungeonRewards.insert(dungeonRewards.end(), dungeonRewardMedallions.begin(), dungeonRewardMedallions.end()); dungeonItems.clear(); - if (CVarGetInteger("gItemTrackerDisplayDungeonItemsHorizontal", 1) && CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { - if (CVarGetInteger("gItemTrackerDisplayDungeonItemsMaps", 1)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.Layout"), 1) && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { dungeonItems = GetDungeonItemsVector(itemTrackerDungeonsWithMapsHorizontal, 12); // Manually adding Thieves Hideout to an open spot so we don't get an additional row for one item dungeonItems[23] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); @@ -905,7 +905,7 @@ void UpdateVectors() { dungeonItems[15] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); } } else { - if (CVarGetInteger("gItemTrackerDisplayDungeonItemsMaps", 1)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { dungeonItems = GetDungeonItemsVector(itemTrackerDungeonsWithMapsCompact); // Manually adding Thieves Hideout to an open spot so we don't get an additional row for one item dungeonItems[35] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); @@ -915,37 +915,37 @@ void UpdateVectors() { } mainWindowItems.clear(); - if (CVarGetInteger("gItemTrackerInventoryItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), inventoryItems.begin(), inventoryItems.end()); } - if (CVarGetInteger("gItemTrackerEquipmentItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), equipmentItems.begin(), equipmentItems.end()); } - if (CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), miscItems.begin(), miscItems.end()); } - if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), dungeonRewardStones.begin(), dungeonRewardStones.end()); mainWindowItems.insert(mainWindowItems.end(), dungeonRewardMedallions.begin(), dungeonRewardMedallions.end()); } - if (CVarGetInteger("gItemTrackerSongsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { - if (CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW && - CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW && + CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); } mainWindowItems.insert(mainWindowItems.end(), songItems.begin(), songItems.end()); } - if (CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), dungeonItems.begin(), dungeonItems.end()); } // if we're adding greg to the misc window, // and misc isn't on the main window, // and it doesn't already have greg, add him - if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && - CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW && + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && + CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW && std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item){return item.id == ITEM_RUPEE_GREEN;})) { miscItems.insert(miscItems.end(), gregItems.begin(), gregItems.end()); @@ -960,7 +960,7 @@ void UpdateVectors() { } // if we're adding greg to the main window - if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { // insert empty items until we're on a new row for greg while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); @@ -971,9 +971,9 @@ void UpdateVectors() { } // If we're adding triforce pieces to the main window - if (CVarGetInteger("gItemTrackerTriforcePiecesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { // If Greg isn't on the main window, add empty items to place the triforce pieces on a new row. - if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) != SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) != SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); } @@ -1009,56 +1009,56 @@ void ItemTrackerLoadFile() { void ItemTrackerWindow::DrawElement() { UpdateVectors(); - int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - int iconSpacing = CVarGetInteger("gItemTrackerIconSpacing", 12); - int comboButton1Mask = buttonMap[CVarGetInteger("gItemTrackerComboButton1", TRACKER_COMBO_BUTTON_L)]; - int comboButton2Mask = buttonMap[CVarGetInteger("gItemTrackerComboButton2", TRACKER_COMBO_BUTTON_R)]; + int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); + int comboButton1Mask = buttonMap[CVarGetInteger(ITEM_TRACKER_CVAR("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; + int comboButton2Mask = buttonMap[CVarGetInteger(ITEM_TRACKER_CVAR("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; OSContPad* buttonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = buttonsPressed != nullptr && buttonsPressed[0].button & comboButton1Mask && buttonsPressed[0].button & comboButton2Mask; - bool isPaused = CVarGetInteger("gItemTrackerShowOnlyPaused", 0) == 0 || gPlayState != nullptr && gPlayState->pauseCtx.state > 0; + bool isPaused = CVarGetInteger(ITEM_TRACKER_CVAR("ShowOnlyPaused"), 0) == 0 || gPlayState != nullptr && gPlayState->pauseCtx.state > 0; - if (CVarGetInteger("gItemTrackerWindowType", TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || isPaused && (CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS ? CVarGetInteger("gItemTrackerEnabled", 0) : comboButtonsHeld)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || isPaused && (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS ? CVarGetInteger(WINDOW_CVAR("ItemTracker"), 0) : comboButtonsHeld)) { if ( - (CVarGetInteger("gItemTrackerInventoryItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerEquipmentItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerSongsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerTriforcePiecesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) ) { BeginFloatingWindows("Item Tracker##main window"); DrawItemsInRows(mainWindowItems, 6); - if (CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW && CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { DrawNotes(); } EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerInventoryItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Inventory Items Tracker"); DrawItemsInRows(inventoryItems); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerEquipmentItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Equipment Items Tracker"); DrawItemsInRows(equipmentItems, 3); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Misc Items Tracker"); DrawItemsInRows(miscItems, 4); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Dungeon Rewards Tracker"); - if (CVarGetInteger("gItemTrackerDungeonRewardsCircle", 0)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonRewardsLayout"), 0)) { ImGui::BeginGroup(); DrawItemsInACircle(dungeonRewardMedallions); ImGui::EndGroup(); @@ -1071,16 +1071,16 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerSongsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Songs Tracker"); DrawItemsInRows(songItems); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Dungeon Items Tracker"); - if (CVarGetInteger("gItemTrackerDisplayDungeonItemsHorizontal", 1)) { - if (CVarGetInteger("gItemTrackerDisplayDungeonItemsMaps", 1)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.Layout"), 1)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { DrawItemsInRows(dungeonItems, 12); } else { DrawItemsInRows(dungeonItems, 8); @@ -1091,19 +1091,19 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { BeginFloatingWindows("Greg Tracker"); DrawItemsInRows(gregItems); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerTriforcePiecesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Triforce Piece Tracker"); DrawItemsInRows(triforcePieces); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { ImGui::SetNextWindowSize(ImVec2(400,300), ImGuiCond_FirstUseEver); BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing); DrawNotes(true); @@ -1140,50 +1140,50 @@ void ItemTrackerSettingsWindow::DrawElement() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::ColorEdit4("BG Color##gItemTrackerBgColor", (float*)&ChromaKeyBackground, ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel)) { - CVarSetFloat("gItemTrackerBgColorR", ChromaKeyBackground.x); - CVarSetFloat("gItemTrackerBgColorG", ChromaKeyBackground.y); - CVarSetFloat("gItemTrackerBgColorB", ChromaKeyBackground.z); - CVarSetFloat("gItemTrackerBgColorA", ChromaKeyBackground.w); + CVarSetFloat(ITEM_TRACKER_CVAR("BgColorR"), ChromaKeyBackground.x); + CVarSetFloat(ITEM_TRACKER_CVAR("BgColorG"), ChromaKeyBackground.y); + CVarSetFloat(ITEM_TRACKER_CVAR("BgColorB"), ChromaKeyBackground.z); + CVarSetFloat(ITEM_TRACKER_CVAR("BgColorA"), ChromaKeyBackground.w); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::PopItemWidth(); - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", "gItemTrackerWindowType", windowTypes, TRACKER_WINDOW_FLOATING)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", ITEM_TRACKER_CVAR("WindowType"), windowTypes, TRACKER_WINDOW_FLOATING)) { shouldUpdateVectors = true; } - if (CVarGetInteger("gItemTrackerWindowType", TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { - if (UIWidgets::PaddedEnhancementCheckbox("Enable Dragging", "gItemTrackerHudEditMode")) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { + if (UIWidgets::PaddedEnhancementCheckbox("Enable Dragging", ITEM_TRACKER_CVAR("Draggable"))) { shouldUpdateVectors = true; } - if (UIWidgets::PaddedEnhancementCheckbox("Only enable while paused", "gItemTrackerShowOnlyPaused")) { + if (UIWidgets::PaddedEnhancementCheckbox("Only enable while paused", ITEM_TRACKER_CVAR("ShowOnlyPaused"))) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", "gItemTrackerDisplayType", displayModes, TRACKER_DISPLAY_ALWAYS)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", ITEM_TRACKER_CVAR("DisplayType.Main"), displayModes, TRACKER_DISPLAY_ALWAYS)) { shouldUpdateVectors = true; } - if (CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", "gItemTrackerComboButton1", buttons, TRACKER_COMBO_BUTTON_L)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", ITEM_TRACKER_CVAR("ComboButton1"), buttons, TRACKER_COMBO_BUTTON_L)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", "gItemTrackerComboButton2", buttons, TRACKER_COMBO_BUTTON_R)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", ITEM_TRACKER_CVAR("ComboButton2"), buttons, TRACKER_COMBO_BUTTON_R)) { shouldUpdateVectors = true; } } } UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36); - UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12); - UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", "gTrackers.ItemTracker.ItemTrackerTextSize", 1, 30, "", 13); + UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", ITEM_TRACKER_CVAR("IconSize"), 25, 128, "", 36); + UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", ITEM_TRACKER_CVAR("IconSpacing"), -5, 50, "", 12); + UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", ITEM_TRACKER_CVAR("TextSize"), 1, 30, "", 13); UIWidgets::Spacer(0); ImGui::Text("Ammo/Capacity Tracking"); - UIWidgets::EnhancementCombobox("gItemTrackerCapacityTrack", itemTrackerCapacityTrackOptions, ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); + UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("ItemCountType"), itemTrackerCapacityTrackOptions, ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); UIWidgets::InsertHelpHoverText("Customize what the numbers under each item are tracking." "\n\nNote: items without capacity upgrades will track ammo even in capacity mode"); - if (CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger("gItemTrackerCapacityTrack", ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { - if (UIWidgets::PaddedEnhancementCheckbox("Align count to left side", "gItemTrackerCurrentOnLeft")) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { + if (UIWidgets::PaddedEnhancementCheckbox("Align count to left side", ITEM_TRACKER_CVAR("ItemCountAlignLeft"))) { shouldUpdateVectors = true; } } @@ -1191,64 +1191,64 @@ void ItemTrackerSettingsWindow::DrawElement() { UIWidgets::Spacer(0); ImGui::Text("Key Count Tracking"); - UIWidgets::EnhancementCombobox("gItemTrackerKeyTrack", itemTrackerKeyTrackOptions, KEYS_COLLECTED_MAX); + UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("KeyCounts"), itemTrackerKeyTrackOptions, KEYS_COLLECTED_MAX); UIWidgets::InsertHelpHoverText("Customize what numbers are shown for key tracking."); UIWidgets::Spacer(0); ImGui::Text("Triforce Piece Count Tracking"); - UIWidgets::EnhancementCombobox("gItemTrackerTriforcePieceTrack", itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); + UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); UIWidgets::InsertHelpHoverText("Customize what numbers are shown for triforce piece tracking."); ImGui::TableNextColumn(); - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Inventory", "gItemTrackerInventoryItemsDisplayType", displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Inventory", ITEM_TRACKER_CVAR("DisplayType.Inventory"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Equipment", "gItemTrackerEquipmentItemsDisplayType", displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Equipment", ITEM_TRACKER_CVAR("DisplayType.Equipment"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Misc", "gItemTrackerMiscItemsDisplayType", displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Misc", ITEM_TRACKER_CVAR("DisplayType.Misc"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Rewards", "gItemTrackerDungeonRewardsDisplayType", displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Rewards", ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (CVarGetInteger("gItemTrackerDungeonRewardsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { - if (UIWidgets::PaddedEnhancementCheckbox("Circle display", "gItemTrackerDungeonRewardsCircle", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (UIWidgets::PaddedEnhancementCheckbox("Circle display", ITEM_TRACKER_CVAR("DungeonRewardsLayout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) { shouldUpdateVectors = true; } } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Songs", "gItemTrackerSongsDisplayType", displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Songs", ITEM_TRACKER_CVAR("DisplayType.Songs"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Items", "gItemTrackerDungeonItemsDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Items", ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) { - if (CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { - if (UIWidgets::PaddedEnhancementCheckbox("Horizontal display", "gItemTrackerDisplayDungeonItemsHorizontal", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (UIWidgets::PaddedEnhancementCheckbox("Horizontal display", ITEM_TRACKER_CVAR("DungeonItems.Layout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { shouldUpdateVectors = true; } } - if (UIWidgets::PaddedEnhancementCheckbox("Maps and compasses", "gItemTrackerDisplayDungeonItemsMaps", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (UIWidgets::PaddedEnhancementCheckbox("Maps and compasses", ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { shouldUpdateVectors = true; } } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Greg", "gItemTrackerGregDisplayType", extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Greg", ITEM_TRACKER_CVAR("DisplayType.Greg"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", "gItemTrackerTriforcePiecesDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", "gItemTrackerNotesDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", ITEM_TRACKER_CVAR("DisplayType.Notes"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } } - UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", "gTrackers.ItemTracker.HookshotIdentifier"); + UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", ITEM_TRACKER_CVAR("HookshotIdentifier")); UIWidgets::InsertHelpHoverText("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot."); UIWidgets::Spacer(0); @@ -1260,10 +1260,10 @@ void ItemTrackerSettingsWindow::DrawElement() { } void ItemTrackerWindow::InitElement() { - float trackerBgR = CVarGetFloat("gItemTrackerBgColorR", 0); - float trackerBgG = CVarGetFloat("gItemTrackerBgColorG", 0); - float trackerBgB = CVarGetFloat("gItemTrackerBgColorB", 0); - float trackerBgA = CVarGetFloat("gItemTrackerBgColorA", 1); + float trackerBgR = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorR"), 0); + float trackerBgG = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorG"), 0); + float trackerBgB = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorB"), 0); + float trackerBgA = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorA"), 1); ChromaKeyBackground = { trackerBgR, trackerBgG, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c9cb36130..1921fb866 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2535,12 +2535,12 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { RandomizerInf randoInf = (RandomizerInf)((textId - (TEXT_SHOP_ITEM_RANDOM + NUM_SHOP_ITEMS)) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1); messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SHOP_ITEM_RANDOM_CONFIRM); } - } else if (CVarGetInteger("gRandomizeRupeeNames", 1) && + } else if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { messageEntry = Randomizer::GetRupeeMessage(textId); // In rando, replace Navi's general overworld hints with rando-related gameplay tips - } else if (CVarGetInteger("gRandoRelevantNavi", 1) && textId >= 0x0140 && textId <= 0x015F) { + } else if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), 1) && textId >= 0x0140 && textId <= 0x015F) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index e78ca1bdc..86c6bbfcc 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -65,7 +65,7 @@ private: uint32_t IsGameMasterQuest(); #endif -#define RANDOMIZER_CVAR(var) "gRandoEnhancements." var +#define RANDO_ENHANCEMENT_CVAR(var) "gRandoEnhancements." var #define RANDOMIZER_SEED_CVAR(var) "gRandoSettings." var #define COSMETIC_CVAR(var) "gCosmetics." var #define AUDIO_CVAR(var) "gAudioEditor." var @@ -79,7 +79,8 @@ uint32_t IsGameMasterQuest(); #define ITEM_TRACKER_CVAR(var) TRACKER_CVAR("ItemTracker." var) #define CHECK_TRACKER_CVAR(var) TRACKER_CVAR("CheckTracker." var) #define ENTRANCE_TRACKER_CVAR(var) TRACKER_CVAR("EntranceTracker." var) -#define DEV_TOOLS_CVAR(var) "gDeveloperTools." +#define DEV_TOOLS_CVAR(var) "gDeveloperTools." var +#define GENERAL_CVAR(var) "gGeneral." var #ifndef __cplusplus void InitOTR(void); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 4bfdc10b5..d10532ee3 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -165,41 +165,41 @@ namespace SohGui { SPDLOG_ERROR("Could not find input editor window"); } - mAudioEditorWindow = std::make_shared("gAudioEditor.WindowOpen", "Audio Editor"); + mAudioEditorWindow = std::make_shared(WINDOW_CVAR("AudioEditor"), "Audio Editor"); gui->AddGuiWindow(mAudioEditorWindow); - mInputViewer = std::make_shared("gOpenWindows.InputViewer", "Input Viewer"); + mInputViewer = std::make_shared(WINDOW_CVAR("InputViewer"), "Input Viewer"); gui->AddGuiWindow(mInputViewer); - mInputViewerSettings = std::make_shared("gOpenWindows.InputViewerSettings", "Input Viewer Settings"); + mInputViewerSettings = std::make_shared(WINDOW_CVAR("InputViewerSettings"), "Input Viewer Settings"); gui->AddGuiWindow(mInputViewerSettings); - mCosmeticsEditorWindow = std::make_shared("gCosmeticsEditorEnabled", "Cosmetics Editor"); + mCosmeticsEditorWindow = std::make_shared(WINDOW_CVAR("CosmeticsEditor"), "Cosmetics Editor"); gui->AddGuiWindow(mCosmeticsEditorWindow); - mActorViewerWindow = std::make_shared("gActorViewerEnabled", "Actor Viewer"); + mActorViewerWindow = std::make_shared(WINDOW_CVAR("ActorViewer"), "Actor Viewer"); gui->AddGuiWindow(mActorViewerWindow); - mColViewerWindow = std::make_shared("gCollisionViewerEnabled", "Collision Viewer"); + mColViewerWindow = std::make_shared(WINDOW_CVAR("CollisionViewer"), "Collision Viewer"); gui->AddGuiWindow(mColViewerWindow); - mSaveEditorWindow = std::make_shared("gSaveEditorEnabled", "Save Editor"); + mSaveEditorWindow = std::make_shared(WINDOW_CVAR("SaveEditor"), "Save Editor"); gui->AddGuiWindow(mSaveEditorWindow); - mDLViewerWindow = std::make_shared("gDLViewerEnabled", "Display List Viewer"); + mDLViewerWindow = std::make_shared(WINDOW_CVAR("DLViewer"), "Display List Viewer"); gui->AddGuiWindow(mDLViewerWindow); - mValueViewerWindow = std::make_shared("gValueViewer.WindowOpen", "Value Viewer"); + mValueViewerWindow = std::make_shared(WINDOW_CVAR("ValueViewer"), "Value Viewer"); gui->AddGuiWindow(mValueViewerWindow); - mMessageViewerWindow = std::make_shared("gMessageViewerEnabled", "Message Viewer"); + mMessageViewerWindow = std::make_shared(WINDOW_CVAR("MessageViewer"), "Message Viewer"); gui->AddGuiWindow(mMessageViewerWindow); - mGameplayStatsWindow = std::make_shared("gGameplayStatsEnabled", "Gameplay Stats"); + mGameplayStatsWindow = std::make_shared(WINDOW_CVAR("GameplayStats"), "Gameplay Stats"); gui->AddGuiWindow(mGameplayStatsWindow); - mCheckTrackerWindow = std::make_shared("gCheckTrackerEnabled", "Check Tracker"); + mCheckTrackerWindow = std::make_shared(WINDOW_CVAR("CheckTracker"), "Check Tracker"); gui->AddGuiWindow(mCheckTrackerWindow); - mCheckTrackerSettingsWindow = std::make_shared("gCheckTrackerSettingsEnabled", "Check Tracker Settings"); + mCheckTrackerSettingsWindow = std::make_shared(WINDOW_CVAR("CheckTrackerSettings"), "Check Tracker Settings"); gui->AddGuiWindow(mCheckTrackerSettingsWindow); - mEntranceTrackerWindow = std::make_shared("gEntranceTrackerEnabled","Entrance Tracker"); + mEntranceTrackerWindow = std::make_shared(WINDOW_CVAR("EntranceTracker"),"Entrance Tracker"); gui->AddGuiWindow(mEntranceTrackerWindow); - mItemTrackerWindow = std::make_shared("gItemTrackerEnabled", "Item Tracker"); + mItemTrackerWindow = std::make_shared(WINDOW_CVAR("ItemTracker"), "Item Tracker"); gui->AddGuiWindow(mItemTrackerWindow); - mItemTrackerSettingsWindow = std::make_shared("gItemTrackerSettingsEnabled", "Item Tracker Settings"); + mItemTrackerSettingsWindow = std::make_shared(WINDOW_CVAR("ItemTrackerSettings"), "Item Tracker Settings"); gui->AddGuiWindow(mItemTrackerSettingsWindow); - mRandomizerSettingsWindow = std::make_shared("gRandomizerSettingsEnabled", "Randomizer Settings"); + mRandomizerSettingsWindow = std::make_shared(WINDOW_CVAR("RandomizerSettings"), "Randomizer Settings"); gui->AddGuiWindow(mRandomizerSettingsWindow); - mAdvancedResolutionSettingsWindow = std::make_shared("gAdvancedResolutionEditorEnabled", "Advanced Resolution Settings"); + mAdvancedResolutionSettingsWindow = std::make_shared(WINDOW_CVAR("AdvancedResolutionEditor"), "Advanced Resolution Settings"); gui->AddGuiWindow(mAdvancedResolutionSettingsWindow); mModalWindow = std::make_shared("gOpenWindows.modalWindowEnabled", "Modal Window"); gui->AddGuiWindow(mModalWindow); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 23aa82362..0ca0f6f89 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -248,12 +248,12 @@ void DrawSettingsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mInputViewer) { - if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger("gOpenWindows.InputViewer", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger(WINDOW_CVAR("InputViewer"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { mInputViewer->ToggleVisibility(); } } if (mInputViewerSettings) { - if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger("gOpenWindows.InputViewerSettings", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger(WINDOW_CVAR("InputViewerSettings"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { mInputViewerSettings->ToggleVisibility(); } } @@ -287,7 +287,7 @@ void DrawSettingsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); UIWidgets::Spacer(0); - if (ImGui::Button(GetWindowButtonText("Advanced Resolution", CVarGetInteger("gAdvancedResolutionEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Advanced Resolution", CVarGetInteger(WINDOW_CVAR("AdvancedResolutionEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mAdvancedResolutionSettingsWindow->ToggleVisibility(); } ImGui::PopStyleColor(1); @@ -1395,19 +1395,19 @@ void DrawEnhancementsMenu() { ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mCosmeticsEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVarGetInteger("gCosmeticsEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVarGetInteger(WINDOW_CVAR("CosmeticsEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mCosmeticsEditorWindow->ToggleVisibility(); } } if (mAudioEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Audio Editor", CVarGetInteger("gAudioEditor.WindowOpen", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Audio Editor", CVarGetInteger(WINDOW_CVAR("AudioEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mAudioEditorWindow->ToggleVisibility(); } } if (mGameplayStatsWindow) { - if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVarGetInteger("gGameplayStatsEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVarGetInteger(WINDOW_CVAR("GameplayStats"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mGameplayStatsWindow->ToggleVisibility(); } } @@ -1692,37 +1692,37 @@ void DrawDeveloperToolsMenu() { } UIWidgets::Spacer(0); if (mSaveEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Save Editor", CVarGetInteger("gSaveEditorEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Save Editor", CVarGetInteger(WINDOW_CVAR("SaveEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mSaveEditorWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mColViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVarGetInteger("gCollisionViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVarGetInteger(WINDOW_CVAR("CollisionViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mColViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mActorViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVarGetInteger("gActorViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVarGetInteger(WINDOW_CVAR("ActorViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mActorViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mDLViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Display List Viewer", CVarGetInteger("gDLViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Display List Viewer", CVarGetInteger(WINDOW_CVAR("DLViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mDLViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mValueViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Value Viewer", CVarGetInteger("gValueViewer.WindowOpen", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Value Viewer", CVarGetInteger(WINDOW_CVAR("ValueViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mValueViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mMessageViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger("gMessageViewerEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger(WINDOW_CVAR("MessageViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mMessageViewerWindow->ToggleVisibility(); } } @@ -1884,39 +1884,39 @@ void DrawRandomizerMenu() { static ImVec2 buttonSize(200.0f, 0.0f); #endif if (mRandomizerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger(WINDOW_CVAR("RandomizerSettings"), 0)).c_str(), buttonSize)) { mRandomizerSettingsWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mItemTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger("gItemTrackerEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger(WINDOW_CVAR("ItemTracker"), 0)).c_str(), buttonSize)) { mItemTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mItemTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVarGetInteger("gItemTrackerSettingsEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVarGetInteger(WINDOW_CVAR("ItemTrackerSettings"), 0)).c_str(), buttonSize)) { mItemTrackerSettingsWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mEntranceTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger("gEntranceTrackerEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger(WINDOW_CVAR("EntranceTracker"), 0)).c_str(), buttonSize)) { mEntranceTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mCheckTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger("gCheckTrackerEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger(WINDOW_CVAR("CheckTracker"), 0)).c_str(), buttonSize)) { mCheckTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mCheckTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVarGetInteger("gCheckTrackerSettingsEnabled", 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVarGetInteger(WINDOW_CVAR("CheckTrackerSettings"), 0)).c_str(), buttonSize)) { mCheckTrackerSettingsWindow->ToggleVisibility(); } } @@ -1927,11 +1927,11 @@ void DrawRandomizerMenu() { if (ImGui::BeginMenu("Rando Enhancements")) { - UIWidgets::EnhancementCheckbox("Rando-Relevant Navi Hints", "gRandoRelevantNavi", false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::EnhancementCheckbox("Rando-Relevant Navi Hints", RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "Replace Navi's overworld quest hints with rando-related gameplay hints." ); - UIWidgets::PaddedEnhancementCheckbox("Random Rupee Names", "gRandomizeRupeeNames", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Random Rupee Names", RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "When obtaining rupees, randomize what the rupee is called in the textbox." ); @@ -1957,13 +1957,13 @@ void DrawRandomizerMenu() { "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; - UIWidgets::PaddedEnhancementCheckbox("Key Colors Match Dungeon", "gRandoMatchKeyColors", true, false, + UIWidgets::PaddedEnhancementCheckbox("Key Colors Match Dungeon", RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), true, false, disableKeyColors, disableKeyColorsText, UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "Matches the color of small keys and boss keys to the dungeon they belong to. " "This helps identify keys from afar and adds a little bit of flair.\n\nThis only " "applies to seeds with keys and boss keys shuffled to Any Dungeon, Overworld, or Anywhere."); - UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares", true, false); + UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), true, false); UIWidgets::Tooltip( "Play unique fanfares when obtaining quest items " "(medallions/stones/songs). Note that these fanfares are longer than usual." diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index 41d2a8ec3..b8e18c633 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -4025,7 +4025,7 @@ void Audio_PlayFanfare_Rando(GetItemEntry getItem) { temp1 = NA_BGM_SMALL_ITEM_GET | 0x900; } // If the setting is toggled on and we get special quest items (longer fanfares): - if (CVarGetInteger("gRandoQuestItemFanfares", 0) != 0) { + if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), 0) != 0) { // If we get a medallion, play the "get a medallion" fanfare if ((itemId >= ITEM_MEDALLION_FOREST) && (itemId <= ITEM_MEDALLION_LIGHT)) { temp1 = NA_BGM_MEDALLION_GET | 0x900; From e2622af004b17df58ab8a8d1472ab78ae649f341 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sat, 20 Apr 2024 11:56:32 -0700 Subject: [PATCH 173/300] Step 3 of CVar macro/sectionalizing: Dev Tools, Cheats, Audio Editor, Remote (#4030) * Swapped Audio Editor CVars. * Swapped Cheat CVars. * Swapped Developer Tools CVars. Also a couple General CVars. * Added REMOTE_CVAR. Swapped Remote CVars. * Missed an include. --- .../Enhancements/audio/AudioCollection.cpp | 15 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 28 ++-- .../controls/SohInputEditorWindow.cpp | 2 +- .../cosmetics/CosmeticsEditor.cpp | 3 +- .../game-interactor/GameInteractor_Remote.cpp | 3 +- soh/soh/Enhancements/mods.cpp | 26 ++-- soh/soh/Enhancements/presets.h | 76 +++++----- .../Enhancements/randomizer/randomizer.cpp | 4 +- soh/soh/OTRGlobals.cpp | 14 +- soh/soh/OTRGlobals.h | 1 + soh/soh/SohMenuBar.cpp | 142 +++++++++--------- soh/src/code/z_bgcheck.c | 6 +- soh/src/code/z_common_data.c | 2 +- soh/src/code/z_en_item00.c | 2 +- soh/src/code/z_kaleido_setup.c | 2 +- soh/src/code/z_map_exp.c | 2 +- soh/src/code/z_message_PAL.c | 4 +- soh/src/code/z_parameter.c | 12 +- soh/src/code/z_play.c | 4 +- soh/src/code/z_player_lib.c | 10 +- soh/src/code/z_room.c | 2 +- .../actors/ovl_Arms_Hook/z_arms_hook.c | 2 +- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 8 +- .../overlays/actors/ovl_En_Crow/z_en_crow.c | 4 +- .../actors/ovl_En_Firefly/z_en_firefly.c | 4 +- .../overlays/actors/ovl_En_Fish/z_en_fish.c | 2 +- .../overlays/actors/ovl_En_Horse/z_en_horse.c | 2 +- .../actors/ovl_En_Insect/z_en_insect.c | 2 +- soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c | 4 +- .../ovl_En_River_Sound/z_en_river_sound.c | 2 +- .../actors/ovl_player_actor/z_player.c | 46 +++--- .../ovl_file_choose/z_file_choose.c | 8 +- .../overlays/gamestates/ovl_title/z_title.c | 4 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 2 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 4 +- .../misc/ovl_kaleido_scope/z_kaleido_scope.h | 6 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 4 +- 37 files changed, 235 insertions(+), 229 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index 9da742f91..415049bbe 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -330,11 +331,13 @@ AudioCollection::AudioCollection() { } std::string AudioCollection::GetCvarKey(std::string sfxKey) { - return "gAudioEditor.ReplacedSequences." + sfxKey + ".value"; + auto prefix = AUDIO_CVAR("ReplacedSequences."); + return prefix + sfxKey + ".value"; } std::string AudioCollection::GetCvarLockKey(std::string sfxKey) { - return "gAudioEditor.ReplacedSequences." + sfxKey + ".locked"; + auto prefix = std::string(AUDIO_CVAR("ReplacedSequences.")); + return prefix + sfxKey + ".locked"; } void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) { @@ -362,7 +365,7 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) { // for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will // play the normal track as usual. if (seqId == NA_BGM_FIELD_MORNING) { - if (CVarGetInteger("gAudioEditor.ReplacedSequences.NA_BGM_FIELD_LOGIC.value", NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { + if (CVarGetInteger(AUDIO_CVAR("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { seqId = NA_BGM_FIELD_LOGIC; } } @@ -381,7 +384,7 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) { } void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) { - const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo->sfxKey; + const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo->sfxKey; excludedSequences.insert(seqInfo); includedSequences.erase(seqInfo); CVarSetInteger(cvarKey.c_str(), 1); @@ -389,7 +392,7 @@ void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) { } void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) { - const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo->sfxKey; + const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo->sfxKey; includedSequences.insert(seqInfo); excludedSequences.erase(seqInfo); CVarClear(cvarKey.c_str()); @@ -401,7 +404,7 @@ void AudioCollection::InitializeShufflePool() { for (auto& [seqId, seqInfo] : sequenceMap) { if (!seqInfo.canBeUsedAsReplacement) continue; - const std::string cvarKey = "gAudioEditor.Excluded." + seqInfo.sfxKey; + const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo.sfxKey; if (CVarGetInteger(cvarKey.c_str(), 0)) { excludedSequences.insert(&seqInfo); } else { diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index 68077a968..e809ce785 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -163,17 +163,17 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence const std::string stopButton = ICON_FA_STOP + hiddenKey; const std::string previewButton = ICON_FA_PLAY + hiddenKey; - if (CVarGetInteger("gAudioEditor.Playing", 0) == sequenceId) { + if (CVarGetInteger(AUDIO_CVAR("Playing"), 0) == sequenceId) { if (ImGui::Button(stopButton.c_str())) { func_800F5C2C(); - CVarSetInteger("gAudioEditor.Playing", 0); + CVarSetInteger(AUDIO_CVAR("Playing"), 0); } UIWidgets::Tooltip("Stop Preview"); } else { if (ImGui::Button(previewButton.c_str())) { - if (CVarGetInteger("gAudioEditor.Playing", 0) != 0) { + if (CVarGetInteger(AUDIO_CVAR("Playing"), 0) != 0) { func_800F5C2C(); - CVarSetInteger("gAudioEditor.Playing", 0); + CVarSetInteger(AUDIO_CVAR("Playing"), 0); } else { if (sequenceType == SEQ_SFX || sequenceType == SEQ_VOICE) { Audio_PlaySoundGeneral(sequenceId, &pos, 4, &freqScale, &freqScale, &reverbAdd); @@ -183,7 +183,7 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence } else { // TODO: Cant do both here, so have to click preview button twice PreviewSequence(sequenceId); - CVarSetInteger("gAudioEditor.Playing", sequenceId); + CVarSetInteger(AUDIO_CVAR("Playing"), sequenceId); } } } @@ -411,7 +411,7 @@ void DrawTypeChip(SeqType type) { void AudioEditorRegisterOnSceneInitHook() { GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { - if (CVarGetInteger("gAudioEditor.RandomizeAllOnNewScene", 0)) { + if (CVarGetInteger(AUDIO_CVAR("RandomizeAllOnNewScene"), 0)) { AudioEditor_RandomizeAll(); } }); @@ -492,18 +492,18 @@ void AudioEditor::DrawElement() { ImGui::TableNextColumn(); if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", "gEnemyBGMDisable"); + UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", AUDIO_CVAR("EnemyBGMDisable")); UIWidgets::InsertHelpHoverText( "Disables the music change when getting close to enemies. Useful for hearing " "your custom music for each scene more often."); - UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", "gLostWoodsConsistentVolume"); + UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", AUDIO_CVAR("LostWoodsConsistentVolume")); UIWidgets::InsertHelpHoverText( "Disables the volume shifting in the Lost Woods. Useful for hearing " "your custom music in the Lost Woods if you don't need the navigation assitance " "the volume changing provides. If toggling this while in the Lost Woods, reload " "the area for the effect to kick in." ); - UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", "gSeqNameOverlay"); + UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", AUDIO_CVAR("SeqNameOverlay")); UIWidgets::InsertHelpHoverText( "Displays the name of the current sequence in the corner of the screen whenever a new sequence " "is loaded to the main sequence player (does not apply to fanfares or enemy BGM)." @@ -511,28 +511,28 @@ void AudioEditor::DrawElement() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); UIWidgets::EnhancementSliderInt("Overlay Duration: %d seconds", "##SeqNameOverlayDuration", - "gSeqNameOverlayDuration", 1, 10, "", 5); + AUDIO_CVAR("SeqNameOverlayDuration"), 1, 10, "", 5); ImGui::PopItemWidth(); ImGui::NewLine(); ImGui::PopItemWidth(); UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier", - "gLinkVoiceFreqMultiplier", 0.4, 2.5, "", 1.0, true, true); + AUDIO_CVAR("LinkVoiceFreqMultiplier"), 0.4, 2.5, "", 1.0, true, true); ImGui::SameLine(); const std::string resetButton = "Reset##linkVoiceFreqMultiplier"; if (ImGui::Button(resetButton.c_str())) { - CVarSetFloat("gLinkVoiceFreqMultiplier", 1.0f); + CVarSetFloat(AUDIO_CVAR("LinkVoiceFreqMultiplier"), 1.0f); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); - UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", "gAudioEditor.RandomizeAllOnNewScene"); + UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", AUDIO_CVAR("RandomizeAllOnNewScene")); UIWidgets::Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene."); ImGui::NewLine(); ImGui::PushItemWidth(-FLT_MIN); UIWidgets::PaddedSeparator(); UIWidgets::PaddedText("The following options are experimental and may cause music\nto sound odd or have other undesireable effects."); - UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", "gExperimentalOctaveDrop"); + UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", AUDIO_CVAR("ExperimentalOctaveDrop")); UIWidgets::InsertHelpHoverText("Some custom sequences may have notes that are too high for the game's audio " "engine to play. Enabling this checkbox will cause these notes to drop a " "couple of octaves so they can still harmonize with the other notes of the " diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index a1290c238..ed86a59e9 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1680,7 +1680,7 @@ void SohInputEditorWindow::DrawMiscControlPanel() { UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select " "certain items."); UIWidgets::Spacer(0); - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed"); if (CVarGetInteger("gEnableWalkModify", 0)) { diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 52f319b3e..0ec469fe0 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -13,6 +13,7 @@ #include #include "soh/UIWidgets.hpp" +#include "soh/OTRGlobals.h" extern "C" { #include @@ -1344,7 +1345,7 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { } } void DrawSillyTab() { - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); if (CVarGetInteger("gLetItSnow", 0)) { if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp index 2cbd6b379..7a3f96f14 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "soh/OTRGlobals.h" // MARK: - Remote @@ -16,7 +17,7 @@ void GameInteractor::EnableRemoteInteractor() { return; } - if (SDLNet_ResolveHost(&remoteIP, CVarGetString("gRemote.IP", "127.0.0.1"), CVarGetInteger("gRemote.Port", 43384)) == -1) { + if (SDLNet_ResolveHost(&remoteIP, CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1"), CVarGetInteger(REMOTE_CVAR("Port"), 43384)) == -1) { SPDLOG_ERROR("[GameInteractor] SDLNet_ResolveHost: {}", SDLNet_GetError()); } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index d1147f5fc..f63878711 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -66,7 +66,7 @@ void ReloadSceneTogglingLinkAge() { void RegisterInfiniteMoney() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gInfiniteMoney", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("InfiniteMoney"), 0) != 0) { if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) { gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); } @@ -77,7 +77,7 @@ void RegisterInfiniteMoney() { void RegisterInfiniteHealth() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gInfiniteHealth", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("InfiniteHealth"), 0) != 0) { if (gSaveContext.health < gSaveContext.healthCapacity) { gSaveContext.health = gSaveContext.healthCapacity; } @@ -88,7 +88,7 @@ void RegisterInfiniteHealth() { void RegisterInfiniteAmmo() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gInfiniteAmmo", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0) != 0) { // Deku Sticks if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) { AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); @@ -125,7 +125,7 @@ void RegisterInfiniteAmmo() { void RegisterInfiniteMagic() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gInfiniteMagic", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("InfiniteMagic"), 0) != 0) { if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) { gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30; } @@ -136,7 +136,7 @@ void RegisterInfiniteMagic() { void RegisterInfiniteNayrusLove() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gInfiniteNayru", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("InfiniteNayru"), 0) != 0) { gSaveContext.nayrusLoveTimer = 0x44B; } }); @@ -146,7 +146,7 @@ void RegisterMoonJumpOnL() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gMoonJumpOnL", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("MoonJumpOnL"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); if (CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) { @@ -161,7 +161,7 @@ void RegisterInfiniteISG() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gEzISG", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("EasyISG"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); player->meleeWeaponState = 1; } @@ -173,7 +173,7 @@ void RegisterEzQPA() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gEzQPA", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("EasyQPA"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); player->meleeWeaponQuads[0].info.toucher.dmgFlags = 0x16171617; player->meleeWeaponQuads[1].info.toucher.dmgFlags = 0x16171617; @@ -185,7 +185,7 @@ void RegisterUnrestrictedItems() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger("gNoRestrictItems", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("NoRestrictItems"), 0) != 0) { u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong; memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions)); gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup; @@ -195,7 +195,7 @@ void RegisterUnrestrictedItems() { void RegisterFreezeTime() { GameInteractor::Instance->RegisterGameHook([]() { - if (CVarGetInteger("gFreezeTime", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("FreezeTime"), 0) != 0) { if (CVarGetInteger("gPrevTime", -1) == -1) { CVarSetInteger("gPrevTime", gSaveContext.dayTime); } @@ -214,7 +214,7 @@ void RegisterSwitchAge() { static bool warped = false; if (!GameInteractor::IsSaveLoaded(true)) { - CVarClear("gSwitchAge"); + CVarClear(GENERAL_CVAR("SwitchAge")); warped = false; return; } @@ -224,7 +224,7 @@ void RegisterSwitchAge() { static RoomContext* roomCtx; static s32 roomNum; - if (CVarGetInteger("gSwitchAge", 0) && !warped) { + if (CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) && !warped) { playerPos = GET_PLAYER(gPlayState)->actor.world.pos; playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y; roomCtx = &gPlayState->roomCtx; @@ -243,7 +243,7 @@ void RegisterSwitchAge() { func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room) } warped = false; - CVarClear("gSwitchAge"); + CVarClear(GENERAL_CVAR("SwitchAge")); } }); } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 820873381..f34a0e90c 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -298,51 +298,51 @@ const std::vector cheatCvars = { "gCustomizeShootingGallery", "gCustomizeBombchuBowling", "gCustomizeFishing", - "gInfiniteAmmo", - "gInfiniteEpona", - "gInfiniteHealth", - "gInfiniteMagic", - "gInfiniteMoney", - "gInfiniteNayru", - "gNoClip", - "gClimbEverything", - "gHookshotEverything", - "gCheatHookshotReachMultiplier", - "gMoonJumpOnL", - "gSuperTunic", - "gEzISG", - "gEzQPA", - "gTimelessEquipment", - "gCheatEasyPauseBufferEnabled", - "gCheatEasyInputBufferingEnabled", - "gNoRestrictItems", - "gFreezeTime", + CHEAT_CVAR("InfiniteAmmo"), + CHEAT_CVAR("InfiniteEponaBoost"), + CHEAT_CVAR("InfiniteHealth"), + CHEAT_CVAR("InfiniteMagic"), + CHEAT_CVAR("InfiniteMoney"), + CHEAT_CVAR("InfiniteNayru"), + CHEAT_CVAR("NoClip"), + CHEAT_CVAR("ClimbEverything"), + CHEAT_CVAR("HookshotEverything"), + CHEAT_CVAR("HookshotReachMultiplier"), + CHEAT_CVAR("MoonJumpOnL"), + CHEAT_CVAR("SuperTunic"), + CHEAT_CVAR("EasyISG"), + CHEAT_CVAR("EasyQPA"), + CHEAT_CVAR("TimelessEquipment"), + CHEAT_CVAR("EasyPauseBuffer"), + CHEAT_CVAR("EasyInputBuffer"), + CHEAT_CVAR("NoRestrictItems"), + CHEAT_CVAR("FreezeTime"), "gPrevTime", - "gDropsDontDie", - "gFireproofDekuShield", - "gShieldTwoHanded", - "gTimeSync", + CHEAT_CVAR("DropsDontDie"), + CHEAT_CVAR("FireproofDekuShield"), + CHEAT_CVAR("ShieldTwoHanded"), + CHEAT_CVAR("TimeSync"), "gDebugEnabled", - "gSkulltulaDebugEnabled", - "gSkipLogoTitle", - "gSaveFileID", - "gEnableBetaQuest", + DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), + DEV_TOOLS_CVAR("SkipLogoTitle"), + DEV_TOOLS_CVAR("SaveFileID"), + CHEAT_CVAR("EnableBetaQuest"), "gBetterDebugWarpScreen", - "gSwitchAge", + GENERAL_CVAR("SwitchAge"), "gSwitchTimeline", - "gNoRedeadFreeze", - "gNoKeeseGuayTarget", - "gBombTimerMultiplier", - "gNoFishDespawn", - "gNoBugsDespawn", + CHEAT_CVAR("NoRedeadFreeze"), + CHEAT_CVAR("NoKeeseGuayTarget"), + CHEAT_CVAR("BombTimerMultiplier"), + CHEAT_CVAR("NoFishDespawn"), + CHEAT_CVAR("NoBugsDespawn"), "gWalkModifierDoesntChangeJump", "gStatsEnabled", - "gSaveStatesEnabled", - "gSaveStatePromise", + CHEAT_CVAR("SaveStatesEnabled"), + CHEAT_CVAR("SaveStatePromise"), "gRegEditEnabled", "gPreset0", "gPreset1", - "gDekuStickCheat", + CHEAT_CVAR("DekuStick"), "gDebugWarpScreenTranslation", "gDebugSaveFileMode", "gCosmetics.Link_BodyScale.Changed", @@ -899,7 +899,7 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), PRESET_ENTRY_S32("gGoronPot", 1), PRESET_ENTRY_S32("gForgeTime", 0), - PRESET_ENTRY_S32("gCheatEasyPauseBufferEnabled", 1), + PRESET_ENTRY_S32(CHEAT_CVAR("EasyPauseBuffer"), 1), PRESET_ENTRY_S32("gDampeAllNight", 1), PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("10GSHint"), 1), PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("20GSHint"), 1), @@ -947,7 +947,7 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gAdultBunnyHood", 1), PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), - PRESET_ENTRY_S32("gCheatEasyPauseBufferEnabled", 1), + PRESET_ENTRY_S32(CHEAT_CVAR("EasyPauseBuffer"), 1), PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), PRESET_ENTRY_S32("gClimbSpeed", 4), PRESET_ENTRY_S32("gCosmetics.Goron_NeckLength", 1000), diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 40235d295..6fdf1f3b2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3149,7 +3149,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); DrawPresetSelector(PRESET_TYPE_RANDOMIZER); ImGui::EndDisabled(); @@ -3192,7 +3192,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); ImGuiWindow* window = ImGui::GetCurrentWindow(); static ImVec2 cellPadding(8.0f, 8.0f); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1921fb866..c91fd68d4 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1148,8 +1148,8 @@ extern "C" void InitOTR() { srand(now); #ifdef ENABLE_REMOTE_CONTROL SDLNet_Init(); - if (CVarGetInteger("gRemote.Enabled", 0)) { - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + if (CVarGetInteger(REMOTE_CVAR("Enabled"), 0)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Enable(); break; @@ -1174,8 +1174,8 @@ extern "C" void DeinitOTR() { SaveManager_ThreadPoolWait(); OTRAudio_Exit(); #ifdef ENABLE_REMOTE_CONTROL - if (CVarGetInteger("gRemote.Enabled", 0)) { - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + if (CVarGetInteger(REMOTE_CVAR("Enabled"), 0)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Disable(); break; @@ -1246,7 +1246,7 @@ extern "C" void Graph_StartFrame() { switch (dwScancode) { case KbScancode::LUS_KB_F5: { - if (CVarGetInteger("gSaveStatesEnabled", 0) == 0) { + if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; @@ -1268,7 +1268,7 @@ extern "C" void Graph_StartFrame() { break; } case KbScancode::LUS_KB_F6: { - if (CVarGetInteger("gSaveStatesEnabled", 0) == 0) { + if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; @@ -1283,7 +1283,7 @@ extern "C" void Graph_StartFrame() { break; } case KbScancode::LUS_KB_F7: { - if (CVarGetInteger("gSaveStatesEnabled", 0) == 0) { + if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 86c6bbfcc..f34b2fee5 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -81,6 +81,7 @@ uint32_t IsGameMasterQuest(); #define ENTRANCE_TRACKER_CVAR(var) TRACKER_CVAR("EntranceTracker." var) #define DEV_TOOLS_CVAR(var) "gDeveloperTools." var #define GENERAL_CVAR(var) "gGeneral." var +#define REMOTE_CVAR(var) "gRemote." var #ifndef __cplusplus void InitOTR(void); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 0ca0f6f89..be75a6127 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -547,7 +547,7 @@ extern std::shared_ptr mGameplayStatsWindow; void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Enhancements")) { - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS); @@ -1430,7 +1430,7 @@ void DrawEnhancementsMenu() { void DrawCheatsMenu() { if (ImGui::BeginMenu("Cheats")) { - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8.0f); ImGui::BeginTable("##cheatsMenu", 2, ImGuiTableFlags_SizingFixedFit); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); @@ -1440,32 +1440,32 @@ void DrawCheatsMenu() { ImGui::Text("Inventory:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); + UIWidgets::PaddedEnhancementCheckbox("Super Tunic", CHEAT_CVAR("SuperTunic"), true, false); UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); - UIWidgets::PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy ISG", CHEAT_CVAR("EasyISG"), true, false); UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); - UIWidgets::PaddedEnhancementCheckbox("Easy QPA", "gEzQPA", true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy QPA", CHEAT_CVAR("EasyQPA"), true, false); UIWidgets::Tooltip("Gives you the glitched damage value of the quick put away glitch."); - UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", "gTimelessEquipment", true, false); + UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", CHEAT_CVAR("TimelessEquipment"), true, false); UIWidgets::Tooltip("Allows any item to be equipped, regardless of age\nAlso allows Child to use Adult strength upgrades"); - UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); + UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", CHEAT_CVAR("NoRestrictItems"), true, false); UIWidgets::Tooltip("Allows you to use any item at any location"); - UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", CHEAT_CVAR("FireproofDekuShield"), true, false); UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); - UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); + UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", CHEAT_CVAR("ShieldTwoHanded"), true, false); UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); UIWidgets::Spacer(2.0f); ImGui::Text("Deku Sticks:"); - UIWidgets::EnhancementCombobox("gDekuStickCheat", DekuStickCheat, DEKU_STICK_NORMAL); + UIWidgets::EnhancementCombobox(CHEAT_CVAR("DekuStick"), DekuStickCheat, DEKU_STICK_NORMAL); UIWidgets::Spacer(2.0f); - UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.2fx", "##gBombTimerMultiplier", "gBombTimerMultiplier", 0.1f, 5.0f, "", 1.0f, false); - UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", "gHookshotEverything", true, false); + UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.2fx", "##gBombTimerMultiplier", CHEAT_CVAR("BombTimerMultiplier"), 0.1f, 5.0f, "", 1.0f, false); + UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", CHEAT_CVAR("HookshotEverything"), true, false); UIWidgets::Tooltip("Makes every surface in the game hookshot-able"); UIWidgets::Spacer(0); - UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", "gCheatHookshotReachMultiplier", 1.0f, 5.0f, "", 1.0f, false); + UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", CHEAT_CVAR("HookshotReachMultiplier"), 1.0f, 5.0f, "", 1.0f, false); UIWidgets::Spacer(2.0f); if (ImGui::Button("Change Age")) { - CVarSetInteger("gSwitchAge", 1); + CVarSetInteger(GENERAL_CVAR("SwitchAge"), 1); } UIWidgets::Tooltip("Switches Link's age and reloads the area."); UIWidgets::Spacer(2.0f); @@ -1478,12 +1478,12 @@ void DrawCheatsMenu() { UIWidgets::Spacer(2.0f); if (ImGui::BeginMenu("Infinite...")) { - UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney"); - UIWidgets::PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false); - UIWidgets::PaddedEnhancementCheckbox("Ammo", "gInfiniteAmmo", true, false); - UIWidgets::PaddedEnhancementCheckbox("Magic", "gInfiniteMagic", true, false); - UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", "gInfiniteNayru", true, false); - UIWidgets::PaddedEnhancementCheckbox("Epona Boost", "gInfiniteEpona", true, false); + UIWidgets::EnhancementCheckbox("Money", CHEAT_CVAR("InfiniteMoney")); + UIWidgets::PaddedEnhancementCheckbox("Health", CHEAT_CVAR("InfiniteHealth"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Ammo", CHEAT_CVAR("InfiniteAmmo"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Magic", CHEAT_CVAR("InfiniteMagic"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", CHEAT_CVAR("InfiniteNayru"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Epona Boost", CHEAT_CVAR("InfiniteEponaBoost"), true, false); ImGui::EndMenu(); } @@ -1501,13 +1501,13 @@ void DrawCheatsMenu() { UIWidgets::PaddedText("they WILL break across transitions and", true, false); UIWidgets::PaddedText("load zones (like doors). Support for", true, false); UIWidgets::PaddedText("related issues will not be provided.", true, false); - if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", "gSaveStatePromise", true, + if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", CHEAT_CVAR("SaveStatePromise"), true, false)) { - CVarSetInteger("gSaveStatesEnabled", 0); + CVarSetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - if (CVarGetInteger("gSaveStatePromise", 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", "gSaveStatesEnabled", true, + if (CVarGetInteger(CHEAT_CVAR("SaveStatePromise"), 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", CHEAT_CVAR("SaveStatesEnabled"), true, false); UIWidgets::Tooltip("F5 to save, F6 to change slots, F7 to load"); } @@ -1519,44 +1519,44 @@ void DrawCheatsMenu() { ImGui::Text("Behavior:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); + UIWidgets::PaddedEnhancementCheckbox("No Clip", CHEAT_CVAR("NoClip"), true, false); UIWidgets::Tooltip("Allows you to walk through walls"); - UIWidgets::PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); + UIWidgets::PaddedEnhancementCheckbox("Climb Everything", CHEAT_CVAR("ClimbEverything"), true, false); UIWidgets::Tooltip("Makes every surface in the game climbable"); - UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); + UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", CHEAT_CVAR("MoonJumpOnL"), true, false); UIWidgets::Tooltip("Holding L makes you float into the air"); - UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", "gCheatEasyPauseBufferEnabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", CHEAT_CVAR("EasyPauseBuffer"), true, false); UIWidgets::Tooltip("Continue holding START button when unpausing to only advance a single frame and then re-pause"); - const bool bEasyFrameAdvanceEnabled = CVarGetInteger("gCheatEasyPauseBufferEnabled", 0); - UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", "gCheatEasyInputBufferingEnabled", true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled", UIWidgets::CheckboxGraphics::Checkmark); + const bool bEasyFrameAdvanceEnabled = CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0); + UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", CHEAT_CVAR("EasyInputBuffer"), true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Inputs that are held down while the Subscreen is closing will be pressed when the game is resumed"); - UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); + UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", CHEAT_CVAR("DropsDontDie"), true, false); UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); - UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", "gNoFishDespawn", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", CHEAT_CVAR("NoFishDespawn"), true, false); UIWidgets::Tooltip("Prevents fish from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", "gNoBugsDespawn", true, false); + UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", CHEAT_CVAR("NoBugsDespawn"), true, false); UIWidgets::Tooltip("Prevents bugs from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); + UIWidgets::PaddedEnhancementCheckbox("Freeze Time", CHEAT_CVAR("FreezeTime"), true, false); UIWidgets::Tooltip("Freezes the time of day"); - UIWidgets::PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); + UIWidgets::PaddedEnhancementCheckbox("Time Sync", CHEAT_CVAR("TimeSync"), true, false); UIWidgets::Tooltip("This syncs the ingame time with the real world time"); - UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", "gNoRedeadFreeze", true, false); + UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", CHEAT_CVAR("NoRedeadFreeze"), true, false); UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream"); - UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", "gNoKeeseGuayTarget", true, false); + UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", CHEAT_CVAR("NoKeeseGuayTarget"), true, false); UIWidgets::Tooltip("Keese and Guay no longer target you and simply ignore you as if you were wearing the skull mask"); { - static int32_t betaQuestEnabled = CVarGetInteger("gEnableBetaQuest", 0); + static int32_t betaQuestEnabled = CVarGetInteger(CHEAT_CVAR("EnableBetaQuest"), 0); static int32_t lastBetaQuestEnabled = betaQuestEnabled; - static int32_t betaQuestWorld = CVarGetInteger("gBetaQuestWorld", 0xFFEF); + static int32_t betaQuestWorld = CVarGetInteger(CHEAT_CVAR("BetaQuestWorld"), 0xFFEF); static int32_t lastBetaQuestWorld = betaQuestWorld; if (!isBetaQuestEnabled) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", CHEAT_CVAR("EnableBetaQuest"), true, false); UIWidgets::Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); - betaQuestEnabled = CVarGetInteger("gEnableBetaQuest", 0); + betaQuestEnabled = CVarGetInteger(CHEAT_CVAR("EnableBetaQuest"), 0); if (betaQuestEnabled) { if (betaQuestEnabled != lastBetaQuestEnabled) { betaQuestWorld = 0; @@ -1588,15 +1588,15 @@ void DrawCheatsMenu() { } else { lastBetaQuestWorld = betaQuestWorld = 0xFFEF; - CVarClear("gBetaQuestWorld"); + CVarClear(CHEAT_CVAR("BetaQuestWorld")); } if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) { // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. lastBetaQuestEnabled = betaQuestEnabled; lastBetaQuestWorld = betaQuestWorld; - CVarSetInteger("gEnableBetaQuest", betaQuestEnabled); - CVarSetInteger("gBetaQuestWorld", betaQuestWorld); + CVarSetInteger(CHEAT_CVAR("EnableBetaQuest"), betaQuestEnabled); + CVarSetInteger(CHEAT_CVAR("BetaQuestWorld"), betaQuestWorld); std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); @@ -1624,15 +1624,15 @@ extern std::shared_ptr mMessageViewerWindow; void DrawDeveloperToolsMenu() { if (ImGui::BeginMenu("Developer Tools")) { - ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); + ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); - UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); + UIWidgets::EnhancementCheckbox("OoT Debug Mode", DEV_TOOLS_CVAR("DebugEnabled")); UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); - if (CVarGetInteger("gDebugEnabled", 0)) { - UIWidgets::EnhancementCheckbox("OoT Registry Editor", "gRegEditEnabled"); + if (CVarGetInteger(DEV_TOOLS_CVAR("DebugEnabled"), 0)) { + UIWidgets::EnhancementCheckbox("OoT Registry Editor", DEV_TOOLS_CVAR("RegEditEnabled")); UIWidgets::Tooltip("Enables the registry editor"); ImGui::Text("Debug Save File Mode:"); - UIWidgets::EnhancementCombobox("gDebugSaveFileMode", DebugSaveFileModes, 1); + UIWidgets::EnhancementCombobox(DEV_TOOLS_CVAR("DebugSaveFileMode"), DebugSaveFileModes, 1); UIWidgets::Tooltip( "Changes the behaviour of debug file select creation (creating a save file on slot 1 with debug mode on)\n" "- Off: The debug save file will be a normal savefile\n" @@ -1640,17 +1640,17 @@ void DrawDeveloperToolsMenu() { "- Maxed: The debug save file will be a save file with all of the items & upgrades" ); } - UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), true, false); UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); - UIWidgets::PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fast File Select", DEV_TOOLS_CVAR("SkipLogoTitle"), true, false); UIWidgets::Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); - if (CVarGetInteger("gSkipLogoTitle", 0)) { + if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) { ImGui::Text("Loading:"); - UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 0); + UIWidgets::EnhancementCombobox(DEV_TOOLS_CVAR("SaveFileID"), FastFileSelect, 0); }; - UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", "gBetterDebugWarpScreen", true, false); + UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", DEV_TOOLS_CVAR("BetterDebugWarpScreen"), true, false); UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day"); - UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", "gDebugWarpScreenTranslation", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", DEV_TOOLS_CVAR("DebugWarpScreenTranslation"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Translate the Debug Warp Screen based on the game language"); if (gPlayState != NULL) { UIWidgets::PaddedSeparator(); @@ -1661,12 +1661,12 @@ void DrawDeveloperToolsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (ImGui::Button("Advance 1", ImVec2(ImGui::GetContentRegionAvail().x / 2.0f, 0.0f))) { - CVarSetInteger("gFrameAdvance", 1); + CVarSetInteger(GENERAL_CVAR("FrameAdvance"), 1); } ImGui::SameLine(); ImGui::Button("Advance (Hold)"); if (ImGui::IsItemActive()) { - CVarSetInteger("gFrameAdvance", 1); + CVarSetInteger(GENERAL_CVAR("FrameAdvance"), 1); } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); @@ -1752,27 +1752,27 @@ bool isStringEmpty(std::string str) { #ifdef ENABLE_REMOTE_CONTROL void DrawRemoteControlMenu() { if (ImGui::BeginMenu("Network")) { - static std::string ip = CVarGetString("gRemote.IP", "127.0.0.1"); - static uint16_t port = CVarGetInteger("gRemote.Port", 43384); - bool isFormValid = !isStringEmpty(CVarGetString("gRemote.IP", "127.0.0.1")) && port > 1024 && port < 65535; + static std::string ip = CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1"); + static uint16_t port = CVarGetInteger(REMOTE_CVAR("Port"), 43384); + bool isFormValid = !isStringEmpty(CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1")) && port > 1024 && port < 65535; const char* remoteOptions[2] = { "Sail", "Crowd Control"}; ImGui::BeginDisabled(GameInteractor::Instance->isRemoteInteractorEnabled); ImGui::Text("Remote Interaction Scheme"); - if (UIWidgets::EnhancementCombobox("gRemote.Scheme", remoteOptions, GI_SCHEME_SAIL)) { - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + if (UIWidgets::EnhancementCombobox(REMOTE_CVAR("Scheme"), remoteOptions, GI_SCHEME_SAIL)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: case GI_SCHEME_CROWD_CONTROL: - CVarSetString("gRemote.IP", "127.0.0.1"); - CVarSetInteger("gRemote.Port", 43384); + CVarSetString(REMOTE_CVAR("IP"), "127.0.0.1"); + CVarSetInteger(REMOTE_CVAR("Port"), 43384); ip = "127.0.0.1"; port = 43384; break; } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: UIWidgets::InsertHelpHoverText( "Sail is a networking protocol designed to facilitate remote " @@ -1805,14 +1805,14 @@ void DrawRemoteControlMenu() { ImGui::Text("Remote IP & Port"); if (ImGui::InputText("##gRemote.IP", (char*)ip.c_str(), ip.capacity() + 1)) { - CVarSetString("gRemote.IP", ip.c_str()); + CVarSetString(REMOTE_CVAR("IP"), ip.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetFontSize() * 5); if (ImGui::InputScalar("##gRemote.Port", ImGuiDataType_U16, &port)) { - CVarSetInteger("gRemote.Port", port); + CVarSetInteger(REMOTE_CVAR("Port"), port); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -1825,9 +1825,9 @@ void DrawRemoteControlMenu() { const char* buttonLabel = GameInteractor::Instance->isRemoteInteractorEnabled ? "Disable" : "Enable"; if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) { if (GameInteractor::Instance->isRemoteInteractorEnabled) { - CVarSetInteger("gRemote.Enabled", 0); + CVarSetInteger(REMOTE_CVAR("Enabled"), 0); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Disable(); break; @@ -1836,9 +1836,9 @@ void DrawRemoteControlMenu() { break; } } else { - CVarSetInteger("gRemote.Enabled", 1); + CVarSetInteger(REMOTE_CVAR("Enabled"), 1); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - switch (CVarGetInteger("gRemote.Scheme", GI_SCHEME_SAIL)) { + switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Enable(); break; diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 064d59860..2af8ef9ab 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -1902,7 +1902,7 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul s32 bgId2; f32 nx, ny, nz; // unit normal of polygon - if (CVarGetInteger("gNoClip", 0) && actor != NULL && actor->id == ACTOR_PLAYER) { + if (CVarGetInteger(CHEAT_CVAR("NoClip"), 0) && actor != NULL && actor->id == ACTOR_PLAYER) { return false; } @@ -4025,7 +4025,7 @@ u32 func_80041D94(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { * SurfaceType Get Wall Flags */ s32 func_80041DB8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { - if (CVarGetInteger("gClimbEverything", 0) != 0) { + if (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0) { return (1 << 3) | D_80119D90[func_80041D94(colCtx, poly, bgId)]; } else { return D_80119D90[func_80041D94(colCtx, poly, bgId)]; @@ -4122,7 +4122,7 @@ u32 SurfaceType_GetEcho(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) * SurfaceType Is Hookshot Surface */ u32 SurfaceType_IsHookshotSurface(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { - return CVarGetInteger("gHookshotEverything", 0) || SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1; + return CVarGetInteger(CHEAT_CVAR("HookshotEverything"), 0) || SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1; } /** diff --git a/soh/src/code/z_common_data.c b/soh/src/code/z_common_data.c index 2a903b26e..491689880 100644 --- a/soh/src/code/z_common_data.c +++ b/soh/src/code/z_common_data.c @@ -8,7 +8,7 @@ void SaveContext_Init(void) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = NATURE_ID_DISABLED; gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; - gSaveContext.nextCutsceneIndex = CVarGetInteger("gBetaQuestWorld", 0xFFEF); + gSaveContext.nextCutsceneIndex = CVarGetInteger(CHEAT_CVAR("BetaQuestWorld"), 0xFFEF); gSaveContext.cutsceneTrigger = 0; gSaveContext.chamberCutsceneNum = 0; gSaveContext.nextDayTime = 0xFFFF; diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 42ea78f90..e89bd86c0 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -792,7 +792,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { if (this->unk_15A > 0) { this->unk_15A--; - if (CVarGetInteger("gDropsDontDie", 0) && (this->unk_154 <= 0)) { + if (CVarGetInteger(CHEAT_CVAR("DropsDontDie"), 0) && (this->unk_154 <= 0)) { this->unk_15A++; } } diff --git a/soh/src/code/z_kaleido_setup.c b/soh/src/code/z_kaleido_setup.c index e4001e6ce..825adf237 100644 --- a/soh/src/code/z_kaleido_setup.c +++ b/soh/src/code/z_kaleido_setup.c @@ -18,7 +18,7 @@ void KaleidoSetup_Update(PlayState* play) { play->shootingGalleryStatus <= 1 && gSaveContext.magicState != MAGIC_STATE_STEP_CAPACITY && gSaveContext.magicState != MAGIC_STATE_FILL && (play->sceneNum != SCENE_BOMBCHU_BOWLING_ALLEY || !Flags_GetSwitch(play, 0x38))) { - u8 easyPauseBufferEnabled = CVarGetInteger("gCheatEasyPauseBufferEnabled", 0); + u8 easyPauseBufferEnabled = CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0); u8 easyPauseBufferTimer = CVarGetInteger("gCheatEasyPauseBufferTimer", 0); // If start is not seen as pressed on the 2nd to last frame then we should end the easy frame advance flow diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 213ee018d..16d4434c9 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -735,7 +735,7 @@ void Minimap_Draw(PlayState* play) { // If any of these CVars are enabled, disable toggling the minimap with L, unless gEnableMapToggle is set bool enableMapToggle = - !(CVarGetInteger("gDebugEnabled", 0) || CVarGetInteger("gMoonJumpOnL", 0) || CVarGetInteger("gTurboOnL", 0)) || + !(CVarGetInteger("gDebugEnabled", 0) || CVarGetInteger(CHEAT_CVAR("MoonJumpOnL"), 0) || CVarGetInteger("gTurboOnL", 0)) || CVarGetInteger("gEnableMapToggle", 0); if (play->pauseCtx.state < 4) { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 7938bad01..fa1c61918 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1655,11 +1655,11 @@ void Message_OpenText(PlayState* play, u16 textId) { //font->msgLength, __FILE__, __LINE__); } else if (CVarGetInteger("gAskToEquip", 0) && - (((LINK_IS_ADULT || CVarGetInteger("gTimelessEquipment", 0)) && + (((LINK_IS_ADULT || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) && // 0C = Biggoron, 4B = Giant's, 4E = Mirror Shield, 50-51 = Tunics (textId == 0x0C || textId == 0x4B || textId == 0x4E || textId == 0x50 || textId == 0x51)) || - ((!LINK_IS_ADULT || CVarGetInteger("gTimelessEquipment", 0)) && + ((!LINK_IS_ADULT || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) && // 4C = Deku Shield, A4 = Kokiri Sword (textId == 0x4C || textId == 0xA4)) || // 4D == Hylian Shield diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 1881ea0e8..e642cb30f 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1539,7 +1539,7 @@ void Inventory_SwapAgeEquipment(void) { // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { + if ((CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { Flags_SetInfTable(INFTABLE_SWORDLESS); gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; } @@ -1554,7 +1554,7 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) { + if (CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; @@ -1629,7 +1629,7 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && + if ((CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { Flags_SetInfTable(INFTABLE_SWORDLESS); if (gSaveContext.childEquips.equipment == 0) { @@ -5720,7 +5720,7 @@ void Interface_Draw(PlayState* play) { if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0)) { if (gSaveContext.minigameState != 1) { // Carrots rendering if the action corresponds to riding a horse - if (interfaceCtx->unk_1EE == 8 && !CVarGetInteger("gInfiniteEpona", 0)) { + if (interfaceCtx->unk_1EE == 8 && !CVarGetInteger(CHEAT_CVAR("InfiniteEponaBoost"), 0)) { // Load Carrot Icon gDPLoadTextureBlock(OVERLAY_DISP++, gCarrotIconTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -6534,11 +6534,11 @@ void Interface_Update(PlayState* play) { D_80125A58 = Player_GetEnvironmentalHazard(play); if (D_80125A58 == 1) { - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_GORON || CVarGetInteger("gSuperTunic", 0) != 0) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_GORON || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { D_80125A58 = 0; } } else if ((Player_GetEnvironmentalHazard(play) >= 2) && (Player_GetEnvironmentalHazard(play) < 5)) { - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_ZORA || CVarGetInteger("gSuperTunic", 0) != 0) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_ZORA || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { D_80125A58 = 0; } } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index d6c84e355..09bafb53b 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -675,7 +675,7 @@ void Play_Init(GameState* thisx) { Fault_AddClient(&D_801614B8, ZeldaArena_Display, NULL, NULL); // In order to keep bunny hood equipped on first load, we need to pre-set the age reqs for the item and slot - if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger("gTimelessEquipment", 0)) { + if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) { gItemAgeReqs[ITEM_MASK_BUNNY] = AGE_REQ_NONE; if(INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY) gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_NONE; @@ -1846,7 +1846,7 @@ void Play_Main(GameState* thisx) { LOG_NUM("1", 1); } - if (CVarGetInteger("gTimeSync", 0)) { + if (CVarGetInteger(CHEAT_CVAR("TimeSync"), 0)) { const int maxRealDaySeconds = 86400; const int maxInGameDayTicks = 65536; diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 532b01eba..afec990c8 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -597,7 +597,7 @@ s32 Player_ActionToModelGroup(Player* this, s32 actionParam) { void Player_SetModelsForHoldingShield(Player* this) { if ((this->stateFlags1 & PLAYER_STATE1_SHIELDING) && ((this->itemAction < 0) || (this->itemAction == this->heldItemAction))) { - if ((CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || + if ((CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD; if (LINK_IS_CHILD && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) { @@ -793,7 +793,7 @@ s32 Player_GetStrength(void) { return PLAYER_STR_NONE; } - if (CVarGetInteger("gTimelessEquipment", 0) || LINK_IS_ADULT) { + if (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || LINK_IS_ADULT) { return strengthUpgrade; } else if (strengthUpgrade != 0) { return PLAYER_STR_BRACELET; @@ -953,9 +953,9 @@ s32 Player_GetEnvironmentalHazard(PlayState* play) { triggerEntry = &sTextTriggers[var]; if ((triggerEntry->flag != 0) && !(gSaveContext.textTriggerFlags & triggerEntry->flag) && - (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)) || + (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)) || (((var == 1) || (var == 3)) && (this->currentBoots == PLAYER_BOOTS_IRON) && - (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger("gSuperTunic", 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)))) { + (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)))) { Message_StartTextbox(play, triggerEntry->textId, NULL); gSaveContext.textTriggerFlags |= triggerEntry->flag; } @@ -1914,7 +1914,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve if (func_8002DD78(this) != 0) { Matrix_Translate(500.0f, 300.0f, 0.0f, MTXMODE_APPLY); Player_DrawHookshotReticle( - play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat("gCheatHookshotReachMultiplier", 1.0f)); + play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat(CHEAT_CVAR("HookshotReachMultiplier"), 1.0f)); } } } else if (CVarGetInteger("gBowReticle", 0) && ( diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index de068ae6c..f0188c42d 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -412,7 +412,7 @@ BgImage* func_80096A74(PolygonType1* polygon1, PlayState* play) { camera = GET_ACTIVE_CAM(play); camId = camera->camDataIdx; - if (camId == -1 && (CVarGetInteger("gNoRestrictItems", 0) || CVarGetInteger("gCrowdControl", 0))) { + if (camId == -1 && (CVarGetInteger(CHEAT_CVAR("NoRestrictItems"), 0) || CVarGetInteger("gCrowdControl", 0))) { // This prevents a crash when using items that change the // camera (such as din's fire), voiding out or dying on // scenes with prerendered backgrounds. diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index 0c7435da4..ab6747c5e 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -85,7 +85,7 @@ void ArmsHook_Wait(ArmsHook* this, PlayState* play) { if (this->actor.parent == NULL) { Player* player = GET_PLAYER(play); // get correct timer length for hookshot or longshot - s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat("gCheatHookshotReachMultiplier", 1.0f); + s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat(CHEAT_CVAR("HookshotReachMultiplier"), 1.0f); ArmsHook_SetupAction(this, ArmsHook_Shoot); func_8002D9A4(&this->actor, 20.0f); diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 7fee4b178..686d83134 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -110,8 +110,8 @@ void EnBom_Init(Actor* thisx, PlayState* play) { Actor_SetScale(thisx, 0.01f); } - if (CVarGetFloat("gBombTimerMultiplier", 1.0f) != 1.0f) { - this->timer = (s32)(70 * CVarGetFloat("gBombTimerMultiplier", 1.0f)); + if (CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f) != 1.0f) { + this->timer = (s32)(70 * CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f)); // Do the sound and scale immediately if GameInteractor hasn't already. if (!GameInteractor_GetRandomBombFuseTimerActive()) { Audio_PlayActorSound2(thisx, NA_SE_PL_TAKE_OUT_SHIELD); @@ -267,7 +267,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { } // With random bomb fuse timer or gBombTimerMultiplier, sound effect and scaling is already done on init. - if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat("gBombTimerMultiplier", 1.0f) == 1.0f) { + if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f) == 1.0f) { Audio_PlayActorSound2(thisx, NA_SE_PL_TAKE_OUT_SHIELD); Actor_SetScale(thisx, 0.01f); } @@ -281,7 +281,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { Actor_UpdateBgCheckInfo(play, thisx, 5.0f, 10.0f, 15.0f, 0x1F); if (thisx->params == BOMB_BODY) { - float timerMultiplier = CVarGetFloat("gBombTimerMultiplier", 1.0f); + float timerMultiplier = CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f); if (this->timer < (timerMultiplier == 1.0f ? 63 : (s32)(70 * timerMultiplier - 7))) { dustAccel.y = 0.2f; diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index ea0432f27..5350bfe58 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -283,7 +283,7 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->actor.yDistToWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL) && - !CVarGetInteger("gNoKeeseGuayTarget", 0)) { + !CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { EnCrow_SetupDiveAttack(this); } } @@ -321,7 +321,7 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || (this->collider.base.atFlags & AT_HIT) || (this->actor.bgCheckFlags & 9) || (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->actor.yDistToWater > -40.0f) || - CVarGetInteger("gNoKeeseGuayTarget", 0)) { + CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { if (this->collider.base.atFlags & AT_HIT) { this->collider.base.atFlags &= ~AT_HIT; Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_ATTACK); diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index f37bc73db..e51896f24 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -416,7 +416,7 @@ void EnFirefly_FlyIdle(EnFirefly* this, PlayState* play) { } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 200.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL) && - !CVarGetInteger("gNoKeeseGuayTarget", 0)) { + !CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { EnFirefly_SetupDiveAttack(this); } } @@ -495,7 +495,7 @@ void EnFirefly_DiveAttack(EnFirefly* this, PlayState* play) { Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); } if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || - CVarGetInteger("gNoKeeseGuayTarget", 0)) { + CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { EnFirefly_SetupFlyAway(this); } } diff --git a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c index 785d1fbca..0b9a383ca 100644 --- a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c +++ b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c @@ -679,7 +679,7 @@ void EnFish_UpdateCutscene(EnFish* this, PlayState* play) { // Update functions and Draw void EnFish_OrdinaryUpdate(EnFish* this, PlayState* play) { - if (this->timer > 0 && CVarGetInteger("gNoFishDespawn", 0) == 0) { + if (this->timer > 0 && CVarGetInteger(CHEAT_CVAR("NoFishDespawn"), 0) == 0) { this->timer--; } diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index f653b6ff9..379ff8a2e 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -3312,7 +3312,7 @@ void EnHorse_CheckBoost(EnHorse* thisx, PlayState* play2) { this->stateFlags |= ENHORSE_BOOST; this->stateFlags |= ENHORSE_FIRST_BOOST_REGEN; this->stateFlags |= ENHORSE_FLAG_8; - if (!CVarGetInteger("gInfiniteEpona", 0)) { this->numBoosts--; } + if (!CVarGetInteger(CHEAT_CVAR("InfiniteEponaBoost"), 0)) { this->numBoosts--; } this->boostTimer = 0; if (this->numBoosts == 0) { this->boostRegenTime = 140; diff --git a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c index 393e10a91..0d3691707 100644 --- a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c +++ b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c @@ -213,7 +213,7 @@ void EnInsect_Init(Actor* thisx, PlayState* play2) { // For bugs that aren't linked to a soil patch, we remove the "short lived" flag to prevent them from despawning // And exit early to not increment the "bugs dropped count" - if (CVarGetInteger("gNoBugsDespawn", 0) && this->soilActor == NULL) { + if (CVarGetInteger(CHEAT_CVAR("NoBugsDespawn"), 0) && this->soilActor == NULL) { this->unk_314 &= ~4; return; } diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 4514439c1..bd9eb288b 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -338,7 +338,7 @@ void func_80AE2C1C(EnRd* this, PlayState* play) { PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_CLIMBING_LADDER)) && !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { if (this->unk_306 == 0) { - if (!(this->unk_312 & PLAYER_STATE2_GRABBED_BY_ENEMY) && !CVarGetInteger("gNoRedeadFreeze", 0)) { + if (!(this->unk_312 & PLAYER_STATE2_GRABBED_BY_ENEMY) && !CVarGetInteger(CHEAT_CVAR("NoRedeadFreeze"), 0)) { player->actor.freezeTimer = 40; func_8008EEAC(play, &this->actor); GET_PLAYER(play)->unk_684 = &this->actor; @@ -570,7 +570,7 @@ void func_80AE3834(EnRd* this, PlayState* play) { s16 temp_v0 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->unk_30E - this->unk_310; if (ABS(temp_v0) < 0x2008) { - if (!(this->unk_312 & 0x80) && !CVarGetInteger("gNoRedeadFreeze", 0)) { + if (!(this->unk_312 & 0x80) && !CVarGetInteger(CHEAT_CVAR("NoRedeadFreeze"), 0)) { player->actor.freezeTimer = 60; func_800AA000(this->actor.xzDistToPlayer, 0xFF, 0x14, 0x96); func_8008EEAC(play, &this->actor); diff --git a/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c b/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c index 4582e0b3f..c05ca317a 100644 --- a/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c +++ b/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c @@ -42,7 +42,7 @@ void EnRiverSound_Init(Actor* thisx, PlayState* play) { } else if (this->actor.params == RS_SARIAS_SONG) { // Always have leading music in rando if ( - CVarGetInteger("gLostWoodsConsistentVolume", 0) || + CVarGetInteger(AUDIO_CVAR("LostWoodsConsistentVolume"), 0) || ((!CHECK_QUEST_ITEM(QUEST_SONG_LULLABY) || CHECK_QUEST_ITEM(QUEST_SONG_SARIA)) && !IS_RANDO) ) { Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index db8e2e3e4..2a69a1ada 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2073,7 +2073,7 @@ void Player_InitExplosiveIA(PlayState* play, Player* this) { this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0); if (spawnedActor != NULL) { if ((explosiveType != 0) && (play->bombchuBowlingStatus != 0)) { - if (!CVarGetInteger("gInfiniteAmmo", 0)) { + if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { play->bombchuBowlingStatus--; } if (play->bombchuBowlingStatus == 0) { @@ -2493,10 +2493,10 @@ LinkAnimationHeader* func_808346C4(PlayState* play, Player* this) { if (this->unk_870 < 0.5f) { return D_808543A4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; + !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } else { return D_808543AC[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger("gShieldTwoHanded", 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; + !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } } @@ -2748,11 +2748,11 @@ s32 func_808350A4(PlayState* play, Player* this) { func_80834380(play, this, &item, &arrowType); if (gSaveContext.minigameState == 1) { - if (!CVarGetInteger("gInfiniteAmmo", 0)) { + if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { play->interfaceCtx.hbaAmmo--; } } else if (play->shootingGalleryStatus != 0) { - if (!CVarGetInteger("gInfiniteAmmo", 0)) { + if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { play->shootingGalleryStatus--; } } else { @@ -4225,7 +4225,7 @@ s32 func_8083816C(s32 arg0) { } void func_8083819C(Player* this, PlayState* play) { - if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger("gFireproofDekuShield", 0) == 0)) { + if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger(CHEAT_CVAR("FireproofDekuShield"), 0) == 0)) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, true); Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); @@ -4338,18 +4338,18 @@ s32 func_808382DC(Player* this, PlayState* play) { if (this->unk_870 < 0.5f) { anim = D_808543BC[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger("gShieldTwoHanded", 0) && + !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } else { anim = D_808543B4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger("gShieldTwoHanded", 0) && + !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim); } else { Player_AnimPlayOnce(play, this, D_808543C4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger("gShieldTwoHanded", 0) && + !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]); } } @@ -4406,7 +4406,7 @@ s32 func_808382DC(Player* this, PlayState* play) { ((sp48 >= 0) && SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) && (this->floorTypeTimer >= D_808544F4[sp48])) || - ((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) || + ((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0) || (this->floorTypeTimer >= D_808544F4[sp48])))) { this->floorTypeTimer = 0; this->actor.colChkInfo.damage = 4; @@ -5225,7 +5225,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) { if (BgCheck_EntityLineTest1(&play->colCtx, &this->actor.world.pos, &sp74, &sp68, &sp84, true, false, false, true, &sp80) && - ((ABS(sp84->normal.y) < 600) || (CVarGetInteger("gClimbEverything", 0) != 0))) { + ((ABS(sp84->normal.y) < 600) || (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0))) { f32 nx = COLPOLY_GET_NORMAL(sp84->normal.x); f32 ny = COLPOLY_GET_NORMAL(sp84->normal.y); f32 nz = COLPOLY_GET_NORMAL(sp84->normal.z); @@ -8504,7 +8504,7 @@ void func_80842A28(PlayState* play, Player* this) { } void func_80842A88(PlayState* play, Player* this) { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Inventory_ChangeAmmo(ITEM_STICK, -1); Player_UseItem(play, this, ITEM_NONE); } @@ -8512,7 +8512,7 @@ void func_80842A88(PlayState* play, Player* this) { s32 func_80842AC4(PlayState* play, Player* this) { if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) { - if (AMMO(ITEM_STICK) != 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (AMMO(ITEM_STICK) != 0 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; @@ -8949,7 +8949,7 @@ static AnimSfxEntry D_808545F0[] = { }; void Player_Action_80843CEC(Player* this, PlayState* play) { - if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger("gSuperTunic", 0) == 0) { + if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0) { if ((play->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3) || (sFloorType == 9) || ((func_80838144(sFloorType) >= 0) && !SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId))) { @@ -10654,7 +10654,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId); // conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant anyway - if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger("gClimbEverything", 0)) { + if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0)) { /* This fixes the "started climbing a wall and then immediately fell off" bug. * The main idea is if a climbing wall is detected, double-check that it will * still be valid once climbing begins by doing a second raycast with a small @@ -10723,7 +10723,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { if ((this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) { CollisionPoly* wallPoly = this->actor.wallPoly; - if ((ABS(wallPoly->normal.y) < 600) || (CVarGetInteger("gClimbEverything", 0) != 0)) { + if ((ABS(wallPoly->normal.y) < 600) || (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0)) { f32 sp8C = COLPOLY_GET_NORMAL(wallPoly->normal.x); f32 sp88 = COLPOLY_GET_NORMAL(wallPoly->normal.y); f32 sp84 = COLPOLY_GET_NORMAL(wallPoly->normal.z); @@ -10914,7 +10914,7 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { seqMode = SEQ_MODE_STILL; } - if (play->actorCtx.targetCtx.bgmEnemy != NULL && !CVarGetInteger("gEnemyBGMDisable", 0)) { + if (play->actorCtx.targetCtx.bgmEnemy != NULL && !CVarGetInteger(AUDIO_CVAR("EnemyBGMDisable"), 0)) { seqMode = SEQ_MODE_ENEMY; Audio_SetBgmEnemyVolume(sqrtf(play->actorCtx.targetCtx.bgmEnemy->xyzDistToPlayerSq)); } @@ -10934,7 +10934,7 @@ static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 }; void func_80848A04(PlayState* play, Player* this) { f32 temp; - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { + if (CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { f32 temp2 = 1.0f; // Secondary temporary variable to use with the alleged draw flame function this->unk_860 = 200; // Keeps the stick's flame lit this->unk_85C = 1.0f; // Ensures the stick is the proper length @@ -10942,20 +10942,20 @@ void func_80848A04(PlayState* play, Player* this) { 0, 8); // I believe this draws the flame effect } - if (this->unk_85C == 0.0f && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (this->unk_85C == 0.0f && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Player_UseItem(play, this, 0xFF); return; } temp = 1.0f; - if (DECR(this->unk_860) == 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (DECR(this->unk_860) == 0 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Inventory_ChangeAmmo(ITEM_STICK, -1); this->unk_860 = 1; temp = 0.0f; this->unk_85C = temp; } else if (this->unk_860 > 200) { temp = (210 - this->unk_860) / 10.0f; - } else if (this->unk_860 < 20 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + } else if (this->unk_860 < 20 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { temp = this->unk_860 / 20.0f; this->unk_85C = temp; } @@ -11001,7 +11001,7 @@ void Player_UpdateBodyBurn(PlayState* play, Player* this) { s32 sp58; s32 sp54; - if (this->currentTunic == PLAYER_TUNIC_GORON || CVarGetInteger("gSuperTunic", 0) != 0) { + if (this->currentTunic == PLAYER_TUNIC_GORON || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { sp54 = 20; } else { sp54 = (s32)(this->linearVelocity * 0.4f) + 1; @@ -11256,7 +11256,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { func_808473D4(play, this); func_80836BEC(this, play); - if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { + if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { func_80848A04(play, this); } else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) { this->unk_860++; diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index ef825cb18..155462c33 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3286,15 +3286,15 @@ void FileChoose_Main(GameState* thisx) { gSaveContext.skyboxTime += 0x10; } - if (CVarGetInteger("gSkipLogoTitle", 0) && CVarGetInteger("gSaveFileID", FASTFILE_1) <= FASTFILE_3 && !isFastFileIdIncompatible) { - if (Save_Exist(CVarGetInteger("gSaveFileID", FASTFILE_1)) && FileChoose_IsSaveCompatible(Save_GetSaveMetaInfo(CVarGetInteger("gSaveFileID", FASTFILE_1)))) { - this->buttonIndex = CVarGetInteger("gSaveFileID", FASTFILE_1); + if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0) && CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1) <= FASTFILE_3 && !isFastFileIdIncompatible) { + if (Save_Exist(CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1)) && FileChoose_IsSaveCompatible(Save_GetSaveMetaInfo(CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1)))) { + this->buttonIndex = CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1); this->menuMode = FS_MENU_MODE_SELECT; this->selectMode = SM_LOAD_GAME; } else { isFastFileIdIncompatible = 1; } - } else if (CVarGetInteger("gSkipLogoTitle", 0) && CVarGetInteger("gSaveFileID", FASTFILE_1) == FASTFILE_MAP_SELECT) { + } else if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0) && CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1) == FASTFILE_MAP_SELECT) { this->buttonIndex = 0xFF; this->menuMode = FS_MENU_MODE_SELECT; this->selectMode = SM_LOAD_GAME; diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index d123e7e90..b4f9a6744 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -245,13 +245,13 @@ void Title_Main(GameState* thisx) { POLY_OPA_DISP = gfx; } - if (this->exit || CVarGetInteger("gSkipLogoTitle", 0)) { + if (this->exit || CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = 0xFF; gSaveContext.gameMode = 1; this->state.running = false; - if (gLoadFileSelect || CVarGetInteger("gSkipLogoTitle", 0)) + if (gLoadFileSelect || CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) SET_NEXT_GAMESTATE(&this->state, FileChoose_Init, FileChooseContext); else SET_NEXT_GAMESTATE(&this->state, Opening_Init, OpeningContext); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index cf4344027..17de25ee4 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -756,7 +756,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { for (rowStart = 0, j = 0, temp = 0, i = 0; i < 4; i++, rowStart += 4, j += 16) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->equipVtx[j], 16, 0); - bool drawGreyItems = !CVarGetInteger("gTimelessEquipment", 0); + bool drawGreyItems = !CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0); if (LINK_AGE_IN_YEARS == YEARS_CHILD) { point = CUR_UPG_VALUE(sChildUpgrades[i]); if ((point != 0) && (CUR_UPG_VALUE(sChildUpgrades[i]) != 0)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 12d7cb4dd..68185ef30 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -340,7 +340,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { gSlotAgeReqs[SLOT_TRADE_CHILD] = ( ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || - CVarGetInteger("gTimelessEquipment", 0) + CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) ) && INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY ? AGE_REQ_NONE @@ -349,7 +349,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { //also update the age requirement for the bunny hood itself gItemAgeReqs[ITEM_MASK_BUNNY] = ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || - CVarGetInteger("gTimelessEquipment", 0) + CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) ? AGE_REQ_NONE : AGE_REQ_CHILD; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h index 936f0bbdd..583cbe942 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h @@ -20,9 +20,9 @@ extern u8 gAreaGsFlags[]; #define AGE_REQ_CHILD LINK_AGE_CHILD #define AGE_REQ_NONE 9 -#define CHECK_AGE_REQ_EQUIP(i, j) (CVarGetInteger("gTimelessEquipment", 0) || (gEquipAgeReqs[i][j] == AGE_REQ_NONE) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge))) -#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) -#define CHECK_AGE_REQ_ITEM(itemIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gItemAgeReqs[itemIndex] == AGE_REQ_NONE) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge)) +#define CHECK_AGE_REQ_EQUIP(i, j) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gEquipAgeReqs[i][j] == AGE_REQ_NONE) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge))) +#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) +#define CHECK_AGE_REQ_ITEM(itemIndex) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gItemAgeReqs[itemIndex] == AGE_REQ_NONE) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge)) void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx); s32 KaleidoScope_UpdateQuestStatusPoint(PauseContext* pauseCtx, s32 point); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 059a845c3..45f644372 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1963,7 +1963,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { POLY_KAL_DISP = KaleidoScope_QuadTextureIA4(POLY_KAL_DISP, pauseCtx->nameSegment, 128, 16, 0); } - if (pauseCtx->pageIndex == PAUSE_MAP && CVarGetInteger("gSkulltulaDebugEnabled", 0) != 0) { + if (pauseCtx->pageIndex == PAUSE_MAP && CVarGetInteger(DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), 0) != 0) { if (YREG(7) != 0) { osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf("キンスタ数(%d) Get_KIN_STA=%x (%x) (%x)\n", YREG(6), GET_GS_FLAGS(YREG(6)), @@ -3994,7 +3994,7 @@ void KaleidoScope_Update(PlayState* play) // Boss Rush skips past the "Save?" window when pressing B while paused. if (CHECK_BTN_ALL(input->press.button, BTN_START) || (CHECK_BTN_ALL(input->press.button, BTN_B) && IS_BOSS_RUSH)) { - if (CVarGetInteger("gCheatEasyPauseBufferEnabled", 0) || CVarGetInteger("gCheatEasyInputBufferingEnabled", 0)) { + if (CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0) || CVarGetInteger(CHEAT_CVAR("EasyInputBuffer"), 0)) { // Easy pause buffer is 13 frames, 12 for kaledio to end, and one more to advance a single frame CVarSetInteger("gCheatEasyPauseBufferTimer", 13); } From 14c7f0c3e1c2e02eb26cd1dcb7de94c5f5ff9061 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 21 Apr 2024 09:14:46 -0500 Subject: [PATCH 174/300] More time cutscene skip fixes --- .../game-interactor/GameInteractor.h | 3 ++ .../Enhancements/timesaver_hook_handlers.cpp | 29 ++++++++++++++++--- .../actors/ovl_Obj_Dekujr/z_obj_dekujr.c | 3 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 8dc20e215..fd5611df8 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -83,6 +83,9 @@ typedef enum { // Opt: *EnMd // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, + // Opt: *ObjDekujr + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) + GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, // Opt: *EnKo // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) GI_VB_OPEN_KOKIRI_FOREST, diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 61a83b482..b920419bb 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -155,6 +155,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); // Normally happens in the cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0xAC60; if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { Item_Give(gPlayState, ITEM_SONG_REQUIEM); } @@ -183,8 +184,6 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* uint8_t isBlueWarp = 0; // Deku Tree Blue warp if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { - gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; - gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11; isBlueWarp = 1; // Dodongo's Cavern Blue warp @@ -199,9 +198,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { // Normally set in the blue warp cutscene Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); - gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; - gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3; + if (IS_RANDO) { + gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3; + } else { + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12; + } + isBlueWarp = 1; // Fire Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { @@ -209,6 +212,9 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* isBlueWarp = 1; // Water Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; + gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; isBlueWarp = 1; // Spirit Temple Blue warp @@ -222,6 +228,9 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } if (isBlueWarp) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + *should = false; gSaveContext.cutsceneIndex = 0; @@ -232,6 +241,9 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* // Flee hyrule castle cutscene if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA; + gSaveContext.cutsceneIndex = 0; *should = false; } @@ -420,6 +432,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { + // We're overriding this so that the Deku JR doesn't despawn after skipping the forest temple blue warp cutscene. + // It typically relies on the forest medallion being obtained, but that isn't given yet until after scene init + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); + } + break; + } case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: case GI_VB_GIVE_ITEM_FAIRY_OCARINA: @@ -514,6 +534,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } else { gPlayState->nextEntranceIndex = ENTR_HYRULE_FIELD_17; } + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; gPlayState->transitionType = TRANS_TYPE_FADE_WHITE; gPlayState->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.nextTransitionType = 2; diff --git a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c index ae9545825..9463d45af 100644 --- a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c +++ b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c @@ -6,6 +6,7 @@ #include "z_obj_dekujr.h" #include "objects/object_dekujr/object_dekujr.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -56,7 +57,7 @@ void ObjDekujr_Init(Actor* thisx, PlayState* play) { this->unk_19C = 0; this->unk_19B = 1; } - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { + if (!GameInteractor_Should(GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST), this)) { Actor_Kill(thisx); } else { ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f); From 5813b37415d3eb37aa7d4cdbd431ce7067ddfba2 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 21 Apr 2024 09:38:53 -0500 Subject: [PATCH 175/300] Migrate child stealth --- .../Enhancements/timesaver_hook_handlers.cpp | 7 +++++++ soh/soh/SohMenuBar.cpp | 18 ++++++------------ soh/src/code/z_play.c | 12 ------------ 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index b920419bb..700e55e18 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -280,6 +280,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = false; } } + + if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) { + if (CVarGetInteger("gTimeSavers.SkipChildStealth", false)) { + gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0; + *should = false; + } + } break; } case GI_VB_PLAY_ENTRANCE_CS: { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c11b88a62..3821f9df4 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -581,26 +581,22 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) && CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) && CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipTowerEscape", false); + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); bool someChecked = CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) || CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) || CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) || - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipTowerEscape", false); + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); ImGuiContext* g = ImGui::GetCurrentContext(); ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; @@ -612,26 +608,22 @@ void DrawEnhancementsMenu() { CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1); CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1); CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 1); CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1); CVarSetInteger("gTimeSavers.NoForcedDialog", 1); CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1); CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1); CVarSetInteger("gTimeSavers.DisableTitleCard", 1); - CVarSetInteger("gTimeSavers.SkipTowerEscape", 1); } else { CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0); CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0); CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0); CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0); CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0); CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0); CVarSetInteger("gTimeSavers.NoForcedDialog", 0); CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0); CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0); CVarSetInteger("gTimeSavers.DisableTitleCard", 0); - CVarSetInteger("gTimeSavers.SkipTowerEscape", 0); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -641,14 +633,16 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); - UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs"); UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); + UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); + UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", "gTimeSavers.SkipChildStealth", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::Tooltip("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", "gTimeSavers.SkipTowerEscape", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("Skip the tower escape sequence between Ganondorf and Ganon."); diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 3ce5eeefc..43d30f54b 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -363,18 +363,6 @@ void Play_Init(GameState* thisx) { u8 tempSetupIndex; s32 pad[2]; - // Skip Child Stealth when option is enabled, Zelda's Letter isn't obtained and Impa's reward hasn't been received - // eventChkInf[4] & 1 = Got Zelda's Letter - // eventChkInf[5] & 0x200 = Got Impa's reward - // entranceIndex 0x7A, ENTR_CASTLE_COURTYARD_GUARDS_DAY_0, Castle Courtyard - Day from crawlspace - // entranceIndex 0x400, ENTR_CASTLE_COURTYARD_ZELDA_0, Zelda's Courtyard - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH) && - !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) { - if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) { - gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0; - } - } - // Properly initialize the frame counter so it doesn't use garbage data if (!firstInit) { play->gameplayFrames = 0; From 33aef87907cb68479f754e63e37b532f18170583 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 21 Apr 2024 08:25:06 -0700 Subject: [PATCH 176/300] CVar Macro Cleanup (#4062) * Standardized CVar macros to have `CVAR_` at the front instead of the end. Removed excluded and replaced sequence macros. * Missed a few developer CVars outside of `SohMenuBar.cpp` * 1 more. --- .../Enhancements/audio/AudioCollection.cpp | 12 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 28 +- soh/soh/Enhancements/controls/InputViewer.cpp | 2 +- .../controls/SohInputEditorWindow.cpp | 6 +- .../cosmetics/CosmeticsEditor.cpp | 2 +- .../game-interactor/GameInteractor_Remote.cpp | 2 +- soh/soh/Enhancements/mods.cpp | 26 +- soh/soh/Enhancements/presets.h | 682 +++++++-------- .../randomizer/3drando/playthrough.cpp | 2 +- soh/soh/Enhancements/randomizer/draw.cpp | 4 +- .../Enhancements/randomizer/randomizer.cpp | 790 +++++++++--------- .../randomizer/randomizer_check_objects.cpp | 74 +- .../randomizer/randomizer_check_tracker.cpp | 186 ++--- .../randomizer_entrance_tracker.cpp | 44 +- .../randomizer/randomizer_item_tracker.cpp | 220 ++--- soh/soh/OTRGlobals.cpp | 18 +- soh/soh/OTRGlobals.h | 32 +- soh/soh/SaveManager.cpp | 4 +- soh/soh/SohGui.cpp | 36 +- soh/soh/SohMenuBar.cpp | 186 ++--- soh/src/code/code_800EC960.c | 2 +- soh/src/code/game.c | 4 +- soh/src/code/graph.c | 2 +- soh/src/code/z_bgcheck.c | 6 +- soh/src/code/z_camera.c | 4 +- soh/src/code/z_common_data.c | 2 +- soh/src/code/z_debug.c | 6 +- soh/src/code/z_demo.c | 8 +- soh/src/code/z_en_item00.c | 2 +- soh/src/code/z_frame_advance.c | 4 +- soh/src/code/z_kaleido_setup.c | 2 +- soh/src/code/z_map_exp.c | 2 +- soh/src/code/z_message_PAL.c | 6 +- soh/src/code/z_parameter.c | 12 +- soh/src/code/z_play.c | 4 +- soh/src/code/z_player_lib.c | 10 +- soh/src/code/z_room.c | 2 +- soh/src/code/z_sram.c | 4 +- .../actors/ovl_Arms_Hook/z_arms_hook.c | 2 +- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 8 +- .../overlays/actors/ovl_En_Crow/z_en_crow.c | 4 +- .../actors/ovl_En_Firefly/z_en_firefly.c | 4 +- .../overlays/actors/ovl_En_Fish/z_en_fish.c | 2 +- .../overlays/actors/ovl_En_Horse/z_en_horse.c | 2 +- .../actors/ovl_En_Insect/z_en_insect.c | 2 +- soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c | 4 +- .../ovl_En_River_Sound/z_en_river_sound.c | 2 +- .../actors/ovl_player_actor/z_player.c | 48 +- .../ovl_file_choose/z_file_choose.c | 14 +- .../overlays/gamestates/ovl_select/z_select.c | 30 +- .../overlays/gamestates/ovl_title/z_title.c | 4 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 2 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 4 +- .../misc/ovl_kaleido_scope/z_kaleido_scope.h | 6 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 6 +- 55 files changed, 1290 insertions(+), 1292 deletions(-) diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index 415049bbe..d637758a8 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -331,12 +331,12 @@ AudioCollection::AudioCollection() { } std::string AudioCollection::GetCvarKey(std::string sfxKey) { - auto prefix = AUDIO_CVAR("ReplacedSequences."); + auto prefix = CVAR_AUDIO("ReplacedSequences."); return prefix + sfxKey + ".value"; } std::string AudioCollection::GetCvarLockKey(std::string sfxKey) { - auto prefix = std::string(AUDIO_CVAR("ReplacedSequences.")); + auto prefix = std::string(CVAR_AUDIO("ReplacedSequences.")); return prefix + sfxKey + ".locked"; } @@ -365,7 +365,7 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) { // for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will // play the normal track as usual. if (seqId == NA_BGM_FIELD_MORNING) { - if (CVarGetInteger(AUDIO_CVAR("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { + if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { seqId = NA_BGM_FIELD_LOGIC; } } @@ -384,7 +384,7 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) { } void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) { - const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo->sfxKey; + const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo->sfxKey; excludedSequences.insert(seqInfo); includedSequences.erase(seqInfo); CVarSetInteger(cvarKey.c_str(), 1); @@ -392,7 +392,7 @@ void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) { } void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) { - const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo->sfxKey; + const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo->sfxKey; includedSequences.insert(seqInfo); excludedSequences.erase(seqInfo); CVarClear(cvarKey.c_str()); @@ -404,7 +404,7 @@ void AudioCollection::InitializeShufflePool() { for (auto& [seqId, seqInfo] : sequenceMap) { if (!seqInfo.canBeUsedAsReplacement) continue; - const std::string cvarKey = std::string(AUDIO_CVAR("Excluded.")) + seqInfo.sfxKey; + const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey; if (CVarGetInteger(cvarKey.c_str(), 0)) { excludedSequences.insert(&seqInfo); } else { diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index e809ce785..e27de6b56 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -163,17 +163,17 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence const std::string stopButton = ICON_FA_STOP + hiddenKey; const std::string previewButton = ICON_FA_PLAY + hiddenKey; - if (CVarGetInteger(AUDIO_CVAR("Playing"), 0) == sequenceId) { + if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) == sequenceId) { if (ImGui::Button(stopButton.c_str())) { func_800F5C2C(); - CVarSetInteger(AUDIO_CVAR("Playing"), 0); + CVarSetInteger(CVAR_AUDIO("Playing"), 0); } UIWidgets::Tooltip("Stop Preview"); } else { if (ImGui::Button(previewButton.c_str())) { - if (CVarGetInteger(AUDIO_CVAR("Playing"), 0) != 0) { + if (CVarGetInteger(CVAR_AUDIO("Playing"), 0) != 0) { func_800F5C2C(); - CVarSetInteger(AUDIO_CVAR("Playing"), 0); + CVarSetInteger(CVAR_AUDIO("Playing"), 0); } else { if (sequenceType == SEQ_SFX || sequenceType == SEQ_VOICE) { Audio_PlaySoundGeneral(sequenceId, &pos, 4, &freqScale, &freqScale, &reverbAdd); @@ -183,7 +183,7 @@ void DrawPreviewButton(uint16_t sequenceId, std::string sfxKey, SeqType sequence } else { // TODO: Cant do both here, so have to click preview button twice PreviewSequence(sequenceId); - CVarSetInteger(AUDIO_CVAR("Playing"), sequenceId); + CVarSetInteger(CVAR_AUDIO("Playing"), sequenceId); } } } @@ -411,7 +411,7 @@ void DrawTypeChip(SeqType type) { void AudioEditorRegisterOnSceneInitHook() { GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { - if (CVarGetInteger(AUDIO_CVAR("RandomizeAllOnNewScene"), 0)) { + if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) { AudioEditor_RandomizeAll(); } }); @@ -492,18 +492,18 @@ void AudioEditor::DrawElement() { ImGui::TableNextColumn(); if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", AUDIO_CVAR("EnemyBGMDisable")); + UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable")); UIWidgets::InsertHelpHoverText( "Disables the music change when getting close to enemies. Useful for hearing " "your custom music for each scene more often."); - UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", AUDIO_CVAR("LostWoodsConsistentVolume")); + UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume")); UIWidgets::InsertHelpHoverText( "Disables the volume shifting in the Lost Woods. Useful for hearing " "your custom music in the Lost Woods if you don't need the navigation assitance " "the volume changing provides. If toggling this while in the Lost Woods, reload " "the area for the effect to kick in." ); - UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", AUDIO_CVAR("SeqNameOverlay")); + UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay")); UIWidgets::InsertHelpHoverText( "Displays the name of the current sequence in the corner of the screen whenever a new sequence " "is loaded to the main sequence player (does not apply to fanfares or enemy BGM)." @@ -511,28 +511,28 @@ void AudioEditor::DrawElement() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); UIWidgets::EnhancementSliderInt("Overlay Duration: %d seconds", "##SeqNameOverlayDuration", - AUDIO_CVAR("SeqNameOverlayDuration"), 1, 10, "", 5); + CVAR_AUDIO("SeqNameOverlayDuration"), 1, 10, "", 5); ImGui::PopItemWidth(); ImGui::NewLine(); ImGui::PopItemWidth(); UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier", - AUDIO_CVAR("LinkVoiceFreqMultiplier"), 0.4, 2.5, "", 1.0, true, true); + CVAR_AUDIO("LinkVoiceFreqMultiplier"), 0.4, 2.5, "", 1.0, true, true); ImGui::SameLine(); const std::string resetButton = "Reset##linkVoiceFreqMultiplier"; if (ImGui::Button(resetButton.c_str())) { - CVarSetFloat(AUDIO_CVAR("LinkVoiceFreqMultiplier"), 1.0f); + CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); - UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", AUDIO_CVAR("RandomizeAllOnNewScene")); + UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", CVAR_AUDIO("RandomizeAllOnNewScene")); UIWidgets::Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene."); ImGui::NewLine(); ImGui::PushItemWidth(-FLT_MIN); UIWidgets::PaddedSeparator(); UIWidgets::PaddedText("The following options are experimental and may cause music\nto sound odd or have other undesireable effects."); - UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", AUDIO_CVAR("ExperimentalOctaveDrop")); + UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", CVAR_AUDIO("ExperimentalOctaveDrop")); UIWidgets::InsertHelpHoverText("Some custom sequences may have notes that are too high for the game's audio " "engine to play. Enabling this checkbox will cause these notes to drop a " "couple of octaves so they can still harmonize with the other notes of the " diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 084383bbd..fb476e9aa 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -60,7 +60,7 @@ void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTex } void InputViewer::DrawElement() { - if (CVarGetInteger(WINDOW_CVAR("InputViewer"), 0)) { + if (CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)) { static bool sButtonTexturesLoaded = false; if (!sButtonTexturesLoaded) { LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index ed86a59e9..02781bf04 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1680,7 +1680,7 @@ void SohInputEditorWindow::DrawMiscControlPanel() { UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select " "certain items."); UIWidgets::Spacer(0); - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed"); if (CVarGetInteger("gEnableWalkModify", 0)) { @@ -1839,7 +1839,7 @@ void SohInputEditorWindow::DrawLinkTab() { } void SohInputEditorWindow::DrawIvanTab() { - if (CVarGetInteger("gDebugEnabled", 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { DrawDebugPortTab(1, "Ivan (P2)"); return; } @@ -2246,7 +2246,7 @@ void SohInputEditorWindow::DrawElement() { ImGui::BeginTabBar("##ControllerConfigPortTabs"); DrawLinkTab(); DrawIvanTab(); - if (CVarGetInteger("gDebugEnabled", 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { DrawDebugPortTab(2); DrawDebugPortTab(3); } diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 0ec469fe0..0b0f94f21 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1345,7 +1345,7 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { } } void DrawSillyTab() { - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); if (CVarGetInteger("gLetItSnow", 0)) { if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp index 7a3f96f14..1d933d8d2 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp @@ -17,7 +17,7 @@ void GameInteractor::EnableRemoteInteractor() { return; } - if (SDLNet_ResolveHost(&remoteIP, CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1"), CVarGetInteger(REMOTE_CVAR("Port"), 43384)) == -1) { + if (SDLNet_ResolveHost(&remoteIP, CVarGetString(CVAR_REMOTE("IP"), "127.0.0.1"), CVarGetInteger(CVAR_REMOTE("Port"), 43384)) == -1) { SPDLOG_ERROR("[GameInteractor] SDLNet_ResolveHost: {}", SDLNet_GetError()); } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index f63878711..b32e7d798 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -66,7 +66,7 @@ void ReloadSceneTogglingLinkAge() { void RegisterInfiniteMoney() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("InfiniteMoney"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("InfiniteMoney"), 0) != 0) { if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) { gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); } @@ -77,7 +77,7 @@ void RegisterInfiniteMoney() { void RegisterInfiniteHealth() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("InfiniteHealth"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("InfiniteHealth"), 0) != 0) { if (gSaveContext.health < gSaveContext.healthCapacity) { gSaveContext.health = gSaveContext.healthCapacity; } @@ -88,7 +88,7 @@ void RegisterInfiniteHealth() { void RegisterInfiniteAmmo() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0) != 0) { // Deku Sticks if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) { AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); @@ -125,7 +125,7 @@ void RegisterInfiniteAmmo() { void RegisterInfiniteMagic() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("InfiniteMagic"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("InfiniteMagic"), 0) != 0) { if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) { gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30; } @@ -136,7 +136,7 @@ void RegisterInfiniteMagic() { void RegisterInfiniteNayrusLove() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("InfiniteNayru"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("InfiniteNayru"), 0) != 0) { gSaveContext.nayrusLoveTimer = 0x44B; } }); @@ -146,7 +146,7 @@ void RegisterMoonJumpOnL() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("MoonJumpOnL"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("MoonJumpOnL"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); if (CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) { @@ -161,7 +161,7 @@ void RegisterInfiniteISG() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("EasyISG"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("EasyISG"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); player->meleeWeaponState = 1; } @@ -173,7 +173,7 @@ void RegisterEzQPA() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("EasyQPA"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("EasyQPA"), 0) != 0) { Player* player = GET_PLAYER(gPlayState); player->meleeWeaponQuads[0].info.toucher.dmgFlags = 0x16171617; player->meleeWeaponQuads[1].info.toucher.dmgFlags = 0x16171617; @@ -185,7 +185,7 @@ void RegisterUnrestrictedItems() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) return; - if (CVarGetInteger(CHEAT_CVAR("NoRestrictItems"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) != 0) { u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong; memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions)); gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup; @@ -195,7 +195,7 @@ void RegisterUnrestrictedItems() { void RegisterFreezeTime() { GameInteractor::Instance->RegisterGameHook([]() { - if (CVarGetInteger(CHEAT_CVAR("FreezeTime"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("FreezeTime"), 0) != 0) { if (CVarGetInteger("gPrevTime", -1) == -1) { CVarSetInteger("gPrevTime", gSaveContext.dayTime); } @@ -214,7 +214,7 @@ void RegisterSwitchAge() { static bool warped = false; if (!GameInteractor::IsSaveLoaded(true)) { - CVarClear(GENERAL_CVAR("SwitchAge")); + CVarClear(CVAR_GENERAL("SwitchAge")); warped = false; return; } @@ -224,7 +224,7 @@ void RegisterSwitchAge() { static RoomContext* roomCtx; static s32 roomNum; - if (CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) && !warped) { + if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) && !warped) { playerPos = GET_PLAYER(gPlayState)->actor.world.pos; playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y; roomCtx = &gPlayState->roomCtx; @@ -243,7 +243,7 @@ void RegisterSwitchAge() { func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room) } warped = false; - CVarClear(GENERAL_CVAR("SwitchAge")); + CVarClear(CVAR_GENERAL("SwitchAge")); } }); } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index f34a0e90c..fc202b94f 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -283,10 +283,10 @@ const std::vector enhancementsCvars = { const std::vector cheatCvars = { "gConsoleEnabled", - WINDOW_CVAR("ActorViewer"), - WINDOW_CVAR("CollisionViewer"), - WINDOW_CVAR("DLViewer"), - WINDOW_CVAR("SaveEditor"), + CVAR_WINDOW("ActorViewer"), + CVAR_WINDOW("CollisionViewer"), + CVAR_WINDOW("DLViewer"), + CVAR_WINDOW("SaveEditor"), "gEnableWalkModify", "gWalkSpeedToggle", "gWalkModifierOne", @@ -298,53 +298,53 @@ const std::vector cheatCvars = { "gCustomizeShootingGallery", "gCustomizeBombchuBowling", "gCustomizeFishing", - CHEAT_CVAR("InfiniteAmmo"), - CHEAT_CVAR("InfiniteEponaBoost"), - CHEAT_CVAR("InfiniteHealth"), - CHEAT_CVAR("InfiniteMagic"), - CHEAT_CVAR("InfiniteMoney"), - CHEAT_CVAR("InfiniteNayru"), - CHEAT_CVAR("NoClip"), - CHEAT_CVAR("ClimbEverything"), - CHEAT_CVAR("HookshotEverything"), - CHEAT_CVAR("HookshotReachMultiplier"), - CHEAT_CVAR("MoonJumpOnL"), - CHEAT_CVAR("SuperTunic"), - CHEAT_CVAR("EasyISG"), - CHEAT_CVAR("EasyQPA"), - CHEAT_CVAR("TimelessEquipment"), - CHEAT_CVAR("EasyPauseBuffer"), - CHEAT_CVAR("EasyInputBuffer"), - CHEAT_CVAR("NoRestrictItems"), - CHEAT_CVAR("FreezeTime"), + CVAR_CHEAT("InfiniteAmmo"), + CVAR_CHEAT("InfiniteEponaBoost"), + CVAR_CHEAT("InfiniteHealth"), + CVAR_CHEAT("InfiniteMagic"), + CVAR_CHEAT("InfiniteMoney"), + CVAR_CHEAT("InfiniteNayru"), + CVAR_CHEAT("NoClip"), + CVAR_CHEAT("ClimbEverything"), + CVAR_CHEAT("HookshotEverything"), + CVAR_CHEAT("HookshotReachMultiplier"), + CVAR_CHEAT("MoonJumpOnL"), + CVAR_CHEAT("SuperTunic"), + CVAR_CHEAT("EasyISG"), + CVAR_CHEAT("EasyQPA"), + CVAR_CHEAT("TimelessEquipment"), + CVAR_CHEAT("EasyPauseBuffer"), + CVAR_CHEAT("EasyInputBuffer"), + CVAR_CHEAT("NoRestrictItems"), + CVAR_CHEAT("FreezeTime"), "gPrevTime", - CHEAT_CVAR("DropsDontDie"), - CHEAT_CVAR("FireproofDekuShield"), - CHEAT_CVAR("ShieldTwoHanded"), - CHEAT_CVAR("TimeSync"), - "gDebugEnabled", - DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), - DEV_TOOLS_CVAR("SkipLogoTitle"), - DEV_TOOLS_CVAR("SaveFileID"), - CHEAT_CVAR("EnableBetaQuest"), - "gBetterDebugWarpScreen", - GENERAL_CVAR("SwitchAge"), + CVAR_CHEAT("DropsDontDie"), + CVAR_CHEAT("FireproofDekuShield"), + CVAR_CHEAT("ShieldTwoHanded"), + CVAR_CHEAT("TimeSync"), + CVAR_DEVELOPER_TOOLS("DebugEnabled"), + CVAR_DEVELOPER_TOOLS("SkulltulaDebugEnabled"), + CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), + CVAR_DEVELOPER_TOOLS("SaveFileID"), + CVAR_CHEAT("EnableBetaQuest"), + CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), + CVAR_GENERAL("SwitchAge"), "gSwitchTimeline", - CHEAT_CVAR("NoRedeadFreeze"), - CHEAT_CVAR("NoKeeseGuayTarget"), - CHEAT_CVAR("BombTimerMultiplier"), - CHEAT_CVAR("NoFishDespawn"), - CHEAT_CVAR("NoBugsDespawn"), + CVAR_CHEAT("NoRedeadFreeze"), + CVAR_CHEAT("NoKeeseGuayTarget"), + CVAR_CHEAT("BombTimerMultiplier"), + CVAR_CHEAT("NoFishDespawn"), + CVAR_CHEAT("NoBugsDespawn"), "gWalkModifierDoesntChangeJump", "gStatsEnabled", - CHEAT_CVAR("SaveStatesEnabled"), - CHEAT_CVAR("SaveStatePromise"), - "gRegEditEnabled", + CVAR_CHEAT("SaveStatesEnabled"), + CVAR_CHEAT("SaveStatePromise"), + CVAR_DEVELOPER_TOOLS("RegEditEnabled"), "gPreset0", "gPreset1", - CHEAT_CVAR("DekuStick"), - "gDebugWarpScreenTranslation", - "gDebugSaveFileMode", + CVAR_CHEAT("DekuStick"), + CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), + CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), "gCosmetics.Link_BodyScale.Changed", "gCosmetics.Link_BodyScale.Value", "gCosmetics.Link_HeadScale.Changed", @@ -355,140 +355,140 @@ const std::vector cheatCvars = { }; const std::vector randomizerCvars = { - RANDOMIZER_SEED_CVAR("10GSHint"), - RANDOMIZER_SEED_CVAR("20GSHint"), - RANDOMIZER_SEED_CVAR("30GSHint"), - RANDOMIZER_SEED_CVAR("40GSHint"), - RANDOMIZER_SEED_CVAR("50GSHint"), - RANDOMIZER_SEED_CVAR("AllLocationsReachable"), - RANDOMIZER_SEED_CVAR("AltarHint"), - RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), - RANDOMIZER_SEED_CVAR("BlueFireArrows"), - RANDOMIZER_SEED_CVAR("BombchusInLogic"), - RANDOMIZER_SEED_CVAR("BossKeysanity"), - RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), - RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), - RANDOMIZER_SEED_CVAR("CuccosToReturn"), - RANDOMIZER_SEED_CVAR("DampeHint"), - RANDOMIZER_SEED_CVAR("DecoupleEntrances"), - RANDOMIZER_SEED_CVAR("DoorOfTime"), - RANDOMIZER_SEED_CVAR("DungeonCount"), - RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), - RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), - RANDOMIZER_SEED_CVAR("EnabledGlitches"), - RANDOMIZER_SEED_CVAR("EnabledTricks"), - RANDOMIZER_SEED_CVAR("ExcludedLocations"), - RANDOMIZER_SEED_CVAR("Forest"), - RANDOMIZER_SEED_CVAR("FullWallets"), - RANDOMIZER_SEED_CVAR("GanonTrial"), - RANDOMIZER_SEED_CVAR("GanonTrialCount"), - RANDOMIZER_SEED_CVAR("GerudoFortress"), - RANDOMIZER_SEED_CVAR("GerudoKeys"), - RANDOMIZER_SEED_CVAR("GossipStoneHints"), - RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), - RANDOMIZER_SEED_CVAR("HintClarity"), - RANDOMIZER_SEED_CVAR("HintDistribution"), - RANDOMIZER_SEED_CVAR("IceTraps"), - RANDOMIZER_SEED_CVAR("ItemPool"), - RANDOMIZER_SEED_CVAR("KakarikoGate"), - RANDOMIZER_SEED_CVAR("Keysanity"), - RANDOMIZER_SEED_CVAR("LacsDungeonCount"), - RANDOMIZER_SEED_CVAR("LacsMedallionCount"), - RANDOMIZER_SEED_CVAR("LacsRewardCount"), - RANDOMIZER_SEED_CVAR("LacsRewardOptions"), - RANDOMIZER_SEED_CVAR("LacsStoneCount"), - RANDOMIZER_SEED_CVAR("LacsTokenCount"), - RANDOMIZER_SEED_CVAR("LAHint"), - RANDOMIZER_SEED_CVAR("LinksPocket"), - RANDOMIZER_SEED_CVAR("LogicRules"), - RANDOMIZER_SEED_CVAR("MedallionCount"), - RANDOMIZER_SEED_CVAR("MixDungeons"), - RANDOMIZER_SEED_CVAR("MixedEntrances"), - RANDOMIZER_SEED_CVAR("MixGrottos"), - RANDOMIZER_SEED_CVAR("MixInteriors"), - RANDOMIZER_SEED_CVAR("MixOverworld"), - RANDOMIZER_SEED_CVAR("MQDungeonCount"), - RANDOMIZER_SEED_CVAR("MQDungeons"), - RANDOMIZER_SEED_CVAR("RainbowBridge"), - RANDOMIZER_SEED_CVAR("RewardCount"), - RANDOMIZER_SEED_CVAR("ScrubText"), - RANDOMIZER_SEED_CVAR("Shopsanity"), - RANDOMIZER_SEED_CVAR("ShopsanityPrices"), - RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), - RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), - RANDOMIZER_SEED_CVAR("ShuffleBeans"), - RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), - RANDOMIZER_SEED_CVAR("ShuffleCows"), - RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), - RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), - RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), - RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), - RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), - RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), - RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple"), - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple"), - RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), - RANDOMIZER_SEED_CVAR("ShuffleMerchants"), - RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), - RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), - RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), - RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), - RANDOMIZER_SEED_CVAR("ShuffleScrubs"), - RANDOMIZER_SEED_CVAR("ShuffleSongs"), - RANDOMIZER_SEED_CVAR("ShuffleTokens"), - RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), - RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), - RANDOMIZER_SEED_CVAR("SkipChildStealth"), - RANDOMIZER_SEED_CVAR("SkipChildZelda"), - RANDOMIZER_SEED_CVAR("SkipEponaRace"), - RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), - RANDOMIZER_SEED_CVAR("SkipTowerEscape"), - RANDOMIZER_SEED_CVAR("StartingAge"), - RANDOMIZER_SEED_CVAR("StartingConsumables"), - RANDOMIZER_SEED_CVAR("StartingBoleroOfFire"), - RANDOMIZER_SEED_CVAR("StartingDekuShield"), - RANDOMIZER_SEED_CVAR("StartingEponasSong"), - RANDOMIZER_SEED_CVAR("StartingKokiriSword"), - RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), - RANDOMIZER_SEED_CVAR("StartingMinuetOfForest"), - RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow"), - RANDOMIZER_SEED_CVAR("StartingOcarina"), - RANDOMIZER_SEED_CVAR("StartingPreludeOfLight"), - RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit"), - RANDOMIZER_SEED_CVAR("StartingSariasSong"), - RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater"), - RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), - RANDOMIZER_SEED_CVAR("StartingSongOfStorms"), - RANDOMIZER_SEED_CVAR("StartingSongOfTime"), - RANDOMIZER_SEED_CVAR("StartingSunsSong"), - RANDOMIZER_SEED_CVAR("StartingZeldasLullaby"), - RANDOMIZER_SEED_CVAR("StoneCount"), - RANDOMIZER_SEED_CVAR("SunlightArrows"), - RANDOMIZER_SEED_CVAR("TokenCount"), - RANDOMIZER_SEED_CVAR("WarpSongText"), - RANDOMIZER_SEED_CVAR("ZorasFountain"), - RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), - RANDOMIZER_SEED_CVAR("GregHint"), - RANDOMIZER_SEED_CVAR("ManualSeedEntry"), - RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), - RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), - RANDOMIZER_SEED_CVAR("TriforceHunt"), - RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), - RANDOMIZER_SEED_CVAR("SariaHint"), - RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), - RANDOMIZER_SEED_CVAR("FrogsHint"), - RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), - RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), + CVAR_RANDOMIZER_SETTING("10GSHint"), + CVAR_RANDOMIZER_SETTING("20GSHint"), + CVAR_RANDOMIZER_SETTING("30GSHint"), + CVAR_RANDOMIZER_SETTING("40GSHint"), + CVAR_RANDOMIZER_SETTING("50GSHint"), + CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), + CVAR_RANDOMIZER_SETTING("AltarHint"), + CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), + CVAR_RANDOMIZER_SETTING("BlueFireArrows"), + CVAR_RANDOMIZER_SETTING("BombchusInLogic"), + CVAR_RANDOMIZER_SETTING("BossKeysanity"), + CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), + CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), + CVAR_RANDOMIZER_SETTING("CuccosToReturn"), + CVAR_RANDOMIZER_SETTING("DampeHint"), + CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), + CVAR_RANDOMIZER_SETTING("DoorOfTime"), + CVAR_RANDOMIZER_SETTING("DungeonCount"), + CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), + CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), + CVAR_RANDOMIZER_SETTING("EnabledGlitches"), + CVAR_RANDOMIZER_SETTING("EnabledTricks"), + CVAR_RANDOMIZER_SETTING("ExcludedLocations"), + CVAR_RANDOMIZER_SETTING("Forest"), + CVAR_RANDOMIZER_SETTING("FullWallets"), + CVAR_RANDOMIZER_SETTING("GanonTrial"), + CVAR_RANDOMIZER_SETTING("GanonTrialCount"), + CVAR_RANDOMIZER_SETTING("GerudoFortress"), + CVAR_RANDOMIZER_SETTING("GerudoKeys"), + CVAR_RANDOMIZER_SETTING("GossipStoneHints"), + CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), + CVAR_RANDOMIZER_SETTING("HintClarity"), + CVAR_RANDOMIZER_SETTING("HintDistribution"), + CVAR_RANDOMIZER_SETTING("IceTraps"), + CVAR_RANDOMIZER_SETTING("ItemPool"), + CVAR_RANDOMIZER_SETTING("KakarikoGate"), + CVAR_RANDOMIZER_SETTING("Keysanity"), + CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), + CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), + CVAR_RANDOMIZER_SETTING("LacsRewardCount"), + CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), + CVAR_RANDOMIZER_SETTING("LacsStoneCount"), + CVAR_RANDOMIZER_SETTING("LacsTokenCount"), + CVAR_RANDOMIZER_SETTING("LAHint"), + CVAR_RANDOMIZER_SETTING("LinksPocket"), + CVAR_RANDOMIZER_SETTING("LogicRules"), + CVAR_RANDOMIZER_SETTING("MedallionCount"), + CVAR_RANDOMIZER_SETTING("MixDungeons"), + CVAR_RANDOMIZER_SETTING("MixedEntrances"), + CVAR_RANDOMIZER_SETTING("MixGrottos"), + CVAR_RANDOMIZER_SETTING("MixInteriors"), + CVAR_RANDOMIZER_SETTING("MixOverworld"), + CVAR_RANDOMIZER_SETTING("MQDungeonCount"), + CVAR_RANDOMIZER_SETTING("MQDungeons"), + CVAR_RANDOMIZER_SETTING("RainbowBridge"), + CVAR_RANDOMIZER_SETTING("RewardCount"), + CVAR_RANDOMIZER_SETTING("ScrubText"), + CVAR_RANDOMIZER_SETTING("Shopsanity"), + CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), + CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), + CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), + CVAR_RANDOMIZER_SETTING("ShuffleBeans"), + CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), + CVAR_RANDOMIZER_SETTING("ShuffleCows"), + CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), + CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), + CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), + CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), + CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), + CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), + CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), + CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), + CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), + CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), + CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), + CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), + CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), + CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), + CVAR_RANDOMIZER_SETTING("ShuffleSongs"), + CVAR_RANDOMIZER_SETTING("ShuffleTokens"), + CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), + CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), + CVAR_RANDOMIZER_SETTING("SkipChildStealth"), + CVAR_RANDOMIZER_SETTING("SkipChildZelda"), + CVAR_RANDOMIZER_SETTING("SkipEponaRace"), + CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), + CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), + CVAR_RANDOMIZER_SETTING("StartingAge"), + CVAR_RANDOMIZER_SETTING("StartingConsumables"), + CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), + CVAR_RANDOMIZER_SETTING("StartingDekuShield"), + CVAR_RANDOMIZER_SETTING("StartingEponasSong"), + CVAR_RANDOMIZER_SETTING("StartingKokiriSword"), + CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), + CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), + CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), + CVAR_RANDOMIZER_SETTING("StartingOcarina"), + CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight"), + CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), + CVAR_RANDOMIZER_SETTING("StartingSariasSong"), + CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), + CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), + CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), + CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), + CVAR_RANDOMIZER_SETTING("StartingSunsSong"), + CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), + CVAR_RANDOMIZER_SETTING("StoneCount"), + CVAR_RANDOMIZER_SETTING("SunlightArrows"), + CVAR_RANDOMIZER_SETTING("TokenCount"), + CVAR_RANDOMIZER_SETTING("WarpSongText"), + CVAR_RANDOMIZER_SETTING("ZorasFountain"), + CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), + CVAR_RANDOMIZER_SETTING("GregHint"), + CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), + CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), + CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), + CVAR_RANDOMIZER_SETTING("TriforceHunt"), + CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), + CVAR_RANDOMIZER_SETTING("SariaHint"), + CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), + CVAR_RANDOMIZER_SETTING("FrogsHint"), + CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), + CVAR_RANDOMIZER_ENHANCEMENT("QuestItemFanfares"), }; const std::vector vanillaPlusPresetEntries = { @@ -857,7 +857,7 @@ const std::vector randomizerPresetEntries = { }; const std::vector spockRacePresetEntries = { - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LogicRules"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LogicRules"), 0), PRESET_ENTRY_S32("gTextSpeed", 5), PRESET_ENTRY_S32("gMweepSpeed", 5), PRESET_ENTRY_S32("gClimbSpeed", 4), @@ -899,55 +899,55 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), PRESET_ENTRY_S32("gGoronPot", 1), PRESET_ENTRY_S32("gForgeTime", 0), - PRESET_ENTRY_S32(CHEAT_CVAR("EasyPauseBuffer"), 1), + PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1), PRESET_ENTRY_S32("gDampeAllNight", 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("10GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("20GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("30GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("40GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("50GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), 0), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DampeHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), - PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations( + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchusInLogic"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1), + PRESET_ENTRY_CPP_STRING(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), FormatLocations( { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("FullWallets"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GregHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 5), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_GREG), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ScrubText"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_COUNT), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_AFFORDABLE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 5), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubText"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_COUNT), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_AFFORDABLE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildStealth"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingConsumables"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1), }; const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gAdultBunnyHood", 1), PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), - PRESET_ENTRY_S32(CHEAT_CVAR("EasyPauseBuffer"), 1), + PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1), PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), PRESET_ENTRY_S32("gClimbSpeed", 4), PRESET_ENTRY_S32("gCosmetics.Goron_NeckLength", 1000), @@ -980,55 +980,55 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32("gNoForcedNavi", 1), PRESET_ENTRY_S32("gNoInputForCredits", 1), PRESET_ENTRY_S32("gPauseAnyCursor", 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("10GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("20GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("30GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("40GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("50GSHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), 0), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DampeHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), - PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations( + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchusInLogic"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1), + PRESET_ENTRY_CPP_STRING(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), FormatLocations( { RC_MARKET_10_BIG_POES, RC_KAK_40_GOLD_SKULLTULA_REWARD, RC_KAK_50_GOLD_SKULLTULA_REWARD, RC_ZR_FROGS_OCARINA_GAME })), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("FullWallets"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GregHint"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 0), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 5), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_NO_LOGIC), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_GREG), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ScrubText"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 0), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_COUNT), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_ALL), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 5), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_NO_LOGIC), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_GREG), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ScrubText"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_REWARDS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_COUNT), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_ALL), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildStealth"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingConsumables"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1), PRESET_ENTRY_S32("gSeparateArrows", 1), PRESET_ENTRY_S32("gSkipScarecrow", 1), PRESET_ENTRY_S32("gSkulltulaFreeze", 1), @@ -1039,33 +1039,33 @@ const std::vector s6PresetEntries = { PRESET_ENTRY_S32("gFastChests", 1), PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 4), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), - PRESET_ENTRY_CPP_STRING(RANDOMIZER_SEED_CVAR("ExcludedLocations"), FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED_DEKU), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SKIP), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_FAST), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_OFF), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MedallionCount"), 6), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_MEDALLIONS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_STARTWITH), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_ON), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingConsumables"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingDekuShield"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingOcarina"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ZorasFountain"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 4), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_CPP_STRING(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), FormatLocations({ RC_DEKU_THEATER_MASK_OF_TRUTH })), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_CLOSED_DEKU), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_FAST), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IceTraps"), RO_ICE_TRAPS_OFF), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MedallionCount"), 6), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_MEDALLIONS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_STARTWITH), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), RO_GENERIC_ON), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildStealth"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingConsumables"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingDekuShield"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 0), }; const std::vector hellModePresetEntries = { @@ -1073,51 +1073,51 @@ const std::vector hellModePresetEntries = { PRESET_ENTRY_S32("gFastChests", 1), PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GanonTrialCount"), 6), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_ONSLAUGHT), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ItemPool"), RO_ITEM_POOL_MINIMAL), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_OPEN), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("LinksPocket"), RO_LINKS_POCKET_NOTHING), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_RANDOM_NUMBER), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_FOUR_ITEMS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_TYCOON), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleCows"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_DUNGEONS), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_ALL), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_RANDOM), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_ANYWHERE), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("SunlightArrows"), 1), - PRESET_ENTRY_S32(RANDOMIZER_SEED_CVAR("ZorasFountain"), 2), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrialCount"), 6), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("IceTraps"), RO_ICE_TRAPS_ONSLAUGHT), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ItemPool"), RO_ITEM_POOL_MINIMAL), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_OPEN), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_NOTHING), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_RANDOM_NUMBER), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_FOUR_ITEMS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_SHOPSANITY_PRICE_TYCOON), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleCows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_LACS_DUNGEONS), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_ALL), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildStealth"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_ANYWHERE), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 2), }; typedef struct PresetDefinition { diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 8fb8aa9b2..e1a5656ea 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -42,7 +42,7 @@ int Playthrough_Init(uint32_t seed, std::unordered_mapgetItemId == RG_GERUDO_FORTRESS_SMALL_KEY ? Randomizer_GetSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA : DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY); - s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), 1); + s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchKeyColors"), 1); s16 color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_SMALL_KEY; s16 colors[9][3] = { { 4, 195, 46 }, // Forest Temple @@ -63,7 +63,7 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GANONS_CASTLE_BOSS_KEY ? DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY) : DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY); - s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), 1); + s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchKeyColors"), 1); s16 color_slot; color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY; s16 colors[6][3] = { diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 6fdf1f3b2..40b3daaf3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2831,143 +2831,143 @@ void GenerateRandomizerImgui(std::string seed = "") { CVarSave(); std::unordered_map cvarSettings; - cvarSettings[RSK_LOGIC_RULES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS); - cvarSettings[RSK_ALL_LOCATIONS_REACHABLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("AllLocationsReachable"), RO_GENERIC_ON); - cvarSettings[RSK_FOREST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED); - cvarSettings[RSK_KAK_GATE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("KakarikoGate"), RO_KAK_GATE_CLOSED); - cvarSettings[RSK_DOOR_OF_TIME] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_CLOSED); - cvarSettings[RSK_ZORAS_FOUNTAIN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ZorasFountain"), 0); - cvarSettings[RSK_STARTING_AGE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingAge"), RO_AGE_CHILD); - cvarSettings[RSK_GERUDO_FORTRESS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL); - cvarSettings[RSK_RAINBOW_BRIDGE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_VANILLA); - cvarSettings[RSK_RAINBOW_BRIDGE_STONE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StoneCount"), 3); - cvarSettings[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MedallionCount"), 6); - cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("RewardCount"), 9); - cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DungeonCount"), 8); - cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TokenCount"), 100); - cvarSettings[RSK_BRIDGE_OPTIONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), 0); - cvarSettings[RSK_GANONS_TRIALS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER); - cvarSettings[RSK_TRIAL_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrialCount"), 6); - cvarSettings[RSK_STARTING_OCARINA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); - cvarSettings[RSK_SHUFFLE_OCARINA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), 0) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); - cvarSettings[RSK_STARTING_KOKIRI_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); - cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), 0) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); - cvarSettings[RSK_SHUFFLE_MASTER_SWORD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMasterSword"), 0); - cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingDekuShield"), 0); - cvarSettings[RSK_STARTING_ZELDAS_LULLABY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingZeldasLullaby"), 0); - cvarSettings[RSK_STARTING_EPONAS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingEponasSong"), 0); - cvarSettings[RSK_STARTING_SARIAS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSariasSong"), 0); - cvarSettings[RSK_STARTING_SUNS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSunsSong"), 0); - cvarSettings[RSK_STARTING_SONG_OF_TIME] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSongOfTime"), 0); - cvarSettings[RSK_STARTING_SONG_OF_STORMS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSongOfStorms"), 0); - cvarSettings[RSK_STARTING_MINUET_OF_FOREST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMinuetOfForest"), 0); - cvarSettings[RSK_STARTING_BOLERO_OF_FIRE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingBoleroOfFire"), 0); - cvarSettings[RSK_STARTING_SERENADE_OF_WATER] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater"), 0); - cvarSettings[RSK_STARTING_REQUIEM_OF_SPIRIT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit"), 0); - cvarSettings[RSK_STARTING_NOCTURNE_OF_SHADOW] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow"), 0); - cvarSettings[RSK_STARTING_PRELUDE_OF_LIGHT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingPreludeOfLight"), 0); - cvarSettings[RSK_STARTING_SKULLTULA_TOKEN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), 0); - cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON); - cvarSettings[RSK_SHUFFLE_SONGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS); - cvarSettings[RSK_SHUFFLE_TOKENS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF); - cvarSettings[RSK_SHOPSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF); - cvarSettings[RSK_SHOPSANITY_PRICES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED); - cvarSettings[RSK_SHOPSANITY_PRICES_AFFORDABLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), RO_SHOPSANITY_OFF); - cvarSettings[RSK_SHUFFLE_SCRUBS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_OFF); - cvarSettings[RSK_SHUFFLE_COWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleCows"), 0); - cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), 0); - cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBeans"), 0); - cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF); - cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), RO_GENERIC_OFF); - cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("EnableBombchuDrops"), 0); - cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BombchusInLogic"), 0); - cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); + cvarSettings[RSK_LOGIC_RULES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS); + cvarSettings[RSK_ALL_LOCATIONS_REACHABLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), RO_GENERIC_ON); + cvarSettings[RSK_FOREST] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_CLOSED); + cvarSettings[RSK_KAK_GATE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_CLOSED); + cvarSettings[RSK_DOOR_OF_TIME] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED); + cvarSettings[RSK_ZORAS_FOUNTAIN] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 0); + cvarSettings[RSK_STARTING_AGE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_CHILD); + cvarSettings[RSK_GERUDO_FORTRESS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL); + cvarSettings[RSK_RAINBOW_BRIDGE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA); + cvarSettings[RSK_RAINBOW_BRIDGE_STONE_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StoneCount"), 3); + cvarSettings[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MedallionCount"), 6); + cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("RewardCount"), 9); + cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("DungeonCount"), 8); + cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TokenCount"), 100); + cvarSettings[RSK_BRIDGE_OPTIONS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), 0); + cvarSettings[RSK_GANONS_TRIALS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER); + cvarSettings[RSK_TRIAL_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrialCount"), 6); + cvarSettings[RSK_STARTING_OCARINA] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 0); + cvarSettings[RSK_SHUFFLE_OCARINA] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), 0) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 0); + cvarSettings[RSK_STARTING_KOKIRI_SWORD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingKokiriSword"), 0); + cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), 0) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingKokiriSword"), 0); + cvarSettings[RSK_SHUFFLE_MASTER_SWORD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), 0); + cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingDekuShield"), 0); + cvarSettings[RSK_STARTING_ZELDAS_LULLABY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), 0); + cvarSettings[RSK_STARTING_EPONAS_SONG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingEponasSong"), 0); + cvarSettings[RSK_STARTING_SARIAS_SONG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSariasSong"), 0); + cvarSettings[RSK_STARTING_SUNS_SONG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSunsSong"), 0); + cvarSettings[RSK_STARTING_SONG_OF_TIME] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), 0); + cvarSettings[RSK_STARTING_SONG_OF_STORMS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), 0); + cvarSettings[RSK_STARTING_MINUET_OF_FOREST] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), 0); + cvarSettings[RSK_STARTING_BOLERO_OF_FIRE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), 0); + cvarSettings[RSK_STARTING_SERENADE_OF_WATER] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), 0); + cvarSettings[RSK_STARTING_REQUIEM_OF_SPIRIT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), 0); + cvarSettings[RSK_STARTING_NOCTURNE_OF_SHADOW] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), 0); + cvarSettings[RSK_STARTING_PRELUDE_OF_LIGHT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight"), 0); + cvarSettings[RSK_STARTING_SKULLTULA_TOKEN] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), 0); + cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON); + cvarSettings[RSK_SHUFFLE_SONGS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS); + cvarSettings[RSK_SHUFFLE_TOKENS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF); + cvarSettings[RSK_SHOPSANITY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF); + cvarSettings[RSK_SHOPSANITY_PRICES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED); + cvarSettings[RSK_SHOPSANITY_PRICES_AFFORDABLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), RO_SHOPSANITY_OFF); + cvarSettings[RSK_SHUFFLE_SCRUBS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_OFF); + cvarSettings[RSK_SHUFFLE_COWS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), 0); + cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 0); + cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), 0); + cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF); + cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), RO_GENERIC_OFF); + cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 0); + cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BombchusInLogic"), 0); + cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 0); // if we skip child zelda, we start with zelda's letter, and malon starts // at the ranch, so we should *not* shuffle the weird egg - cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0) == 0) && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), 0)); - cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), 0); - cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), 0); - cvarSettings[RSK_ITEM_POOL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ItemPool"), RO_ITEM_POOL_BALANCED); - cvarSettings[RSK_ICE_TRAPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("IceTraps"), RO_ICE_TRAPS_NORMAL); - cvarSettings[RSK_TOT_ALTAR_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("AltarHint"), RO_GENERIC_ON); - cvarSettings[RSK_LIGHT_ARROWS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LAHint"), RO_GENERIC_ON); - cvarSettings[RSK_DAMPES_DIARY_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DampeHint"), RO_GENERIC_OFF); - cvarSettings[RSK_GREG_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GregHint"), RO_GENERIC_OFF); - cvarSettings[RSK_SARIA_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SariaHint"), RO_GENERIC_OFF); - cvarSettings[RSK_FROGS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("FrogsHint"), RO_GENERIC_OFF); - cvarSettings[RSK_WARP_SONG_HINTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("WarpSongText"), RO_GENERIC_OFF); - cvarSettings[RSK_SCRUB_TEXT_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ScrubText"), RO_GENERIC_OFF); - cvarSettings[RSK_KAK_10_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("10GSHint"), RO_GENERIC_OFF); - cvarSettings[RSK_KAK_20_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("20GSHint"), RO_GENERIC_OFF); - cvarSettings[RSK_KAK_30_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("30GSHint"), RO_GENERIC_OFF); - cvarSettings[RSK_KAK_40_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("40GSHint"), RO_GENERIC_OFF); - cvarSettings[RSK_KAK_50_SKULLS_HINT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("50GSHint"), RO_GENERIC_OFF); - cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING); - cvarSettings[RSK_HINT_CLARITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("HintClarity"), RO_HINT_CLARITY_CLEAR); - cvarSettings[RSK_HINT_DISTRIBUTION] = CVarGetInteger(RANDOMIZER_SEED_CVAR("HintDistribution"), RO_HINT_DIST_BALANCED); - cvarSettings[RSK_BLUE_FIRE_ARROWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BlueFireArrows"), 0); - cvarSettings[RSK_SUNLIGHT_ARROWS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SunlightArrows"), 0); - cvarSettings[RSK_KEYSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_GERUDO_KEYS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA); - cvarSettings[RSK_KEYRINGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_OFF); - int maxKeyringCount = (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; - cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = std::min(CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), maxKeyringCount), maxKeyringCount); + cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 0) == 0) && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), 0)); + cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), 0); + cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), 0); + cvarSettings[RSK_ITEM_POOL] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ItemPool"), RO_ITEM_POOL_BALANCED); + cvarSettings[RSK_ICE_TRAPS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IceTraps"), RO_ICE_TRAPS_NORMAL); + cvarSettings[RSK_TOT_ALTAR_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("AltarHint"), RO_GENERIC_ON); + cvarSettings[RSK_LIGHT_ARROWS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LAHint"), RO_GENERIC_ON); + cvarSettings[RSK_DAMPES_DIARY_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("DampeHint"), RO_GENERIC_OFF); + cvarSettings[RSK_GREG_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GregHint"), RO_GENERIC_OFF); + cvarSettings[RSK_SARIA_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SariaHint"), RO_GENERIC_OFF); + cvarSettings[RSK_FROGS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("FrogsHint"), RO_GENERIC_OFF); + cvarSettings[RSK_WARP_SONG_HINTS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("WarpSongText"), RO_GENERIC_OFF); + cvarSettings[RSK_SCRUB_TEXT_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ScrubText"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_10_SKULLS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("10GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_20_SKULLS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("20GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_30_SKULLS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("30GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_40_SKULLS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("40GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_KAK_50_SKULLS_HINT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("50GSHint"), RO_GENERIC_OFF); + cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING); + cvarSettings[RSK_HINT_CLARITY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("HintClarity"), RO_HINT_CLARITY_CLEAR); + cvarSettings[RSK_HINT_DISTRIBUTION] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("HintDistribution"), RO_HINT_DIST_BALANCED); + cvarSettings[RSK_BLUE_FIRE_ARROWS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 0); + cvarSettings[RSK_SUNLIGHT_ARROWS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 0); + cvarSettings[RSK_KEYSANITY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_GERUDO_KEYS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA); + cvarSettings[RSK_KEYRINGS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_OFF); + int maxKeyringCount = (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; + cvarSettings[RSK_KEYRINGS_RANDOM_COUNT] = std::min(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), maxKeyringCount), maxKeyringCount); // Don't allow this to be on if Gerudo Fortress Carpenters is anything other than Normal cvarSettings[RSK_KEYRINGS_GERUDO_FORTRESS] = - (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) - ? CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), RO_GENERIC_OFF) : RO_GENERIC_OFF; - cvarSettings[RSK_KEYRINGS_FOREST_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple"), 0); - cvarSettings[RSK_KEYRINGS_FIRE_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple"), 0); - cvarSettings[RSK_KEYRINGS_WATER_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple"), 0); - cvarSettings[RSK_KEYRINGS_SPIRIT_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple"), 0); - cvarSettings[RSK_KEYRINGS_SHADOW_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple"), 0); - cvarSettings[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell"), 0); - cvarSettings[RSK_KEYRINGS_GTG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG"), 0); - cvarSettings[RSK_KEYRINGS_GANONS_CASTLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle"), 0); - cvarSettings[RSK_BOSS_KEYSANITY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - cvarSettings[RSK_GANONS_BOSS_KEY] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA); - cvarSettings[RSK_LACS_STONE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsStoneCount"), 3); - cvarSettings[RSK_LACS_MEDALLION_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 6); - cvarSettings[RSK_LACS_REWARD_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardCount"), 9); - cvarSettings[RSK_LACS_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 8); - cvarSettings[RSK_LACS_TOKEN_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsTokenCount"), 100); - cvarSettings[RSK_LACS_OPTIONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), 0); - cvarSettings[RSK_STARTING_CONSUMABLES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingConsumables"), 0); - cvarSettings[RSK_FULL_WALLETS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("FullWallets"), 0); + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) + ? CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), RO_GENERIC_OFF) : RO_GENERIC_OFF; + cvarSettings[RSK_KEYRINGS_FOREST_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), 0); + cvarSettings[RSK_KEYRINGS_FIRE_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), 0); + cvarSettings[RSK_KEYRINGS_WATER_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), 0); + cvarSettings[RSK_KEYRINGS_SPIRIT_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), 0); + cvarSettings[RSK_KEYRINGS_SHADOW_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), 0); + cvarSettings[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), 0); + cvarSettings[RSK_KEYRINGS_GTG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), 0); + cvarSettings[RSK_KEYRINGS_GANONS_CASTLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), 0); + cvarSettings[RSK_BOSS_KEYSANITY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + cvarSettings[RSK_GANONS_BOSS_KEY] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA); + cvarSettings[RSK_LACS_STONE_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsStoneCount"), 3); + cvarSettings[RSK_LACS_MEDALLION_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), 6); + cvarSettings[RSK_LACS_REWARD_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 9); + cvarSettings[RSK_LACS_DUNGEON_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), 8); + cvarSettings[RSK_LACS_TOKEN_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsTokenCount"), 100); + cvarSettings[RSK_LACS_OPTIONS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), 0); + cvarSettings[RSK_STARTING_CONSUMABLES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingConsumables"), 0); + cvarSettings[RSK_FULL_WALLETS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("FullWallets"), 0); // RANDOTODO implement chest minigame shuffle with keysanity cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME] = false; cvarSettings[RSK_LANGUAGE] = CVarGetInteger("gLanguages", 0); - cvarSettings[RSK_CUCCO_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 7); - cvarSettings[RSK_BIG_POE_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 10); + cvarSettings[RSK_CUCCO_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7); + cvarSettings[RSK_BIG_POE_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 10); // If we skip child zelda, skip child stealth is pointless, so this needs to be reflected in the spoiler log - cvarSettings[RSK_SKIP_CHILD_STEALTH] = !CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0) && CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildStealth"), 0); + cvarSettings[RSK_SKIP_CHILD_STEALTH] = !CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 0) && CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildStealth"), 0); - cvarSettings[RSK_SKIP_EPONA_RACE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipEponaRace"), 0); - cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipTowerEscape"), 0); - cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVarGetInteger(RANDOMIZER_SEED_CVAR("CompleteMaskQuest"), 0); - cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipScarecrowsSong"), 0); - cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes"), 0); + cvarSettings[RSK_SKIP_EPONA_RACE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 0); + cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 0); + cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 0); + cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 0); + cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), 0); - cvarSettings[RSK_SKULLS_SUNS_SONG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), 0); + cvarSettings[RSK_SKULLS_SUNS_SONG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), 0); // Link's Pocket has to have a dungeon reward if the other rewards are shuffled to end of dungeon. - cvarSettings[RSK_LINKS_POCKET] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON ? - CVarGetInteger(RANDOMIZER_SEED_CVAR("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) : RO_LINKS_POCKET_DUNGEON_REWARD; + cvarSettings[RSK_LINKS_POCKET] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON ? + CVarGetInteger(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) : RO_LINKS_POCKET_DUNGEON_REWARD; if (OTRGlobals::Instance->HasMasterQuest() && OTRGlobals::Instance->HasOriginal()) { // If both OTRs are loaded. - cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE); - cvarSettings[RSK_MQ_DUNGEON_COUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12); + cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE); + cvarSettings[RSK_MQ_DUNGEON_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12); } else if (OTRGlobals::Instance->HasMasterQuest()) { // If only Master Quest is loaded. cvarSettings[RSK_RANDOM_MQ_DUNGEONS] = RO_MQ_DUNGEONS_SET_NUMBER; @@ -2978,52 +2978,52 @@ void GenerateRandomizerImgui(std::string seed = "") { cvarSettings[RSK_MQ_DUNGEON_COUNT] = 0; } - cvarSettings[RSK_TRIFORCE_HUNT] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0); - cvarSettings[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 30); - cvarSettings[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 20); + cvarSettings[RSK_TRIFORCE_HUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), 0); + cvarSettings[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30); + cvarSettings[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), 20); - cvarSettings[RSK_MQ_DEKU_TREE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsDekuTree"), 0); - cvarSettings[RSK_MQ_DODONGOS_CAVERN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsDodongosCavern"), 0); - cvarSettings[RSK_MQ_JABU_JABU] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsJabuJabu"), 0); - cvarSettings[RSK_MQ_FOREST_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsForestTemple"), 0); - cvarSettings[RSK_MQ_FIRE_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsFireTemple"), 0); - cvarSettings[RSK_MQ_WATER_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsWaterTemple"), 0); - cvarSettings[RSK_MQ_SPIRIT_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsSpiritTemple"), 0); - cvarSettings[RSK_MQ_SHADOW_TEMPLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsShadowTemple"), 0); - cvarSettings[RSK_MQ_BOTTOM_OF_THE_WELL] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsBottomOfTheWell"), 0); - cvarSettings[RSK_MQ_ICE_CAVERN] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsIceCavern"), 0); - cvarSettings[RSK_MQ_GTG] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsGTG"), 0); - cvarSettings[RSK_MQ_GANONS_CASTLE] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonsGanonsCastle"), 0); + cvarSettings[RSK_MQ_DEKU_TREE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree"), 0); + cvarSettings[RSK_MQ_DODONGOS_CAVERN] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern"), 0); + cvarSettings[RSK_MQ_JABU_JABU] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu"), 0); + cvarSettings[RSK_MQ_FOREST_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple"), 0); + cvarSettings[RSK_MQ_FIRE_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple"), 0); + cvarSettings[RSK_MQ_WATER_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple"), 0); + cvarSettings[RSK_MQ_SPIRIT_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple"), 0); + cvarSettings[RSK_MQ_SHADOW_TEMPLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple"), 0); + cvarSettings[RSK_MQ_BOTTOM_OF_THE_WELL] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell"), 0); + cvarSettings[RSK_MQ_ICE_CAVERN] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), 0); + cvarSettings[RSK_MQ_GTG] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), 0); + cvarSettings[RSK_MQ_GANONS_CASTLE] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), 0); // Enable if any of the entrance rando options are enabled. - cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), RO_GENERIC_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_BOSS_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); - cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_OWL_DROPS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOwlDrops"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_WARP_SONGS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF); - cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns"), RO_GENERIC_OFF); - cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixedEntrances"), RO_GENERIC_OFF); - cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixDungeons"), RO_GENERIC_OFF); - cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixBosses"), RO_GENERIC_OFF); - cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixOverworld"), RO_GENERIC_OFF); - cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixInteriors"), RO_GENERIC_OFF); - cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("MixGrottos"), RO_GENERIC_OFF); - cvarSettings[RSK_DECOUPLED_ENTRANCES] = CVarGetInteger(RANDOMIZER_SEED_CVAR("DecoupleEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_BOSS_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_OWL_DROPS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_WARP_SONGS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), RO_GENERIC_OFF); + cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixDungeons"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixBosses"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixOverworld"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixInteriors"), RO_GENERIC_OFF); + cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixGrottos"), RO_GENERIC_OFF); + cvarSettings[RSK_DECOUPLED_ENTRANCES] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), RO_GENERIC_OFF); // todo: this efficently when we build out cvar array support std::set excludedLocations; - std::stringstream excludedLocationStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), "")); + std::stringstream excludedLocationStringStream(CVarGetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), "")); std::string excludedLocationString; while (getline(excludedLocationStringStream, excludedLocationString, ',')) { excludedLocations.insert((RandomizerCheck)std::stoi(excludedLocationString)); @@ -3032,7 +3032,7 @@ void GenerateRandomizerImgui(std::string seed = "") { // todo: better way to sort out linking tricks rather than name std::set enabledTricks; - std::stringstream enabledTrickStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), "")); + std::stringstream enabledTrickStringStream(CVarGetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), "")); std::string enabledTrickString; while (getline(enabledTrickStringStream, enabledTrickString, ',')) { enabledTricks.insert((RandomizerTrick)std::stoi(enabledTrickString)); @@ -3149,13 +3149,13 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); DrawPresetSelector(PRESET_TYPE_RANDOMIZER); ImGui::EndDisabled(); UIWidgets::Spacer(0); - UIWidgets::EnhancementCheckbox("Manual seed entry", RANDOMIZER_SEED_CVAR("ManualSeedEntry"), false, ""); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ManualSeedEntry"), 0)) { + UIWidgets::EnhancementCheckbox("Manual seed entry", CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), false, ""); + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0)) { ImGui::Text("Seed"); ImGui::InputText("##RandomizerSeed", seedString, MAX_SEED_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); UIWidgets::Tooltip( @@ -3174,14 +3174,14 @@ void RandomizerSettingsWindow::DrawElement() { } UIWidgets::Spacer(0); - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT); if (ImGui::Button("Generate Randomizer")) { - GenerateRandomizer(CVarGetInteger(RANDOMIZER_SEED_CVAR("ManualSeedEntry"), 0) ? seedString : ""); + GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : ""); } ImGui::EndDisabled(); UIWidgets::Spacer(0); - if (!CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { + if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { std::string spoilerfilepath = CVarGetString("gSpoilerLog", ""); ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str()); } @@ -3192,7 +3192,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGuiWindow* window = ImGui::GetCurrentWindow(); static ImVec2 cellPadding(8.0f, 8.0f); @@ -3209,7 +3209,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::PopItemFlag(); ImGui::TableNextRow(); - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // COLUMN 1 - Area Access ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; @@ -3230,7 +3230,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "boy no longer blocks the path out of the forest." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Forest"), randoForest, RO_FOREST_CLOSED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("Forest"), randoForest, RO_FOREST_CLOSED); UIWidgets::PaddedSeparator(); @@ -3243,7 +3243,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - The gate is always open. The happy mask shop " "will open immediately after obtaining Zelda's letter." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("KakarikoGate"), randoKakarikoGate, RO_KAK_GATE_CLOSED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("KakarikoGate"), randoKakarikoGate, RO_KAK_GATE_CLOSED); UIWidgets::PaddedSeparator(); @@ -3258,7 +3258,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Open - The Door of Time is permanently open with no requirements." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("DoorOfTime"), randoDoorOfTime, RO_DOOROFTIME_CLOSED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("DoorOfTime"), randoDoorOfTime, RO_DOOROFTIME_CLOSED); UIWidgets::PaddedSeparator(); @@ -3275,7 +3275,7 @@ void RandomizerSettingsWindow::DrawElement() { "Open - King Zora has already mweeped out of the way in both " "time periods. Ruto's Letter is removed from the item pool." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ZorasFountain"), randoZorasFountain, RO_ZF_CLOSED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ZorasFountain"), randoZorasFountain, RO_ZF_CLOSED); UIWidgets::PaddedSeparator(); @@ -3289,9 +3289,9 @@ void RandomizerSettingsWindow::DrawElement() { //Starting Age //Disabled when Forest is set to Closed or under very specific conditions - bool disableRandoStartingAge = CVarGetInteger(RANDOMIZER_SEED_CVAR("Forest"), RO_FOREST_CLOSED) == RO_FOREST_CLOSED || - ((CVarGetInteger(RANDOMIZER_SEED_CVAR("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED) && - (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), RO_GENERIC_OFF) == RO_GENERIC_OFF)); // closed door of time with ocarina shuffle off + bool disableRandoStartingAge = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_CLOSED) == RO_FOREST_CLOSED || + ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED) && + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == RO_GENERIC_OFF)); // closed door of time with ocarina shuffle off static const char* disableRandoStartingAgeText = "This option is disabled due to other options making the game unbeatable."; ImGui::Text("%s", Settings::StartingAge.GetName().c_str()); @@ -3300,7 +3300,7 @@ void RandomizerSettingsWindow::DrawElement() { "Starting as adult means you start with the Master Sword in your inventory.\n" "The child option is forcefully set if it would conflict with other options." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("StartingAge"), randoStartingAge, RO_AGE_CHILD, disableRandoStartingAge, disableRandoStartingAgeText, RO_AGE_CHILD); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("StartingAge"), randoStartingAge, RO_AGE_CHILD, disableRandoStartingAge, disableRandoStartingAgeText, RO_AGE_CHILD); UIWidgets::PaddedSeparator(); @@ -3318,7 +3318,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Only \"Normal\" is compatible with Gerudo Fortress Key Rings." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GerudoFortress"), randoGerudoFortress, RO_GF_NORMAL); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("GerudoFortress"), randoGerudoFortress, RO_GF_NORMAL); UIWidgets::PaddedSeparator(); @@ -3347,9 +3347,9 @@ void RandomizerSettingsWindow::DrawElement() { "Greg - Find Greg the Green Rupee." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("RainbowBridge"), randoRainbowBridge, RO_BRIDGE_VANILLA); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("RainbowBridge"), randoRainbowBridge, RO_BRIDGE_VANILLA); ImGui::PopItemWidth(); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("RainbowBridge"), RO_BRIDGE_VANILLA)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA)) { case RO_BRIDGE_ALWAYS_OPEN: break; case RO_BRIDGE_VANILLA: @@ -3367,19 +3367,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - RANDOMIZER_SEED_CVAR("StoneCount"), 1, 3, "", 3, true, true, false); + CVAR_RANDOMIZER_SETTING("StoneCount"), 1, 3, "", 3, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - RANDOMIZER_SEED_CVAR("StoneCount"), 1, 4, "", 4, true, true, false); + CVAR_RANDOMIZER_SETTING("StoneCount"), 1, 4, "", 4, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - RANDOMIZER_SEED_CVAR("StoneCount"), 1, 3, "", 3, true, true, false); + CVAR_RANDOMIZER_SETTING("StoneCount"), 1, 3, "", 3, true, true, false); break; } break; @@ -3396,19 +3396,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 6, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("MedallionCount"), 1, 6, "", 6, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 7, "", 7, true, true, false); + CVAR_RANDOMIZER_SETTING("MedallionCount"), 1, 7, "", 7, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - RANDOMIZER_SEED_CVAR("MedallionCount"), 1, 6, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("MedallionCount"), 1, 6, "", 6, true, true, false); break; } break; @@ -3425,19 +3425,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - RANDOMIZER_SEED_CVAR("RewardCount"), 1, 9, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("RewardCount"), 1, 9, "", 9, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - RANDOMIZER_SEED_CVAR("RewardCount"), 1, 10, "", 10, true, true, false); + CVAR_RANDOMIZER_SETTING("RewardCount"), 1, 10, "", 10, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - RANDOMIZER_SEED_CVAR("RewardCount"), 1, 9, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("RewardCount"), 1, 9, "", 9, true, true, false); break; } @@ -3455,25 +3455,25 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps open the bridge, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), randoBridgeRewardOptions, RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD)) { case RO_BRIDGE_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 8, "", 8, true, true, false); + CVAR_RANDOMIZER_SETTING("DungeonCount"), 1, 8, "", 8, true, true, false); break; case RO_BRIDGE_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 9, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("DungeonCount"), 1, 9, "", 9, true, true, false); break; case RO_BRIDGE_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - RANDOMIZER_SEED_CVAR("DungeonCount"), 1, 8, "", 8, true, true, false); + CVAR_RANDOMIZER_SETTING("DungeonCount"), 1, 8, "", 8, true, true, false); break; } break; case RO_BRIDGE_TOKENS: UIWidgets::PaddedEnhancementSliderInt("Token Count: %d", "##RandoTokenCount", - RANDOMIZER_SEED_CVAR("TokenCount"), 1, 100, "", 100, true, true, false); + CVAR_RANDOMIZER_SETTING("TokenCount"), 1, 100, "", 100, true, true, false); break; case RO_BRIDGE_GREG: break; @@ -3494,11 +3494,11 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Random Number - A Random number and set of trials will be required." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GanonTrial"), randoGanonsTrial, RO_GANONS_TRIALS_SET_NUMBER); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("GanonTrial"), randoGanonsTrial, RO_GANONS_TRIALS_SET_NUMBER); ImGui::PopItemWidth(); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) == RO_GANONS_TRIALS_SET_NUMBER) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) == RO_GANONS_TRIALS_SET_NUMBER) { UIWidgets::PaddedEnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", - RANDOMIZER_SEED_CVAR("GanonTrialCount"), 1, 6, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("GanonTrialCount"), 1, 6, "", 6, true, true, false); UIWidgets::InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); } @@ -3522,46 +3522,46 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Selection - Leave unchecked for Vanilla and checked for Master Quest." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("MQDungeons"), randoMqDungeons, RO_MQ_DUNGEONS_NONE); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("MQDungeons"), randoMqDungeons, RO_MQ_DUNGEONS_NONE); ImGui::PopItemWidth(); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER) { UIWidgets::PaddedEnhancementSliderInt( - "Master Quest Dungeon Count: %d", "##RandoMqDungeonCount", RANDOMIZER_SEED_CVAR("MQDungeonCount"), 1, - 12, "", CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12), true, true, false); + "Master Quest Dungeon Count: %d", "##RandoMqDungeonCount", CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 1, + 12, "", CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12), true, true, false); } - else if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { + else if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { UIWidgets::EnhancementCheckbox("Deku Tree##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsDekuTree")); + CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree")); UIWidgets::EnhancementCheckbox("Dodongo's Cavern##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsDodongosCavern")); + CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern")); UIWidgets::EnhancementCheckbox("Jabu Jabu's Belly##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsJabuJabu")); + CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu")); UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsForestTemple")); + CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple")); UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsFireTemple")); + CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple")); UIWidgets::EnhancementCheckbox("Water Temple##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsWaterTemple")); + CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple")); UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsSpiritTemple")); + CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple")); UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsShadowTemple")); + CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple")); UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsBottomOfTheWell")); + CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell")); UIWidgets::EnhancementCheckbox("Ice Cavern##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsIceCavern")); - UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeMqDungeons", RANDOMIZER_SEED_CVAR("MQDungeonsGTG")); + CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern")); + UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeMqDungeons", CVAR_RANDOMIZER_SETTING("MQDungeonsGTG")); UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeMqDungeons", - RANDOMIZER_SEED_CVAR("MQDungeonsGanonsCastle")); + CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle")); } UIWidgets::PaddedSeparator(); } - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // Triforce Hunt - UIWidgets::EnhancementCheckbox("Triforce Hunt", RANDOMIZER_SEED_CVAR("TriforceHunt")); + UIWidgets::EnhancementCheckbox("Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt")); UIWidgets::InsertHelpHoverText( "Pieces of the Triforce of Courage have been scattered across the world. Find them all to finish the game!\n\n" "When the required amount of pieces have been found, the game is saved and Ganon's Boss key is given " @@ -3569,26 +3569,26 @@ void RandomizerSettingsWindow::DrawElement() { "Keep in mind Ganon might not be logically beatable when \"All Locations Reachable\" is turned off." ); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), 0)) { // Triforce Hunt (total pieces) UIWidgets::Spacer(0); - int totalPieces = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 30); + int totalPieces = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30); ImGui::Text("Triforce Pieces in the world: %d", totalPieces); UIWidgets::InsertHelpHoverText( "The amount of Triforce pieces that will be placed in the world. " "Keep in mind seed generation can fail if more pieces are placed than there are junk items in the item pool." ); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##TriforceHuntTotalPieces", RANDOMIZER_SEED_CVAR("TriforceHuntTotalPieces"), 1, 100, "", 30); + UIWidgets::EnhancementSliderInt("", "##TriforceHuntTotalPieces", CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 1, 100, "", 30); // Triforce Hunt (required pieces) - int requiredPieces = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 20); + int requiredPieces = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), 20); ImGui::Text("Triforce Pieces to win: %d", requiredPieces); UIWidgets::InsertHelpHoverText( "The amount of Triforce pieces required to win the game." ); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##TriforceHuntRequiredPieces", RANDOMIZER_SEED_CVAR("TriforceHuntRequiredPieces"), 1, totalPieces, "", 20); + UIWidgets::EnhancementSliderInt("", "##TriforceHuntRequiredPieces", CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), 1, totalPieces, "", 20); } UIWidgets::PaddedSeparator(); @@ -3615,7 +3615,7 @@ void RandomizerSettingsWindow::DrawElement() { "- Bottom of the Well will be open for adult after playing Song of Storms to the Windmill guy as child.\n" "- Gerudo Training Ground will be open for child after adult has paid to open the gate once." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), randoShuffleDungeonsEntrances, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), randoShuffleDungeonsEntrances, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); @@ -3628,12 +3628,12 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Full - Shuffle the entrances of all boss rooms together. Child may be expected to defeat Phantom Ganon and/or Bongo Bongo." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), randoShuffleBossEntrances, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), randoShuffleBossEntrances, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); // Shuffle Overworld Entrances - UIWidgets::EnhancementCheckbox("Shuffle Overworld Entrances", RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances")); + UIWidgets::EnhancementCheckbox("Shuffle Overworld Entrances", CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle the pool of Overworld entrances, which corresponds to almost all loading zones between overworld areas.\n" "\n" @@ -3656,12 +3656,12 @@ void RandomizerSettingsWindow::DrawElement() { "- Temple of Time\n" "- Kakariko Potion Shop" ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), randoShuffleInteriorsEntrances, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), randoShuffleInteriorsEntrances, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); UIWidgets::PaddedSeparator(); // Shuffle Grotto Entrances - UIWidgets::EnhancementCheckbox("Shuffle Grotto Entrances", RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances")); + UIWidgets::EnhancementCheckbox("Shuffle Grotto Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle the pool of grotto entrances, including all graves, small Fairy fountains and the Deku Theatre." ); @@ -3669,7 +3669,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Owl Drops - UIWidgets::EnhancementCheckbox("Shuffle Owl Drops", RANDOMIZER_SEED_CVAR("ShuffleOwlDrops")); + UIWidgets::EnhancementCheckbox("Shuffle Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops")); UIWidgets::InsertHelpHoverText( "Randomize where Kaepora Gaebora (the Owl) drops you at when you talk " "to him at Lake Hylia or at the top of Death Mountain Trail." @@ -3678,7 +3678,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Warp Songs - UIWidgets::EnhancementCheckbox("Shuffle Warp Songs", RANDOMIZER_SEED_CVAR("ShuffleWarpSongs")); + UIWidgets::EnhancementCheckbox("Shuffle Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs")); UIWidgets::InsertHelpHoverText( "Randomize where each of the 6 warp songs leads to." ); @@ -3686,7 +3686,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Overworld Spawns - UIWidgets::EnhancementCheckbox("Shuffle Overworld Spawns", RANDOMIZER_SEED_CVAR("ShuffleOverworldSpawns")); + UIWidgets::EnhancementCheckbox("Shuffle Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns")); UIWidgets::InsertHelpHoverText( "Randomize where you start as Child or Adult when loading a save in the Overworld. This " "means you may not necessarily spawn inside Link's House or Temple of Time.\n" @@ -3700,7 +3700,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Decouple Entrances - UIWidgets::EnhancementCheckbox("Decouple Entrances", RANDOMIZER_SEED_CVAR("DecoupleEntrances")); + UIWidgets::EnhancementCheckbox("Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances")); UIWidgets::InsertHelpHoverText( "Decouple entrances when shuffling them. This means you are no longer guaranteed " "to end up back where you came from when you go back through an entrance.\n" @@ -3712,7 +3712,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Mixed Entrance Pools - UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", RANDOMIZER_SEED_CVAR("MixedEntrances")); + UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances")); UIWidgets::InsertHelpHoverText( "Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose " "entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n" @@ -3722,36 +3722,36 @@ void RandomizerSettingsWindow::DrawElement() { "vice versa, while overworld entrances are shuffled in their own separate pool and indoors stay vanilla." ); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("MixedEntrances"), RO_GENERIC_OFF)) { - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonsEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Dungeons", RANDOMIZER_SEED_CVAR("MixDungeons")); + UIWidgets::EnhancementCheckbox("Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons")); UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool"); } - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Bosses", RANDOMIZER_SEED_CVAR("MixBosses")); + UIWidgets::EnhancementCheckbox("Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses")); UIWidgets::InsertHelpHoverText("Boss entrances will be part of the mixed pool"); } - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOverworldEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Overworld", RANDOMIZER_SEED_CVAR("MixOverworld")); + UIWidgets::EnhancementCheckbox("Mix Overworld", CVAR_RANDOMIZER_SETTING("MixOverworld")); UIWidgets::InsertHelpHoverText("Overworld entrances will be part of the mixed pool"); } - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleInteriorsEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Interiors", RANDOMIZER_SEED_CVAR("MixInteriors")); + UIWidgets::EnhancementCheckbox("Mix Interiors", CVAR_RANDOMIZER_SETTING("MixInteriors")); UIWidgets::InsertHelpHoverText("Interior entrances will be part of the mixed pool"); } - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGrottosEntrances"), RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF)) { UIWidgets::Spacer(0); ImGui::SetCursorPosX(20); - UIWidgets::EnhancementCheckbox("Mix Grottos", RANDOMIZER_SEED_CVAR("MixGrottos")); + UIWidgets::EnhancementCheckbox("Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos")); UIWidgets::InsertHelpHoverText("Grotto entrances will be part of the mixed pool"); } } @@ -3764,7 +3764,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::EndTabItem(); } - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (ImGui::BeginTabItem("Items")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoStartingInventory", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { @@ -3796,7 +3796,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Songs can appear at any location." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleSongs"), randoShuffleSongs, RO_SONG_SHUFFLE_SONG_LOCATIONS); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), randoShuffleSongs, RO_SONG_SHUFFLE_SONG_LOCATIONS); UIWidgets::PaddedSeparator(); @@ -3814,9 +3814,9 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "All Tokens - Shuffle all 100 GS tokens." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleTokens"), randoTokensanity, RO_TOKENSANITY_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), randoTokensanity, RO_TOKENSANITY_OFF); - UIWidgets::PaddedEnhancementCheckbox("Nighttime GS expect Sun's Song", RANDOMIZER_SEED_CVAR("GsExpectSunsSong"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Nighttime GS expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), true, false); UIWidgets::InsertHelpHoverText( "All Golden Skulltulas that require nighttime to appear will only be " "expected to be collected after getting Sun's Song." @@ -3826,9 +3826,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Kokiri Sword // Disabled when Start with Kokiri Sword is active - bool disableShuffleKokiriSword = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingKokiriSword"), 0); + bool disableShuffleKokiriSword = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingKokiriSword"), 0); static const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), + UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), disableShuffleKokiriSword, disableShuffleKokiriSwordText); UIWidgets::InsertHelpHoverText( "Shuffles the Kokiri Sword into the item pool.\n" @@ -3840,9 +3840,9 @@ void RandomizerSettingsWindow::DrawElement() { //Shuffle Master Sword //RANDOTODO: Disable when Start with Master Sword is active - // bool disableShuffleMasterSword = CvarGetInteger(RANDOMIZER_SEED_CVAR("StartingMasterSword"), 0); + // bool disableShuffleMasterSword = CvarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMasterSword"), 0); // static const char* disableShuffleMasterSwordText = "This option is disabled because \"Start with Master Sword\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleMasterSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleMasterSword")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleMasterSword.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleMasterSword")); UIWidgets::InsertHelpHoverText( "Shuffles the Master Sword into the item pool.\n" "\n" @@ -3854,9 +3854,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Ocarinas // Disabled when Start with Ocarina is active - bool disableShuffleOcarinas = CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingOcarina"), 0); + bool disableShuffleOcarinas = CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 0); static const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), + UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), disableShuffleOcarinas, disableShuffleOcarinasText); UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" @@ -3868,9 +3868,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle Weird Egg // Disabled when Skip Child Zelda is active - bool disableShuffleWeirdEgg = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); + bool disableShuffleWeirdEgg = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 0); static const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled."; - UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), + UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), disableShuffleWeirdEgg, disableShuffleWeirdEggText); UIWidgets::InsertHelpHoverText( "Shuffles the Weird Egg from Malon in to the item pool. Enabling " @@ -3887,7 +3887,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Gerudo Membership Card - UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleGerudoToken")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken")); UIWidgets::InsertHelpHoverText( "Shuffles the Gerudo Membership Card into the item pool.\n" "\n" @@ -3917,10 +3917,10 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Random - Vanilla shop items will be shuffled among different shops, and each shop will contain a random number(1-4) of non-vanilla shop items.\n" ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Shopsanity"), randoShopsanity, RO_SHOPSANITY_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("Shopsanity"), randoShopsanity, RO_SHOPSANITY_OFF); // Shopsanity Prices - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF)) { case RO_SHOPSANITY_OFF: case RO_SHOPSANITY_ZERO_ITEMS: // no need to show it if there aren't shop slots in the pool break; @@ -3932,9 +3932,9 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "X Wallet - Randomized between 5 and the wallet's max size, in multiples of 5" ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), randoShopsanityPrices, RO_SHOPSANITY_PRICE_BALANCED); - UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShopsanityPricesAffordable"), - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED, + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), randoShopsanityPrices, RO_SHOPSANITY_PRICE_BALANCED); + UIWidgets::EnhancementCheckbox(Settings::ShopsanityPricesAffordable.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_SHOPSANITY_PRICE_BALANCED) == RO_SHOPSANITY_PRICE_BALANCED, "This can only apply to a wallet range."); UIWidgets::InsertHelpHoverText("Random selection between the selected wallet tier's affordable price and the affordable prices of the preceding wallet tiers.\n\n" "Affordable prices per tier: starter = 10, adult = 105, giant = 205, tycoon = 505\n\n" @@ -3954,17 +3954,17 @@ void RandomizerSettingsWindow::DrawElement() { "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" "\n" "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), randoShuffleScrubs, RO_SCRUBS_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), randoShuffleScrubs, RO_SCRUBS_OFF); UIWidgets::PaddedSeparator(); // Shuffle Cows - UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleCows")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleCows")); UIWidgets::InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleBeans")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleBeans")); UIWidgets::InsertHelpHoverText( "Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean " "Salesman to sell a random item at a price of 60 rupees." @@ -3985,12 +3985,12 @@ void RandomizerSettingsWindow::DrawElement() { "Granny's item will only be offered after you have traded in the Odd Mushroom when Shuffle Adult Trade is on. " "Otherwise when off, you will need to have found the Claim Check to buy her item (simulating the trade quest is complete)." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), randoShuffleMerchants, RO_SHUFFLE_MERCHANTS_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), randoShuffleMerchants, RO_SHUFFLE_MERCHANTS_OFF); UIWidgets::PaddedSeparator(); // Shuffle Frog Song Rupees - UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees")); UIWidgets::InsertHelpHoverText( "Shuffles 5 Purple Rupees into to the item pool, and allows\n" "you to earn items by playing songs at the Frog Choir.\n" @@ -4002,7 +4002,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Shuffle Adult Trade Quest - UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), RANDOMIZER_SEED_CVAR("ShuffleAdultTrade")); + UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade")); UIWidgets::InsertHelpHoverText( "Adds all of the adult trade quest items into the pool, each of which " "can be traded for a unique reward.\n" @@ -4019,9 +4019,9 @@ void RandomizerSettingsWindow::DrawElement() { // Shuffle 100 GS Reward // Forcefully enabled if Ganon's Boss Key is on the cursed man bool forceEnable100GSShuffle = - (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS); + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS); static const char* disable100GSRewardText = "This option is forcefully enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\""; - UIWidgets::EnhancementCheckbox(Settings::Shuffle100GSReward.GetName().c_str(), RANDOMIZER_SEED_CVAR("Shuffle100GSReward"), + UIWidgets::EnhancementCheckbox(Settings::Shuffle100GSReward.GetName().c_str(), CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), forceEnable100GSShuffle, disable100GSRewardText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::InsertHelpHoverText( "Shuffle the item the cursed rich man in the House of Skulltula gives when you " @@ -4055,7 +4055,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Spiritual stones and medallions can appear anywhere." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), randoShuffleDungeonRewards, RO_DUNGEON_REWARDS_END_OF_DUNGEON); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), randoShuffleDungeonRewards, RO_DUNGEON_REWARDS_END_OF_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4074,7 +4074,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Maps & Compasses can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), randoShuffleMapsAndCompasses, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), randoShuffleMapsAndCompasses, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4095,7 +4095,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Small Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("Keysanity"), randoShuffleSmallKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("Keysanity"), randoShuffleSmallKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4118,30 +4118,30 @@ void RandomizerSettingsWindow::DrawElement() { "other than Vanilla, then the maximum amount of Key Rings that can be selected by Random or " "Count will be 9. Otherwise, the maximum amount of Key Rings will be 8." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), randoShuffleKeyRings, RO_KEYRINGS_OFF); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), randoShuffleKeyRings, RO_KEYRINGS_OFF); ImGui::PopItemWidth(); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKeyRings"), RO_KEYRINGS_OFF)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_OFF)) { case RO_KEYRINGS_COUNT: - maxKeyringCount = (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; + maxKeyringCount = (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; UIWidgets::PaddedEnhancementSliderInt("Key Ring Count: %d", "##RandomizeShuffleKeyRingsRandomCount", - RANDOMIZER_SEED_CVAR("ShuffleKeyRingsRandomCount"), 1, + CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), 1, maxKeyringCount, "", maxKeyringCount, true, true, false); break; case RO_KEYRINGS_SELECTION: disableGFKeyring = - CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) != RO_GF_NORMAL || CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA; - UIWidgets::EnhancementCheckbox("Gerudo Fortress##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGerudoFortress"), + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) != RO_GF_NORMAL || CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA; + UIWidgets::EnhancementCheckbox("Gerudo Fortress##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), disableGFKeyring, "Disabled because the currently selected Gerudo Fortress Carpenters\n setting and/or Gerudo Fortress Keys setting is incompatible with \nhaving a Gerudo Fortress keyring."); - UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsForestTemple")); - UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsFireTemple")); - UIWidgets::EnhancementCheckbox("Water Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsWaterTemple")); - UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsSpiritTemple")); - UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsShadowTemple")); - UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsBottomOfTheWell")); - UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGTG")); - UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeShuffleKeyRings", RANDOMIZER_SEED_CVAR("ShuffleKeyRingsGanonsCastle")); + UIWidgets::EnhancementCheckbox("Forest Temple##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple")); + UIWidgets::EnhancementCheckbox("Fire Temple##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple")); + UIWidgets::EnhancementCheckbox("Water Temple##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple")); + UIWidgets::EnhancementCheckbox("Spirit Temple##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple")); + UIWidgets::EnhancementCheckbox("Shadow Temple##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple")); + UIWidgets::EnhancementCheckbox("Bottom of the Well##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell")); + UIWidgets::EnhancementCheckbox("Gerudo Training Grounds##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG")); + UIWidgets::EnhancementCheckbox("Ganon's Castle##RandomizeShuffleKeyRings", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle")); break; default: break; @@ -4161,7 +4161,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Thieve's Hideout Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GerudoKeys"), randoShuffleGerudoFortressKeys, RO_GERUDO_KEYS_VANILLA); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("GerudoKeys"), randoShuffleGerudoFortressKeys, RO_GERUDO_KEYS_VANILLA); UIWidgets::PaddedSeparator(); @@ -4180,7 +4180,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Anywhere - Boss Keys can appear anywhere in the world." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("BossKeysanity"), randoShuffleBossKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("BossKeysanity"), randoShuffleBossKeys, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); UIWidgets::PaddedSeparator(); @@ -4209,13 +4209,13 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "100 GS Reward - Ganon's Boss Key will be awarded by the cursed rich man after you collect 100 Gold Skulltula Tokens." ); - bool disableGBK = CVarGetInteger(RANDOMIZER_SEED_CVAR("TriforceHunt"), 0); + bool disableGBK = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), 0); static const char* disableGBKText = "This option is disabled because Triforce Hunt is enabled. Ganon's Boss key\nwill instead be given to you after Triforce Hunt completion."; - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), randoShuffleGanonsBossKey, + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), randoShuffleGanonsBossKey, RO_GANON_BOSS_KEY_VANILLA, disableGBK, disableGBKText, RO_GANON_BOSS_KEY_VANILLA); ImGui::PopItemWidth(); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA)) { case RO_GANON_BOSS_KEY_LACS_STONES: ImGui::Text("Reward Options"); UIWidgets::InsertHelpHoverText( @@ -4229,19 +4229,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 3, "", 3, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsStoneCount"), 1, 3, "", 3, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 4, "", 3, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsStoneCount"), 1, 4, "", 3, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Stone Count: %d", "##RandoLacsStoneCount", - RANDOMIZER_SEED_CVAR("LacsStoneCount"), 1, 3, "", 3, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsStoneCount"), 1, 3, "", 3, true, true, false); break; } break; @@ -4258,19 +4258,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 6, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), 1, 6, "", 6, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 7, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), 1, 7, "", 6, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Medallion Count: %d", "##RandoLacsMedallionCount", - RANDOMIZER_SEED_CVAR("LacsMedallionCount"), 1, 6, "", 6, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), 1, 6, "", 6, true, true, false); break; } break; @@ -4287,19 +4287,19 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 9, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 1, 9, "", 9, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 10, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 1, 10, "", 9, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Reward Count: %d", "##RandoLacsRewardCount", - RANDOMIZER_SEED_CVAR("LacsRewardCount"), 1, 9, "", 9, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsRewardCount"), 1, 9, "", 9, true, true, false); break; } break; @@ -4316,25 +4316,25 @@ void RandomizerSettingsWindow::DrawElement() { "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger(RANDOMIZER_SEED_CVAR("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), randoLACSRewardOptions, RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD)) { case RO_LACS_STANDARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 8, "", 8, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), 1, 8, "", 8, true, true, false); break; case RO_LACS_GREG_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 9, "", 8, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), 1, 9, "", 8, true, true, false); break; case RO_LACS_WILDCARD_REWARD: UIWidgets::PaddedEnhancementSliderInt("Dungeon Count: %d", "##RandoLacsDungeonCount", - RANDOMIZER_SEED_CVAR("LacsDungeonCount"), 1, 8, "", 8, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), 1, 8, "", 8, true, true, false); break; } break; case RO_GANON_BOSS_KEY_LACS_TOKENS: UIWidgets::PaddedEnhancementSliderInt("Token Count: %d", "##RandoLacsTokenCount", - RANDOMIZER_SEED_CVAR("LacsTokenCount"), 1, 100, "", 100, true, true, false); + CVAR_RANDOMIZER_SETTING("LacsTokenCount"), 1, 100, "", 100, true, true, false); break; default: break; @@ -4352,7 +4352,7 @@ void RandomizerSettingsWindow::DrawElement() { } ImGui::EndDisabled(); - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (ImGui::BeginTabItem("Gameplay")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoGameplay", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { @@ -4370,57 +4370,57 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8)); // Cuccos to return - int cuccos = CVarGetInteger(RANDOMIZER_SEED_CVAR("CuccosToReturn"), 7); + int cuccos = CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7); ImGui::Text("Cuccos to return: %d", cuccos); UIWidgets::InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##RandoCuccosToReturn", RANDOMIZER_SEED_CVAR("CuccosToReturn"), 0, 7, "", 7); + UIWidgets::EnhancementSliderInt("", "##RandoCuccosToReturn", CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 0, 7, "", 7); UIWidgets::PaddedSeparator(); // Big Poe Target Count - int poes = CVarGetInteger(RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 10); + int poes = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 10); ImGui::Text("Big Poe Target Count: %d", poes); UIWidgets::InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); ImGui::SameLine(); - UIWidgets::EnhancementSliderInt("", "##RandoBigPoeTargetCount", RANDOMIZER_SEED_CVAR("BigPoeTargetCount"), 1, 10, "", 10); + UIWidgets::EnhancementSliderInt("", "##RandoBigPoeTargetCount", CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1, 10, "", 10); UIWidgets::PaddedSeparator(); // Skip child stealth // Disabled when Skip Child Zelda is active - bool disableChildStealth = CVarGetInteger(RANDOMIZER_SEED_CVAR("SkipChildZelda"), 0); + bool disableChildStealth = CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 0); static const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; - UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipChildStealth"), disableChildStealth, disableChildStealthText); + UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), CVAR_RANDOMIZER_SETTING("SkipChildStealth"), disableChildStealth, disableChildStealthText); UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); UIWidgets::PaddedSeparator(); // Skip child zelda - UIWidgets::EnhancementCheckbox("Skip Child Zelda", RANDOMIZER_SEED_CVAR("SkipChildZelda")); + UIWidgets::EnhancementCheckbox("Skip Child Zelda", CVAR_RANDOMIZER_SETTING("SkipChildZelda")); UIWidgets::InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."); UIWidgets::PaddedSeparator(); // Skip Epona race - UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipEponaRace")); + UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), CVAR_RANDOMIZER_SETTING("SkipEponaRace")); UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); UIWidgets::PaddedSeparator(); // Skip tower escape - UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipTowerEscape")); + UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), CVAR_RANDOMIZER_SETTING("SkipTowerEscape")); UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); UIWidgets::PaddedSeparator(); // Complete mask quest - UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), RANDOMIZER_SEED_CVAR("CompleteMaskQuest")); + UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), CVAR_RANDOMIZER_SETTING("CompleteMaskQuest")); UIWidgets::InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); UIWidgets::PaddedSeparator(); // Skip Scarecrow Song - UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), RANDOMIZER_SEED_CVAR("SkipScarecrowsSong")); + UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong")); UIWidgets::InsertHelpHoverText( "Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will automatically summon him." ); @@ -4448,7 +4448,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Minimal - Most excess items are removed." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("ItemPool"), randoItemPool, RO_ITEM_POOL_BALANCED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("ItemPool"), randoItemPool, RO_ITEM_POOL_BALANCED); UIWidgets::PaddedSeparator(); // Ice Traps @@ -4467,7 +4467,7 @@ void RandomizerSettingsWindow::DrawElement() { "Onslaught - All junk items will be replaced by Ice Traps, even those " "in the base pool." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("IceTraps"), randoIceTraps, RO_ICE_TRAPS_NORMAL); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("IceTraps"), randoIceTraps, RO_ICE_TRAPS_NORMAL); UIWidgets::PaddedSeparator(); @@ -4485,8 +4485,8 @@ void RandomizerSettingsWindow::DrawElement() { "Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n" "\n" "Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n"); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("GossipStoneHints"), randoGossipStoneHints, RO_GOSSIP_STONES_NEED_NOTHING); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) != RO_GOSSIP_STONES_NONE) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), randoGossipStoneHints, RO_GOSSIP_STONES_NEED_NOTHING); + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) != RO_GOSSIP_STONES_NONE) { // Hint Clarity UIWidgets::Spacer(0); ImGui::Indent(); @@ -4503,7 +4503,7 @@ void RandomizerSettingsWindow::DrawElement() { "Clear - Hints are clearly written and are unique for each item.\n" "Ex: Kokiri Sword > the Kokiri Sword" ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("HintClarity"), randoHintClarity, RO_HINT_CLARITY_CLEAR); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("HintClarity"), randoHintClarity, RO_HINT_CLARITY_CLEAR); // Hint Distribution UIWidgets::Spacer(0); @@ -4519,7 +4519,7 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Very Strong - Many powerful hints." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("HintDistribution"), randoHintDistribution, RO_HINT_DIST_BALANCED); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("HintDistribution"), randoHintDistribution, RO_HINT_DIST_BALANCED); ImGui::Unindent(); } @@ -4534,30 +4534,30 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::Indent(); //Altar, Light Arrows, and Warp Songs are enabled by default - UIWidgets::PaddedEnhancementCheckbox("Altar Text", RANDOMIZER_SEED_CVAR("AltarHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Altar Text", CVAR_RANDOMIZER_SETTING("AltarHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Reading the Temple of Time altar as child will tell you the locations of the Spiritual Stones.\n" "Reading the Temple of Time altar as adult will tell you the locations of the Medallions, as well as the conditions for building the Rainbow Bridge and getting the Boss Key for Ganon's Castle."); - UIWidgets::PaddedEnhancementCheckbox("Light Arrows", RANDOMIZER_SEED_CVAR("LAHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Light Arrows", CVAR_RANDOMIZER_SETTING("LAHint"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Talking to Ganondorf in his boss room or Sheik inside Ganon's Castle (when trials are enabled) will tell you the location of the Light Arrows." "If this option is enabled and Ganondorf is reachable without Light Arrows, Gossip Stones will never hint the Light Arrows."); - UIWidgets::PaddedEnhancementCheckbox("Dampe's Diary (Hookshot)", RANDOMIZER_SEED_CVAR("DampeHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Dampe's Diary (Hookshot)", CVAR_RANDOMIZER_SETTING("DampeHint"), true, false); UIWidgets::InsertHelpHoverText("Reading the diary of Dampé the gravekeeper as adult will tell you the location of one of the Hookshots."); - UIWidgets::PaddedEnhancementCheckbox("Greg the Green Rupee", RANDOMIZER_SEED_CVAR("GregHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Greg the Green Rupee", CVAR_RANDOMIZER_SETTING("GregHint"), true, false); UIWidgets::InsertHelpHoverText("Talking to the chest game owner after buying a key will tell you the location of Greg the Green Rupee."); - UIWidgets::PaddedEnhancementCheckbox("Saria (Magic)", RANDOMIZER_SEED_CVAR("SariaHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Saria (Magic)", CVAR_RANDOMIZER_SETTING("SariaHint"), true, false); UIWidgets::InsertHelpHoverText("Talking to Saria either in person or through Saria's Song will tell you the location of a progressive magic meter."); - UIWidgets::PaddedEnhancementCheckbox("Frog Ocarina Game", RANDOMIZER_SEED_CVAR("FrogsHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Frog Ocarina Game", CVAR_RANDOMIZER_SETTING("FrogsHint"), true, false); UIWidgets::InsertHelpHoverText("Standing near the pedestal for the frogs in Zora's River will tell you the reward for the frogs' ocarina game."); - UIWidgets::PaddedEnhancementCheckbox("Warp Song text", RANDOMIZER_SEED_CVAR("WarpSongText"), true, false, !CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWarpSongs"), RO_GENERIC_OFF), + UIWidgets::PaddedEnhancementCheckbox("Warp Song text", CVAR_RANDOMIZER_SETTING("WarpSongText"), true, false, !CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), RO_GENERIC_OFF), "This option is disabled since warp songs are not shuffled.", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::InsertHelpHoverText("Playing a warp song will tell you where it leads. (If warp song destinations are vanilla, this is always enabled.)"); - UIWidgets::PaddedEnhancementCheckbox("Scrub Item text", RANDOMIZER_SEED_CVAR("ScrubText"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Scrub Item text", CVAR_RANDOMIZER_SETTING("ScrubText"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::InsertHelpHoverText("Business scrubs will reveal the identity of what they're selling."); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 10", RANDOMIZER_SEED_CVAR("10GSHint"), true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 20", RANDOMIZER_SEED_CVAR("20GSHint"), true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 30", RANDOMIZER_SEED_CVAR("30GSHint"), true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 40", RANDOMIZER_SEED_CVAR("40GSHint"), true, false); - UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 50", RANDOMIZER_SEED_CVAR("50GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 10", CVAR_RANDOMIZER_SETTING("10GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 20", CVAR_RANDOMIZER_SETTING("20GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 30", CVAR_RANDOMIZER_SETTING("30GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 40", CVAR_RANDOMIZER_SETTING("40GSHint"), true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 50", CVAR_RANDOMIZER_SETTING("50GSHint"), true, false); ImGui::Unindent(); @@ -4572,13 +4572,13 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::EnhancementCheckbox("Full Wallets", RANDOMIZER_SEED_CVAR("FullWallets")); + UIWidgets::EnhancementCheckbox("Full Wallets", CVAR_RANDOMIZER_SETTING("FullWallets")); UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); UIWidgets::PaddedSeparator(); // Bombchus in Logic - UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), RANDOMIZER_SEED_CVAR("BombchusInLogic")); + UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), CVAR_RANDOMIZER_SETTING("BombchusInLogic")); UIWidgets::InsertHelpHoverText( "Bombchus are properly considered in logic.\n" "\n" @@ -4592,14 +4592,14 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Enable Bombchu Drops - UIWidgets::EnhancementCheckbox("Enable Bombchu Drops", RANDOMIZER_SEED_CVAR("EnableBombchuDrops")); + UIWidgets::EnhancementCheckbox("Enable Bombchu Drops", CVAR_RANDOMIZER_SETTING("EnableBombchuDrops")); UIWidgets::InsertHelpHoverText( "Once you obtain bombchus for the first time, refills can be found in bushes and other places where bomb drops can normally spawn." ); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox("Blue Fire Arrows", RANDOMIZER_SEED_CVAR("BlueFireArrows")); + UIWidgets::EnhancementCheckbox("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows")); UIWidgets::InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress." @@ -4607,7 +4607,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox("Sunlight Arrows", RANDOMIZER_SEED_CVAR("SunlightArrows")); + UIWidgets::EnhancementCheckbox("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows")); UIWidgets::InsertHelpHoverText( "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress." @@ -4624,7 +4624,7 @@ void RandomizerSettingsWindow::DrawElement() { } ImGui::EndDisabled(); - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); static bool locationsTabOpen = false; if (ImGui::BeginTabItem("Locations")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); @@ -4632,7 +4632,7 @@ void RandomizerSettingsWindow::DrawElement() { locationsTabOpen = true; RandomizerCheckObjects::UpdateImGuiVisibility(); // todo: this efficently when we build out cvar array support - std::stringstream excludedLocationStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), "")); + std::stringstream excludedLocationStringStream(CVarGetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), "")); std::string excludedLocationString; excludedLocations.clear(); while (getline(excludedLocationStringStream, excludedLocationString, ',')) { @@ -4682,7 +4682,7 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += std::to_string(excludedLocationIt); excludedLocationString += ","; } - CVarSetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), excludedLocationString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), excludedLocationString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -4724,9 +4724,9 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += ","; } if (excludedLocationString == "") { - CVarClear(RANDOMIZER_SEED_CVAR("ExcludedLocations")); + CVarClear(CVAR_RANDOMIZER_SETTING("ExcludedLocations")); } else { - CVarSetString(RANDOMIZER_SEED_CVAR("ExcludedLocations"), excludedLocationString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), excludedLocationString.c_str()); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -4755,13 +4755,13 @@ void RandomizerSettingsWindow::DrawElement() { tricksTabOpen = true; //RandomizerTricks::UpdateImGuiVisibility(); // todo: this efficently when we build out cvar array support - std::stringstream enabledTrickStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), "")); + std::stringstream enabledTrickStringStream(CVarGetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), "")); std::string enabledTrickString; enabledTricks.clear(); while (getline(enabledTrickStringStream, enabledTrickString, ',')) { enabledTricks.insert((RandomizerTrick)std::stoi(enabledTrickString)); } - std::stringstream enabledGlitchStringStream(CVarGetString(RANDOMIZER_SEED_CVAR("EnabledGlitches"), "")); + std::stringstream enabledGlitchStringStream(CVarGetString(CVAR_RANDOMIZER_SETTING("EnabledGlitches"), "")); std::string enabledGlitchString; enabledGlitches.clear(); while (getline(enabledGlitchStringStream, enabledGlitchString, ',')) { @@ -4785,10 +4785,10 @@ void RandomizerSettingsWindow::DrawElement() { "\n" "Vanilla - Places all items and dungeon rewards in their vanilla locations." ); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LogicRules"), randoLogicRules, RO_LOGIC_GLITCHLESS); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_GLITCHLESS) { + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LogicRules"), randoLogicRules, RO_LOGIC_GLITCHLESS); + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_GLITCHLESS) { ImGui::SameLine(); - UIWidgets::EnhancementCheckbox(Settings::LocationsReachable.GetName().c_str(), RANDOMIZER_SEED_CVAR("AllLocationsReachable"), false, "", UIWidgets::CheckboxGraphics::Cross, RO_GENERIC_ON); + UIWidgets::EnhancementCheckbox(Settings::LocationsReachable.GetName().c_str(), CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), false, "", UIWidgets::CheckboxGraphics::Cross, RO_GENERIC_ON); UIWidgets::InsertHelpHoverText( "When this options is enabled, the randomizer will " "guarantee that every item is obtainable and every " @@ -4797,7 +4797,7 @@ void RandomizerSettingsWindow::DrawElement() { "will be guaranteed reachable." ); } - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { ImGui::SameLine(); ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Heads up! This will disable all rando settings except for entrance shuffle and starter items"); } @@ -4805,7 +4805,7 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); // Enable Glitch-Useful Cutscenes - UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), RANDOMIZER_SEED_CVAR("EnableGlitchCutscenes")); + UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes")); UIWidgets::InsertHelpHoverText( "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); @@ -4814,7 +4814,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::EndTable(); } - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); // Tricks static std::unordered_map areaTreeDisabled { @@ -4897,7 +4897,7 @@ void RandomizerSettingsWindow::DrawElement() { }; static ImGuiTextFilter trickSearch; trickSearch.Draw("Filter (inc,-exc)", 490.0f); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { ImGui::SameLine(); if (ImGui::Button("Disable All")) { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { @@ -4913,7 +4913,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); + CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); @@ -4930,7 +4930,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } @@ -4952,7 +4952,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::PopItemFlag(); ImGui::TableNextRow(); - if (CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC) { // COLUMN 1 - DISABLED TRICKS ImGui::TableNextColumn(); @@ -5007,7 +5007,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5043,7 +5043,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } DrawTagChips(*rtObject.rtTags); @@ -5117,7 +5117,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); + CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5156,9 +5156,9 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } if (enabledTrickString == "") { - CVarClear(RANDOMIZER_SEED_CVAR("EnabledTricks")); + CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); } else { - CVarSetString(RANDOMIZER_SEED_CVAR("EnabledTricks"), enabledTrickString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -5215,17 +5215,17 @@ void RandomizerSettingsWindow::DrawElement() { window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); ImGui::BeginDisabled( - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON || - CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA ); ImGui::Text("%s", Settings::LinksPocketItem.GetName().c_str()); - UIWidgets::EnhancementCombobox(RANDOMIZER_SEED_CVAR("LinksPocket"), randoLinksPocket, RO_LINKS_POCKET_DUNGEON_REWARD); + UIWidgets::EnhancementCombobox(CVAR_RANDOMIZER_SETTING("LinksPocket"), randoLinksPocket, RO_LINKS_POCKET_DUNGEON_REWARD); UIWidgets::PaddedSeparator(); ImGui::EndDisabled(); - UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingKokiriSword")); + UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingKokiriSword")); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingDekuShield")); + UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingDekuShield")); UIWidgets::PaddedSeparator(); @@ -5236,13 +5236,13 @@ void RandomizerSettingsWindow::DrawElement() { window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); - ImGui::BeginDisabled(CVarGetInteger(RANDOMIZER_SEED_CVAR("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); - UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingOcarina")); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingOcarina")); UIWidgets::PaddedSeparator(); ImGui::EndDisabled(); - UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingConsumables")); + UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingConsumables")); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementSliderInt("Gold Skulltula Tokens: %d", "##RandoStartingSkulltulaToken", RANDOMIZER_SEED_CVAR("StartingSkulltulaToken"), 0, 100, "", 0); + UIWidgets::EnhancementSliderInt("Gold Skulltula Tokens: %d", "##RandoStartingSkulltulaToken", CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), 0, 100, "", 0); UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -5251,22 +5251,22 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingSongs", ImVec2(0, -8)); - UIWidgets::EnhancementCheckbox(Settings::StartingZeldasLullaby.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingZeldasLullaby")); - UIWidgets::EnhancementCheckbox(Settings::StartingEponasSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingEponasSong")); - UIWidgets::EnhancementCheckbox(Settings::StartingSariasSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSariasSong")); - UIWidgets::EnhancementCheckbox(Settings::StartingSunsSong.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSunsSong")); - UIWidgets::EnhancementCheckbox(Settings::StartingSongOfTime.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSongOfTime")); - UIWidgets::EnhancementCheckbox(Settings::StartingSongOfStorms.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSongOfStorms")); + UIWidgets::EnhancementCheckbox(Settings::StartingZeldasLullaby.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby")); + UIWidgets::EnhancementCheckbox(Settings::StartingEponasSong.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingEponasSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSariasSong.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingSariasSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSunsSong.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingSunsSong")); + UIWidgets::EnhancementCheckbox(Settings::StartingSongOfTime.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingSongOfTime")); + UIWidgets::EnhancementCheckbox(Settings::StartingSongOfStorms.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingSongOfStorms")); UIWidgets::PaddedSeparator(); ImGui::Text("Warp Songs"); UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox(Settings::StartingMinuetOfForest.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingMinuetOfForest")); - UIWidgets::EnhancementCheckbox(Settings::StartingBoleroOfFire.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingBoleroOfFire")); - UIWidgets::EnhancementCheckbox(Settings::StartingSerenadeOfWater.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingSerenadeOfWater")); - UIWidgets::EnhancementCheckbox(Settings::StartingRequiemOfSpirit.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingRequiemOfSpirit")); - UIWidgets::EnhancementCheckbox(Settings::StartingNocturneOfShadow.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingNocturneOfShadow")); - UIWidgets::EnhancementCheckbox(Settings::StartingPreludeOfLight.GetName().c_str(), RANDOMIZER_SEED_CVAR("StartingPreludeOfLight")); + UIWidgets::EnhancementCheckbox(Settings::StartingMinuetOfForest.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest")); + UIWidgets::EnhancementCheckbox(Settings::StartingBoleroOfFire.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire")); + UIWidgets::EnhancementCheckbox(Settings::StartingSerenadeOfWater.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater")); + UIWidgets::EnhancementCheckbox(Settings::StartingRequiemOfSpirit.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit")); + UIWidgets::EnhancementCheckbox(Settings::StartingNocturneOfShadow.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow")); + UIWidgets::EnhancementCheckbox(Settings::StartingPreludeOfLight.GetName().c_str(), CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight")); UIWidgets::PaddedSeparator(); ImGui::EndChild(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index f3582a5cb..b97a6f335 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -885,57 +885,57 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { (!RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea) || locationIt.vOrMQ == RCVORMQ_BOTH || locationIt.vOrMQ == RCVORMQ_MQ && - ((CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12) > 0) || // at least one MQ dungeon - CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || + ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) > 0) || // at least one MQ dungeon + CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || locationIt.vOrMQ == RCVORMQ_VANILLA && - (CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || CVarGetInteger(RANDOMIZER_SEED_CVAR("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon ) && - (locationIt.rcType != RCTYPE_SHOP || CVarGetInteger(RANDOMIZER_SEED_CVAR("Shopsanity"), RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && - (locationIt.rcType != RCTYPE_SCRUB || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleScrubs"), RO_SCRUBS_OFF) != RO_SCRUBS_OFF || + (locationIt.rcType != RCTYPE_SHOP || CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && + (locationIt.rcType != RCTYPE_SCRUB || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_OFF) != RO_SCRUBS_OFF || locationIt.rc == RC_HF_DEKU_SCRUB_GROTTO || locationIt.rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT || locationIt.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE) && // The 3 scrubs that are always randomized - (locationIt.rcType != RCTYPE_MERCHANT || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF) != RO_SHUFFLE_MERCHANTS_OFF) && - (locationIt.rcType != RCTYPE_SONG_LOCATION || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_SONG_LOCATIONS) && // song locations + (locationIt.rcType != RCTYPE_MERCHANT || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF) != RO_SHUFFLE_MERCHANTS_OFF) && + (locationIt.rcType != RCTYPE_SONG_LOCATION || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_SONG_LOCATIONS) && // song locations ((locationIt.rcType != RCTYPE_BOSS_HEART_OR_OTHER_REWARD && locationIt.rc != RC_SONG_FROM_IMPA && locationIt.rc != RC_SHEIK_IN_ICE_CAVERN) || - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_DUNGEON_REWARDS) && // song dungeon rewards - (locationIt.rcType != RCTYPE_DUNGEON_REWARD || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON) && // dungeon rewards end of dungeons - (locationIt.rcType != RCTYPE_OCARINA || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleOcarinas"), RO_GENERIC_NO)) && // ocarina locations + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_SONG_LOCATIONS) != RO_SONG_SHUFFLE_DUNGEON_REWARDS) && // song dungeon rewards + (locationIt.rcType != RCTYPE_DUNGEON_REWARD || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) != RO_DUNGEON_REWARDS_END_OF_DUNGEON) && // dungeon rewards end of dungeons + (locationIt.rcType != RCTYPE_OCARINA || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_NO)) && // ocarina locations (locationIt.rc != RC_HC_ZELDAS_LETTER) && // don't show until we support shuffling letter (locationIt.rcType != RCTYPE_GOSSIP_STONE) && // don't show gossip stones (maybe gossipsanity will be a thing eventually?) (locationIt.rcType != RCTYPE_LINKS_POCKET) && // links pocket can be set to nothing if needed (locationIt.rcType != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them (locationIt.rcType != RCTYPE_SKULL_TOKEN || - (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_ALL) || - ((CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_OVERWORLD) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) || - ((CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea)) + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_ALL) || + ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_OVERWORLD) && RandomizerCheckObjects::AreaIsOverworld(locationIt.rcArea)) || + ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(locationIt.rcArea)) ) && - (locationIt.rcType != RCTYPE_COW || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleCows"), RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_ADULT_TRADE || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleAdultTrade"), RO_GENERIC_NO)) && - (locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleKokiriSword"), RO_GENERIC_NO)) && - (locationIt.rc != RC_ZR_MAGIC_BEAN_SALESMAN || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleBeans"), RO_GENERIC_NO)) && - (locationIt.rc != RC_HC_MALON_EGG || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleWeirdEgg"), RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_FROG_SONG || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleFrogSongRupees"), RO_GENERIC_NO)) && - (locationIt.rcType != RCTYPE_MAP_COMPASS || CVarGetInteger(RANDOMIZER_SEED_CVAR("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_SMALL_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_BOSS_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && - (locationIt.rcType != RCTYPE_GANON_BOSS_KEY || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_VANILLA) && // vanilla ganon boss key + (locationIt.rcType != RCTYPE_COW || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_ADULT_TRADE || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), RO_GENERIC_NO)) && + (locationIt.rc != RC_KF_KOKIRI_SWORD_CHEST || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), RO_GENERIC_NO)) && + (locationIt.rc != RC_ZR_MAGIC_BEAN_SALESMAN || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), RO_GENERIC_NO)) && + (locationIt.rc != RC_HC_MALON_EGG || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_FROG_SONG || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), RO_GENERIC_NO)) && + (locationIt.rcType != RCTYPE_MAP_COMPASS || CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_SMALL_KEY || CVarGetInteger(CVAR_RANDOMIZER_SETTING("Keysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_BOSS_KEY || CVarGetInteger(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && + (locationIt.rcType != RCTYPE_GANON_BOSS_KEY || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_VANILLA) && // vanilla ganon boss key (locationIt.rc != RC_TOT_LIGHT_ARROWS_CUTSCENE || - (CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_DUNGEONS && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_MEDALLIONS && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_REWARDS && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_STONES && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_TOKENS && - CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_VANILLA) + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_DUNGEONS && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_MEDALLIONS && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_REWARDS && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_STONES && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_TOKENS && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_LACS_VANILLA) ) && // LACS ganon boss key - (locationIt.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_KAK_TOKENS) && // 100 skull reward ganon boss key + (locationIt.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) != RO_GANON_BOSS_KEY_KAK_TOKENS) && // 100 skull reward ganon boss key (locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD || - (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_OPEN && locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) || - (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_FAST && - ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || - (locationIt.rc == RC_GF_NORTH_F1_CARPENTER && CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_OPEN && locationIt.rcType != RCTYPE_GF_KEY && locationIt.rc != RC_GF_GERUDO_MEMBERSHIP_CARD) || + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_FAST && + ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || + (locationIt.rc == RC_GF_NORTH_F1_CARPENTER && CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) ) || - (CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && - ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(RANDOMIZER_SEED_CVAR("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || - (locationIt.rcType == RCTYPE_GF_KEY && CVarGetInteger(RANDOMIZER_SEED_CVAR("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + ((locationIt.rc == RC_GF_GERUDO_MEMBERSHIP_CARD && CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), RO_GENERIC_NO) == RO_GENERIC_YES) || + (locationIt.rcType == RCTYPE_GF_KEY && CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)) ) ) ); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index d991c464f..9d747c063 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -869,14 +869,14 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { void CheckTrackerWindow::DrawElement() { ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver); - if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { - if (CVarGetInteger(CHECK_TRACKER_CVAR("ShowOnlyPaused"), 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { + if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(CVAR_TRACKER_CHECK("ShowOnlyPaused"), 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { return; } - if (CVarGetInteger(CHECK_TRACKER_CVAR("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - int comboButton1Mask = buttons[CVarGetInteger(CHECK_TRACKER_CVAR("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; - int comboButton2Mask = buttons[CVarGetInteger(CHECK_TRACKER_CVAR("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; + if (CVarGetInteger(CVAR_TRACKER_CHECK("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + int comboButton1Mask = buttons[CVarGetInteger(CVAR_TRACKER_CHECK("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; + int comboButton2Mask = buttons[CVarGetInteger(CVAR_TRACKER_CHECK("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; OSContPad* trackerButtonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = trackerButtonsPressed != nullptr && trackerButtonsPressed[0].button & comboButton1Mask && @@ -916,7 +916,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::TableNextRow(0, headerHeight); ImGui::TableNextColumn(); UIWidgets::EnhancementCheckbox( - "Show Hidden Items", CHECK_TRACKER_CVAR("ShowHidden"), false, + "Show Hidden Items", CVAR_TRACKER_CHECK("ShowHidden"), false, "When active, items will show hidden checks by default when updated to this state."); UIWidgets::PaddedSeparator(); if (ImGui::Button("Expand All")) { @@ -955,17 +955,17 @@ void CheckTrackerWindow::DrawElement() { RainbowTick(); bool doDraw = false; bool thisAreaFullyChecked = false; - bool showHidden = CVarGetInteger(CHECK_TRACKER_CVAR("ShowHidden"), 0); - bool hideIncomplete = CVarGetInteger(CHECK_TRACKER_CVAR("AreaIncomplete.Hide"), 0); - bool hideComplete = CVarGetInteger(CHECK_TRACKER_CVAR("AreaComplete.Hide"), 0); + bool showHidden = CVarGetInteger(CVAR_TRACKER_CHECK("ShowHidden"), 0); + bool hideIncomplete = CVarGetInteger(CVAR_TRACKER_CHECK("AreaIncomplete.Hide"), 0); + bool hideComplete = CVarGetInteger(CVAR_TRACKER_CHECK("AreaComplete.Hide"), 0); bool collapseLogic; bool doingCollapseOrExpand = optExpandAll || optCollapseAll; bool isThisAreaSpoiled; RandomizerCheckArea lastArea = RCAREA_INVALID; - Color_RGBA8 areaCompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.MainColor"), Color_Main_Default); - Color_RGBA8 areaIncompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), Color_Main_Default); - Color_RGBA8 extraCompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); - Color_RGBA8 extraIncompleteColor = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); + Color_RGBA8 areaCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor"), Color_Main_Default); + Color_RGBA8 areaIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), Color_Main_Default); + Color_RGBA8 extraCompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); + Color_RGBA8 extraIncompleteColor = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string stemp; @@ -1020,7 +1020,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f)); - isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger(CHECK_TRACKER_CVAR("MQSpoilers"), 0); + isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger(CVAR_TRACKER_CHECK("MQSpoilers"), 0); if (isThisAreaSpoiled) { if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { @@ -1098,12 +1098,12 @@ void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flag ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NoFocusOnAppearing; } - if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar; - if (!CVarGetInteger(CHECK_TRACKER_CVAR("Draggable"), 0)) { + if (!CVarGetInteger(CVAR_TRACKER_CHECK("Draggable"), 0)) { windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; } } @@ -1363,52 +1363,52 @@ void DrawLocation(RandomizerCheckObject rcObj) { Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string txt; - bool showHidden = CVarGetInteger(CHECK_TRACKER_CVAR("ShowHidden"), 0); + bool showHidden = CVarGetInteger(CVAR_TRACKER_CHECK("ShowHidden"), 0); RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rcObj.rc]; RandomizerCheckStatus status = checkData.status; bool skipped = checkData.skipped; if (status == RCSHOW_COLLECTED) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Collected.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Collected.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Collected.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Collected.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Extra_Default); } else if (status == RCSHOW_SAVED) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Saved.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Saved.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Saved.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Saved.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Extra_Default); } else if (skipped) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Skipped.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Skipped.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Skipped.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default); } else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Seen.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Seen.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Seen.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Seen.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Extra_Default); } else if (status == RCSHOW_SCUMMED) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Scummed.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Scummed.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Scummed.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Scummed.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Extra_Default); } else if (status == RCSHOW_UNCHECKED) { - if (!showHidden && CVarGetInteger(CHECK_TRACKER_CVAR("Unchecked.Hide"), 0)) { + if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Unchecked.Hide"), 0)) { return; } - mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default) : - CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.MainColor"), Color_Main_Default); - extraColor = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); + mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default) : + CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.MainColor"), Color_Main_Default); + extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); } //Main Text @@ -1503,15 +1503,15 @@ void DrawLocation(RandomizerCheckObject rcObj) { } static std::set rainbowCVars = { - CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), - CHECK_TRACKER_CVAR("AreaComplete.MainColor"), CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), - CHECK_TRACKER_CVAR("Unchecked.MainColor"), CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), - CHECK_TRACKER_CVAR("Skipped.MainColor"), CHECK_TRACKER_CVAR("Skipped.ExtraColor"), - CHECK_TRACKER_CVAR("Seen.MainColor"), CHECK_TRACKER_CVAR("Seen.ExtraColor"), - CHECK_TRACKER_CVAR("Hinted.MainColor"), CHECK_TRACKER_CVAR("Hinted.ExtraColor"), - CHECK_TRACKER_CVAR("Collected.MainColor"), CHECK_TRACKER_CVAR("Collected.ExtraColor"), - CHECK_TRACKER_CVAR("Scummed.MainColor"), CHECK_TRACKER_CVAR("Scummed.ExtraColor"), - CHECK_TRACKER_CVAR("Saved.MainColor"), CHECK_TRACKER_CVAR("Saved.ExtraColor"), + CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), + CVAR_TRACKER_CHECK("AreaComplete.MainColor"), CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), + CVAR_TRACKER_CHECK("Unchecked.MainColor"), CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), + CVAR_TRACKER_CHECK("Skipped.MainColor"), CVAR_TRACKER_CHECK("Skipped.ExtraColor"), + CVAR_TRACKER_CHECK("Seen.MainColor"), CVAR_TRACKER_CHECK("Seen.ExtraColor"), + CVAR_TRACKER_CHECK("Hinted.MainColor"), CVAR_TRACKER_CHECK("Hinted.ExtraColor"), + CVAR_TRACKER_CHECK("Collected.MainColor"), CVAR_TRACKER_CHECK("Collected.ExtraColor"), + CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), + CVAR_TRACKER_CHECK("Saved.MainColor"), CVAR_TRACKER_CHECK("Saved.ExtraColor"), }; int hue = 0; @@ -1606,33 +1606,33 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - if (UIWidgets::EnhancementColor("BG Color", CHECK_TRACKER_CVAR("BgColor"), + if (UIWidgets::EnhancementColor("BG Color", CVAR_TRACKER_CHECK("BgColor"), ImVec4(Color_Background.r, Color_Background.g, Color_Background.b, Color_Background.a), ImVec4(Color_Bg_Default.r, Color_Bg_Default.g, Color_Bg_Default.b, Color_Bg_Default.a), false, true)) { - Color_Background = CVarGetColor(CHECK_TRACKER_CVAR("BgColor"), Color_Bg_Default); + Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default); } ImGui::PopItemWidth(); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CHECK_TRACKER_CVAR("WindowType"), windowType, TRACKER_WINDOW_WINDOW); - if (CVarGetInteger(CHECK_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { - UIWidgets::EnhancementCheckbox("Enable Dragging", CHECK_TRACKER_CVAR("Draggable")); - UIWidgets::EnhancementCheckbox("Only enable while paused", CHECK_TRACKER_CVAR("ShowOnlyPaused")); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CHECK_TRACKER_CVAR("DisplayType"), displayType, 0); - if (CVarGetInteger(CHECK_TRACKER_CVAR("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CHECK_TRACKER_CVAR("ComboButton1"), buttonStrings, TRACKER_COMBO_BUTTON_L); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CHECK_TRACKER_CVAR("ComboButton2"), buttonStrings, TRACKER_COMBO_BUTTON_R); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CVAR_TRACKER_CHECK("WindowType"), windowType, TRACKER_WINDOW_WINDOW); + if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { + UIWidgets::EnhancementCheckbox("Enable Dragging", CVAR_TRACKER_CHECK("Draggable")); + UIWidgets::EnhancementCheckbox("Only enable while paused", CVAR_TRACKER_CHECK("ShowOnlyPaused")); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CVAR_TRACKER_CHECK("DisplayType"), displayType, 0); + if (CVarGetInteger(CVAR_TRACKER_CHECK("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CVAR_TRACKER_CHECK("ComboButton1"), buttonStrings, TRACKER_COMBO_BUTTON_L); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CVAR_TRACKER_CHECK("ComboButton2"), buttonStrings, TRACKER_COMBO_BUTTON_R); } } - UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", CHECK_TRACKER_CVAR("MQSpoilers")); + UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", CVAR_TRACKER_CHECK("MQSpoilers")); UIWidgets::Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked."); - if (UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", CHECK_TRACKER_CVAR("HideRightShopChecks"), false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", CVAR_TRACKER_CHECK("HideRightShopChecks"), false, "", UIWidgets::CheckboxGraphics::Cross, true)) { hideShopRightChecks = !hideShopRightChecks; RecalculateAreaTotals(); } UIWidgets::Tooltip("If enabled, will prevent the tracker from displaying slots 1-4 in all shops."); - if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", CHECK_TRACKER_CVAR("AlwaysShowGSLocs"), false, "")) { + if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), false, "")) { alwaysShowGS = !alwaysShowGS; RecalculateAreaTotals(); } @@ -1645,15 +1645,15 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableNextColumn(); - CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, CHECK_TRACKER_CVAR("AreaIncomplete.Hide"), ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", CHECK_TRACKER_CVAR("AreaComplete.MainColor"), CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, CHECK_TRACKER_CVAR("AreaComplete.Hide"), ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CHECK_TRACKER_CVAR("Unchecked.MainColor"), CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CHECK_TRACKER_CVAR("Unchecked.Hide"), "Checks you have not interacted with at all."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CHECK_TRACKER_CVAR("Skipped.MainColor"), CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CHECK_TRACKER_CVAR("Skipped.Hide"), ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CHECK_TRACKER_CVAR("Seen.MainColor"), CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CHECK_TRACKER_CVAR("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CHECK_TRACKER_CVAR("Scummed.MainColor"), CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, "gCheckTrackerScummedHide", "Checks you collect, but then reload before saving so you no longer have them."); - //CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CHECK_TRACKER_CVAR("Hinted.MainColor"), CHECK_TRACKER_CVAR("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CHECK_TRACKER_CVAR("Hinted.Hide"), ""); - CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CHECK_TRACKER_CVAR("Collected.MainColor"), CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CHECK_TRACKER_CVAR("Collected.Hide"), "Checks you have collected without saving or reloading yet."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CHECK_TRACKER_CVAR("Saved.MainColor"), CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CHECK_TRACKER_CVAR("Saved.Hide"), "Checks that you saved the game while having collected."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Area Incomplete", CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Main, Color_Area_Incomplete_Extra, Color_Main_Default, Color_Area_Incomplete_Extra_Default, CVAR_TRACKER_CHECK("AreaIncomplete.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Area Complete", CVAR_TRACKER_CHECK("AreaComplete.MainColor"), CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Main, Color_Area_Complete_Extra, Color_Main_Default, Color_Area_Complete_Extra_Default, CVAR_TRACKER_CHECK("AreaComplete.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CVAR_TRACKER_CHECK("Unchecked.MainColor"), CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CVAR_TRACKER_CHECK("Unchecked.Hide"), "Checks you have not interacted with at all."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CVAR_TRACKER_CHECK("Skipped.MainColor"), CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CVAR_TRACKER_CHECK("Skipped.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CVAR_TRACKER_CHECK("Seen.MainColor"), CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CVAR_TRACKER_CHECK("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, "gCheckTrackerScummedHide", "Checks you collect, but then reload before saving so you no longer have them."); + //CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CVAR_TRACKER_CHECK("Hinted.MainColor"), CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CVAR_TRACKER_CHECK("Hinted.Hide"), ""); + CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CVAR_TRACKER_CHECK("Collected.MainColor"), CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CVAR_TRACKER_CHECK("Collected.Hide"), "Checks you have collected without saving or reloading yet."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CVAR_TRACKER_CHECK("Saved.MainColor"), CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CVAR_TRACKER_CHECK("Saved.Hide"), "Checks that you saved the game while having collected."); ImGui::PopStyleVar(1); ImGui::EndTable(); @@ -1661,25 +1661,25 @@ void CheckTrackerSettingsWindow::DrawElement() { } void CheckTrackerWindow::InitElement() { - Color_Background = CVarGetColor(CHECK_TRACKER_CVAR("BgColor"), Color_Bg_Default); - Color_Area_Incomplete_Main = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.MainColor"), Color_Main_Default); - Color_Area_Incomplete_Extra = CVarGetColor(CHECK_TRACKER_CVAR("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); - Color_Area_Complete_Main = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.MainColor"), Color_Main_Default); - Color_Area_Complete_Extra = CVarGetColor(CHECK_TRACKER_CVAR("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); - Color_Unchecked_Main = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.MainColor"), Color_Main_Default); - Color_Unchecked_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); - Color_Skipped_Main = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.MainColor"), Color_Main_Default); - Color_Skipped_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Skipped.ExtraColor"), Color_Skipped_Extra_Default); - Color_Seen_Main = CVarGetColor(CHECK_TRACKER_CVAR("Seen.MainColor"), Color_Main_Default); - Color_Seen_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Seen.ExtraColor"), Color_Seen_Extra_Default); - Color_Hinted_Main = CVarGetColor(CHECK_TRACKER_CVAR("Hinted.MainColor"), Color_Main_Default); - Color_Hinted_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Hinted.ExtraColor"), Color_Hinted_Extra_Default); - Color_Collected_Main = CVarGetColor(CHECK_TRACKER_CVAR("Collected.MainColor"), Color_Main_Default); - Color_Collected_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Collected.ExtraColor"), Color_Collected_Extra_Default); - Color_Scummed_Main = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.MainColor"), Color_Main_Default); - Color_Scummed_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Scummed.ExtraColor"), Color_Scummed_Extra_Default); - Color_Saved_Main = CVarGetColor(CHECK_TRACKER_CVAR("Saved.MainColor"), Color_Main_Default); - Color_Saved_Extra = CVarGetColor(CHECK_TRACKER_CVAR("Saved.ExtraColor"), Color_Saved_Extra_Default); + Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default); + Color_Area_Incomplete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor"), Color_Main_Default); + Color_Area_Incomplete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor"), Color_Area_Incomplete_Extra_Default); + Color_Area_Complete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor"), Color_Main_Default); + Color_Area_Complete_Extra = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor"), Color_Area_Complete_Extra_Default); + Color_Unchecked_Main = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.MainColor"), Color_Main_Default); + Color_Unchecked_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Extra_Default); + Color_Skipped_Main = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor"), Color_Main_Default); + Color_Skipped_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default); + Color_Seen_Main = CVarGetColor(CVAR_TRACKER_CHECK("Seen.MainColor"), Color_Main_Default); + Color_Seen_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Extra_Default); + Color_Hinted_Main = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.MainColor"), Color_Main_Default); + Color_Hinted_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Extra_Default); + Color_Collected_Main = CVarGetColor(CVAR_TRACKER_CHECK("Collected.MainColor"), Color_Main_Default); + Color_Collected_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Extra_Default); + Color_Scummed_Main = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.MainColor"), Color_Main_Default); + Color_Scummed_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Extra_Default); + Color_Saved_Main = CVarGetColor(CVAR_TRACKER_CHECK("Saved.MainColor"), Color_Main_Default); + Color_Saved_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Extra_Default); SaveManager::Instance->AddInitFunction(InitTrackerData); sectionId = SaveManager::Instance->AddSaveFunction("trackerData", 1, SaveFile, true, -1); @@ -1695,8 +1695,8 @@ void CheckTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); - hideShopRightChecks = CVarGetInteger(CHECK_TRACKER_CVAR("HideRightShopChecks"), 1); - alwaysShowGS = CVarGetInteger(CHECK_TRACKER_CVAR("AlwaysShowGSLocs"), 0); + hideShopRightChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideRightShopChecks"), 1); + alwaysShowGS = CVarGetInteger(CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), 0); LocationTable_Init(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index e05a5ed38..31d921657 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -665,25 +665,25 @@ void EntranceTrackerWindow::DrawElement() { ImGui::TableNextColumn(); ImGui::Text("Sort By"); - UIWidgets::EnhancementRadioButton("To", ENTRANCE_TRACKER_CVAR("SortBy"), 0); + UIWidgets::EnhancementRadioButton("To", CVAR_TRACKER_ENTRANCE("SortBy"), 0); UIWidgets::Tooltip("Sort entrances by the original source entrance"); - UIWidgets::EnhancementRadioButton("From", ENTRANCE_TRACKER_CVAR("SortBy"), 1); + UIWidgets::EnhancementRadioButton("From", CVAR_TRACKER_ENTRANCE("SortBy"), 1); UIWidgets::Tooltip("Sort entrances by the overrided destination"); UIWidgets::Spacer(2.0f); ImGui::Text("List Items"); - UIWidgets::PaddedEnhancementCheckbox("Auto scroll", ENTRANCE_TRACKER_CVAR("AutoScroll"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Auto scroll", CVAR_TRACKER_ENTRANCE("AutoScroll"), true, false); UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Highlight previous", ENTRANCE_TRACKER_CVAR("HighlightPrevious"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Highlight previous", CVAR_TRACKER_ENTRANCE("HighlightPrevious"), true, false); UIWidgets::Tooltip("Highlight the previous entrance that Link came from"); - UIWidgets::PaddedEnhancementCheckbox("Highlight available", ENTRANCE_TRACKER_CVAR("HighlightAvailable"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Highlight available", CVAR_TRACKER_ENTRANCE("HighlightAvailable"), true, false); UIWidgets::Tooltip("Highlight available entrances in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", ENTRANCE_TRACKER_CVAR("CollapseUndiscovered"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), true, false); UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group"); bool disableHideReverseEntrances = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_ON; static const char* disableHideReverseEntrancesText = "This option is disabled because \"Decouple Entrances\" is enabled."; - UIWidgets::PaddedEnhancementCheckbox("Hide reverse", ENTRANCE_TRACKER_CVAR("HideReverseEntrances"), true, false, + UIWidgets::PaddedEnhancementCheckbox("Hide reverse", CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), true, false, disableHideReverseEntrances, disableHideReverseEntrancesText, UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Hide reverse entrance transitions when Decouple Entrances is off"); UIWidgets::Spacer(0); @@ -691,17 +691,17 @@ void EntranceTrackerWindow::DrawElement() { ImGui::TableNextColumn(); ImGui::Text("Group By"); - UIWidgets::EnhancementRadioButton("Area", ENTRANCE_TRACKER_CVAR("GroupBy"), 0); + UIWidgets::EnhancementRadioButton("Area", CVAR_TRACKER_ENTRANCE("GroupBy"), 0); UIWidgets::Tooltip("Group entrances by their area"); - UIWidgets::EnhancementRadioButton("Type", ENTRANCE_TRACKER_CVAR("GroupBy"), 1); + UIWidgets::EnhancementRadioButton("Type", CVAR_TRACKER_ENTRANCE("GroupBy"), 1); UIWidgets::Tooltip("Group entrances by their entrance type"); UIWidgets::Spacer(2.0f); ImGui::Text("Spoiler Reveal"); - UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", ENTRANCE_TRACKER_CVAR("ShowTo"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", CVAR_TRACKER_ENTRANCE("ShowTo"), true, false); UIWidgets::Tooltip("Reveal the \"To\" entrance for undiscovered entrances"); - UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", ENTRANCE_TRACKER_CVAR("ShowFrom"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", CVAR_TRACKER_ENTRANCE("ShowFrom"), true, false); UIWidgets::Tooltip("Reveal the \"From\" entrance for undiscovered entrances"); ImGui::EndTable(); @@ -749,8 +749,8 @@ void EntranceTrackerWindow::DrawElement() { nextTreeState = 2; } - uint8_t destToggle = CVarGetInteger(ENTRANCE_TRACKER_CVAR("SortBy"), 0); - uint8_t groupToggle = CVarGetInteger(ENTRANCE_TRACKER_CVAR("GroupBy"), 0); + uint8_t destToggle = CVarGetInteger(CVAR_TRACKER_ENTRANCE("SortBy"), 0); + uint8_t groupToggle = CVarGetInteger(CVAR_TRACKER_ENTRANCE("GroupBy"), 0); // Combine destToggle and groupToggle to get a range of 0-3 uint8_t groupType = destToggle + (groupToggle * 2); @@ -801,7 +801,7 @@ void EntranceTrackerWindow::DrawElement() { // However, if entrances are decoupled, then all transitions need to be displayed, so we proceed with the filtering if ((original->type == ENTRANCE_TYPE_DUNGEON || original->type == ENTRANCE_TYPE_GROTTO || original->type == ENTRANCE_TYPE_INTERIOR) && (original->oneExit != 1 && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_OFF) && - CVarGetInteger(ENTRANCE_TRACKER_CVAR("HideReverseEntrances"), 1) == 1) { + CVarGetInteger(CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), 1) == 1) { continue; } @@ -812,8 +812,8 @@ void EntranceTrackerWindow::DrawElement() { bool isDiscovered = IsEntranceDiscovered(entrance.index); - bool showOriginal = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0)) || isDiscovered; - bool showOverride = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0)) || isDiscovered; + bool showOriginal = (!destToggle ? CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowTo"), 0) : CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowFrom"), 0)) || isDiscovered; + bool showOverride = (!destToggle ? CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowFrom"), 0) : CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowTo"), 0)) || isDiscovered; const char* origSrcAreaName = spoilerEntranceGroupNames[original->srcGroup].c_str(); const char* origTypeName = groupTypeNames[original->type].c_str(); @@ -826,7 +826,7 @@ void EntranceTrackerWindow::DrawElement() { const char* rplcDstName = showOverride ? override->destination.c_str() : ""; // Filter for entrances by group name, type, source/destination names, and meta tags - if ((!locationSearch.IsActive() && (showOriginal || showOverride || !CVarGetInteger(ENTRANCE_TRACKER_CVAR("CollapseUndiscovered"), 0))) || + if ((!locationSearch.IsActive() && (showOriginal || showOverride || !CVarGetInteger(CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), 0))) || ((showOriginal && (locationSearch.PassFilter(origSrcName) || locationSearch.PassFilter(origDstName) || locationSearch.PassFilter(origSrcAreaName) || locationSearch.PassFilter(origTypeName) || locationSearch.PassFilter(original->metaTag.c_str()))) || @@ -864,8 +864,8 @@ void EntranceTrackerWindow::DrawElement() { bool isDiscovered = IsEntranceDiscovered(entrance.index); - bool showOriginal = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0)) || isDiscovered; - bool showOverride = (!destToggle ? CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowFrom"), 0) : CVarGetInteger(ENTRANCE_TRACKER_CVAR("ShowTo"), 0)) || isDiscovered; + bool showOriginal = (!destToggle ? CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowTo"), 0) : CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowFrom"), 0)) || isDiscovered; + bool showOverride = (!destToggle ? CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowFrom"), 0) : CVarGetInteger(CVAR_TRACKER_ENTRANCE("ShowTo"), 0)) || isDiscovered; const char* unknown = "???"; @@ -879,16 +879,16 @@ void EntranceTrackerWindow::DrawElement() { // Handle highlighting and auto scroll if ((original->index == lastEntranceIndex || (override->reverseIndex == lastEntranceIndex && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_OFF)) && - CVarGetInteger(ENTRANCE_TRACKER_CVAR("HighlightPrevious"), 0)) { + CVarGetInteger(CVAR_TRACKER_ENTRANCE("HighlightPrevious"), 0)) { color = COLOR_ORANGE; } else if (LinkIsInArea(original) != -1) { - if (CVarGetInteger(ENTRANCE_TRACKER_CVAR("HighlightAvailable"), 0)) { + if (CVarGetInteger(CVAR_TRACKER_ENTRANCE("HighlightAvailable"), 0)) { color = COLOR_GREEN; } if (doAreaScroll) { doAreaScroll = false; - if (CVarGetInteger(ENTRANCE_TRACKER_CVAR("AutoScroll"), 0)) { + if (CVarGetInteger(CVAR_TRACKER_ENTRANCE("AutoScroll"), 0)) { ImGui::SetScrollHereY(0.0f); } } diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index e38af9fa3..5ae80b5e7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -413,17 +413,17 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { if (!GameInteractor::IsSaveLoaded()) { return; } - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int textSize = CVarGetInteger(ITEM_TRACKER_CVAR("TextSize"), 13); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int textSize = CVarGetInteger(CVAR_TRACKER_ITEM("TextSize"), 13); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ImVec2 p = ImGui::GetCursorScreenPos(); - int32_t trackerNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); - int32_t trackerKeyNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("KeyCounts"), KEYS_COLLECTED_MAX); + int32_t trackerNumberDisplayMode = CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); + int32_t trackerKeyNumberDisplayMode = CVarGetInteger(CVAR_TRACKER_ITEM("KeyCounts"), KEYS_COLLECTED_MAX); float textScalingFactor = static_cast(iconSize) / 36.0f; uint32_t actualItemId = INV_CONTENT(item.id); bool hasItem = actualItemId != ITEM_NONE; - if (CVarGetInteger(ITEM_TRACKER_CVAR("HookshotIdentifier"), 0)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("HookshotIdentifier"), 0)) { if ((actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT) && hasItem) { // Calculate the scaled position for the text @@ -469,7 +469,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImU32 currentColor = IM_COL_WHITE; ImU32 maxColor = item.id == QUEST_SKULL_TOKEN ? IM_COL_RED : IM_COL_GREEN; - bool shouldAlignToLeft = CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountAlignLeft"), 0) && + bool shouldAlignToLeft = CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountAlignLeft"), 0) && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_CAPACITY && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_AMMO; @@ -529,7 +529,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { uint8_t piecesTotal = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_TOTAL); ImU32 currentColor = gSaveContext.triforcePiecesCollected >= piecesRequired ? IM_COL_GREEN : IM_COL_WHITE; ImU32 maxColor = IM_COL_GREEN; - int32_t trackerTriforcePieceNumberDisplayMode = CVarGetInteger(ITEM_TRACKER_CVAR("TriforcePieceCounts"), TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); + int32_t trackerTriforcePieceNumberDisplayMode = CVarGetInteger(CVAR_TRACKER_ITEM("TriforcePieceCounts"), TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); currentString += std::to_string(gSaveContext.triforcePiecesCollected); currentString += "/"; @@ -559,7 +559,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { void DrawEquip(ItemTrackerItem item) { bool hasEquip = HasEquipment(item); - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -568,7 +568,7 @@ void DrawEquip(ItemTrackerItem item) { void DrawQuest(ItemTrackerItem item) { bool hasQuestItem = HasQuestItem(item); - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); ImGui::BeginGroup(); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -585,7 +585,7 @@ void DrawQuest(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) { uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); bool hasItem = actualItemId != ITEM_NONE; std::string itemName = ""; @@ -661,7 +661,7 @@ void DrawBottle(ItemTrackerItem item) { item = actualItemTrackerItemMap[actualItemId]; } - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); @@ -672,7 +672,7 @@ void DrawDungeonItem(ItemTrackerItem item) { uint32_t itemId = item.id; ImU32 dungeonColor = IM_COL_WHITE; uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false; bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; ImGui::BeginGroup(); @@ -718,7 +718,7 @@ void DrawDungeonItem(ItemTrackerItem item) { } void DrawSong(ItemTrackerItem item) { - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); ImVec2 p = ImGui::GetCursorScreenPos(); bool hasSong = HasSong(item); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); @@ -729,8 +729,8 @@ void DrawSong(ItemTrackerItem item) { void DrawNotes(bool resizeable = false) { ImGui::BeginGroup(); - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); struct ItemTrackerNotes { static int TrackerNotesResizeCallback(ImGuiInputTextCallbackData* data) { @@ -775,11 +775,11 @@ void BeginFloatingWindows(std::string UniqueName, ImGuiWindowFlags flags = 0) { windowFlags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); windowFlags |= ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar; - if (!CVarGetInteger(ITEM_TRACKER_CVAR("Draggable"), 0)) { + if (!CVarGetInteger(CVAR_TRACKER_ITEM("Draggable"), 0)) { windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; } } @@ -800,9 +800,9 @@ void EndFloatingWindows() { * Takes in a vector of ItemTrackerItem and draws them in rows of N items */ void DrawItemsInRows(std::vector items, int columns = 6) { - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); - int topPadding = (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); + int topPadding = (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; for (int i = 0; i < items.size(); i++) { int row = i / columns; @@ -817,8 +817,8 @@ void DrawItemsInRows(std::vector items, int columns = 6) { * Takes in a vector of ItemTrackerItem and draws them evenly spread across a circle */ void DrawItemsInACircle(std::vector items) { - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); ImVec2 max = ImGui::GetWindowContentRegionMax(); float radius = (iconSize + iconSpacing) * 2; @@ -827,7 +827,7 @@ void DrawItemsInACircle(std::vector items) { float angle = (float)i / items.size() * 2.0f * M_PI; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; - ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36) - 8) / 2.0f, y + 4)); + ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4)); items[i].drawFunc(items[i]); } } @@ -838,8 +838,8 @@ void DrawItemsInACircle(std::vector items) { * to then call DrawItemsInRows */ std::vector GetDungeonItemsVector(std::vector dungeons, int columns = 6) { - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); std::vector dungeonItems = {}; int rowCount = 0; @@ -894,8 +894,8 @@ void UpdateVectors() { dungeonRewards.insert(dungeonRewards.end(), dungeonRewardMedallions.begin(), dungeonRewardMedallions.end()); dungeonItems.clear(); - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.Layout"), 1) && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonItems.Layout"), 1) && CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), 1)) { dungeonItems = GetDungeonItemsVector(itemTrackerDungeonsWithMapsHorizontal, 12); // Manually adding Thieves Hideout to an open spot so we don't get an additional row for one item dungeonItems[23] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); @@ -905,7 +905,7 @@ void UpdateVectors() { dungeonItems[15] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); } } else { - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), 1)) { dungeonItems = GetDungeonItemsVector(itemTrackerDungeonsWithMapsCompact); // Manually adding Thieves Hideout to an open spot so we don't get an additional row for one item dungeonItems[35] = ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, SCENE_THIEVES_HIDEOUT, DrawDungeonItem); @@ -915,37 +915,37 @@ void UpdateVectors() { } mainWindowItems.clear(); - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), inventoryItems.begin(), inventoryItems.end()); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), equipmentItems.begin(), equipmentItems.end()); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), miscItems.begin(), miscItems.end()); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), dungeonRewardStones.begin(), dungeonRewardStones.end()); mainWindowItems.insert(mainWindowItems.end(), dungeonRewardMedallions.begin(), dungeonRewardMedallions.end()); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW && - CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW && + CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); } mainWindowItems.insert(mainWindowItems.end(), songItems.begin(), songItems.end()); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), dungeonItems.begin(), dungeonItems.end()); } // if we're adding greg to the misc window, // and misc isn't on the main window, // and it doesn't already have greg, add him - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && - CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW && + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && + CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW && std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item){return item.id == ITEM_RUPEE_GREEN;})) { miscItems.insert(miscItems.end(), gregItems.begin(), gregItems.end()); @@ -960,7 +960,7 @@ void UpdateVectors() { } // if we're adding greg to the main window - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { // insert empty items until we're on a new row for greg while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); @@ -971,9 +971,9 @@ void UpdateVectors() { } // If we're adding triforce pieces to the main window - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { // If Greg isn't on the main window, add empty items to place the triforce pieces on a new row. - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) != SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) != SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); } @@ -1009,56 +1009,56 @@ void ItemTrackerLoadFile() { void ItemTrackerWindow::DrawElement() { UpdateVectors(); - int iconSize = CVarGetInteger(ITEM_TRACKER_CVAR("IconSize"), 36); - int iconSpacing = CVarGetInteger(ITEM_TRACKER_CVAR("IconSpacing"), 12); - int comboButton1Mask = buttonMap[CVarGetInteger(ITEM_TRACKER_CVAR("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; - int comboButton2Mask = buttonMap[CVarGetInteger(ITEM_TRACKER_CVAR("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); + int comboButton1Mask = buttonMap[CVarGetInteger(CVAR_TRACKER_ITEM("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; + int comboButton2Mask = buttonMap[CVarGetInteger(CVAR_TRACKER_ITEM("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; OSContPad* buttonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = buttonsPressed != nullptr && buttonsPressed[0].button & comboButton1Mask && buttonsPressed[0].button & comboButton2Mask; - bool isPaused = CVarGetInteger(ITEM_TRACKER_CVAR("ShowOnlyPaused"), 0) == 0 || gPlayState != nullptr && gPlayState->pauseCtx.state > 0; + bool isPaused = CVarGetInteger(CVAR_TRACKER_ITEM("ShowOnlyPaused"), 0) == 0 || gPlayState != nullptr && gPlayState->pauseCtx.state > 0; - if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || isPaused && (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS ? CVarGetInteger(WINDOW_CVAR("ItemTracker"), 0) : comboButtonsHeld)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || isPaused && (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS ? CVarGetInteger(CVAR_WINDOW("ItemTracker"), 0) : comboButtonsHeld)) { if ( - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) ) { BeginFloatingWindows("Item Tracker##main window"); DrawItemsInRows(mainWindowItems, 6); - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW && CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { DrawNotes(); } EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Inventory"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Inventory Items Tracker"); DrawItemsInRows(inventoryItems); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Equipment"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Equipment Items Tracker"); DrawItemsInRows(equipmentItems, 3); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Misc Items Tracker"); DrawItemsInRows(miscItems, 4); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Dungeon Rewards Tracker"); - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonRewardsLayout"), 0)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonRewardsLayout"), 0)) { ImGui::BeginGroup(); DrawItemsInACircle(dungeonRewardMedallions); ImGui::EndGroup(); @@ -1071,16 +1071,16 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Songs"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Songs Tracker"); DrawItemsInRows(songItems); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Dungeon Items Tracker"); - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.Layout"), 1)) { - if (CVarGetInteger(ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), 1)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonItems.Layout"), 1)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), 1)) { DrawItemsInRows(dungeonItems, 12); } else { DrawItemsInRows(dungeonItems, 8); @@ -1091,19 +1091,19 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { BeginFloatingWindows("Greg Tracker"); DrawItemsInRows(gregItems); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Triforce Piece Tracker"); DrawItemsInRows(triforcePieces); EndFloatingWindows(); } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { ImGui::SetNextWindowSize(ImVec2(400,300), ImGuiCond_FirstUseEver); BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing); DrawNotes(true); @@ -1140,50 +1140,50 @@ void ItemTrackerSettingsWindow::DrawElement() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::ColorEdit4("BG Color##gItemTrackerBgColor", (float*)&ChromaKeyBackground, ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel)) { - CVarSetFloat(ITEM_TRACKER_CVAR("BgColorR"), ChromaKeyBackground.x); - CVarSetFloat(ITEM_TRACKER_CVAR("BgColorG"), ChromaKeyBackground.y); - CVarSetFloat(ITEM_TRACKER_CVAR("BgColorB"), ChromaKeyBackground.z); - CVarSetFloat(ITEM_TRACKER_CVAR("BgColorA"), ChromaKeyBackground.w); + CVarSetFloat(CVAR_TRACKER_ITEM("BgColorR"), ChromaKeyBackground.x); + CVarSetFloat(CVAR_TRACKER_ITEM("BgColorG"), ChromaKeyBackground.y); + CVarSetFloat(CVAR_TRACKER_ITEM("BgColorB"), ChromaKeyBackground.z); + CVarSetFloat(CVAR_TRACKER_ITEM("BgColorA"), ChromaKeyBackground.w); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::PopItemWidth(); - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", ITEM_TRACKER_CVAR("WindowType"), windowTypes, TRACKER_WINDOW_FLOATING)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Window Type", CVAR_TRACKER_ITEM("WindowType"), windowTypes, TRACKER_WINDOW_FLOATING)) { shouldUpdateVectors = true; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { - if (UIWidgets::PaddedEnhancementCheckbox("Enable Dragging", ITEM_TRACKER_CVAR("Draggable"))) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { + if (UIWidgets::PaddedEnhancementCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"))) { shouldUpdateVectors = true; } - if (UIWidgets::PaddedEnhancementCheckbox("Only enable while paused", ITEM_TRACKER_CVAR("ShowOnlyPaused"))) { + if (UIWidgets::PaddedEnhancementCheckbox("Only enable while paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"))) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", ITEM_TRACKER_CVAR("DisplayType.Main"), displayModes, TRACKER_DISPLAY_ALWAYS)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), displayModes, TRACKER_DISPLAY_ALWAYS)) { shouldUpdateVectors = true; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", ITEM_TRACKER_CVAR("ComboButton1"), buttons, TRACKER_COMBO_BUTTON_L)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 1", CVAR_TRACKER_ITEM("ComboButton1"), buttons, TRACKER_COMBO_BUTTON_L)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", ITEM_TRACKER_CVAR("ComboButton2"), buttons, TRACKER_COMBO_BUTTON_R)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttons, TRACKER_COMBO_BUTTON_R)) { shouldUpdateVectors = true; } } } UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", ITEM_TRACKER_CVAR("IconSize"), 25, 128, "", 36); - UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", ITEM_TRACKER_CVAR("IconSpacing"), -5, 50, "", 12); - UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", ITEM_TRACKER_CVAR("TextSize"), 1, 30, "", 13); + UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", CVAR_TRACKER_ITEM("IconSize"), 25, 128, "", 36); + UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", CVAR_TRACKER_ITEM("IconSpacing"), -5, 50, "", 12); + UIWidgets::EnhancementSliderInt("Text size : %dpx", "##ITEMTRACKERTEXTSIZE", CVAR_TRACKER_ITEM("TextSize"), 1, 30, "", 13); UIWidgets::Spacer(0); ImGui::Text("Ammo/Capacity Tracking"); - UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("ItemCountType"), itemTrackerCapacityTrackOptions, ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); + UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("ItemCountType"), itemTrackerCapacityTrackOptions, ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); UIWidgets::InsertHelpHoverText("Customize what the numbers under each item are tracking." "\n\nNote: items without capacity upgrades will track ammo even in capacity mode"); - if (CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger(ITEM_TRACKER_CVAR("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { - if (UIWidgets::PaddedEnhancementCheckbox("Align count to left side", ITEM_TRACKER_CVAR("ItemCountAlignLeft"))) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { + if (UIWidgets::PaddedEnhancementCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"))) { shouldUpdateVectors = true; } } @@ -1191,64 +1191,64 @@ void ItemTrackerSettingsWindow::DrawElement() { UIWidgets::Spacer(0); ImGui::Text("Key Count Tracking"); - UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("KeyCounts"), itemTrackerKeyTrackOptions, KEYS_COLLECTED_MAX); + UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("KeyCounts"), itemTrackerKeyTrackOptions, KEYS_COLLECTED_MAX); UIWidgets::InsertHelpHoverText("Customize what numbers are shown for key tracking."); UIWidgets::Spacer(0); ImGui::Text("Triforce Piece Count Tracking"); - UIWidgets::EnhancementCombobox(ITEM_TRACKER_CVAR("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); + UIWidgets::EnhancementCombobox(CVAR_TRACKER_ITEM("TriforcePieceCounts"), itemTrackerTriforcePieceTrackOptions, TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX); UIWidgets::InsertHelpHoverText("Customize what numbers are shown for triforce piece tracking."); ImGui::TableNextColumn(); - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Inventory", ITEM_TRACKER_CVAR("DisplayType.Inventory"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Inventory", CVAR_TRACKER_ITEM("DisplayType.Inventory"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Equipment", ITEM_TRACKER_CVAR("DisplayType.Equipment"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Misc", ITEM_TRACKER_CVAR("DisplayType.Misc"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Rewards", ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { - if (UIWidgets::PaddedEnhancementCheckbox("Circle display", ITEM_TRACKER_CVAR("DungeonRewardsLayout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { + if (UIWidgets::PaddedEnhancementCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, false)) { shouldUpdateVectors = true; } } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Songs", ITEM_TRACKER_CVAR("DisplayType.Songs"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, SECTION_DISPLAY_MAIN_WINDOW)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Items", ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Dungeon Items", CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) { - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { - if (UIWidgets::PaddedEnhancementCheckbox("Horizontal display", ITEM_TRACKER_CVAR("DungeonItems.Layout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (UIWidgets::PaddedEnhancementCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { shouldUpdateVectors = true; } } - if (UIWidgets::PaddedEnhancementCheckbox("Maps and compasses", ITEM_TRACKER_CVAR("DungeonItems.DisplayMaps"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { + if (UIWidgets::PaddedEnhancementCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true)) { shouldUpdateVectors = true; } } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Greg", ITEM_TRACKER_CVAR("DisplayType.Greg"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Greg", CVAR_TRACKER_ITEM("DisplayType.Greg"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", ITEM_TRACKER_CVAR("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (CVarGetInteger(ITEM_TRACKER_CVAR("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", ITEM_TRACKER_CVAR("DisplayType.Notes"), displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } } - UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", ITEM_TRACKER_CVAR("HookshotIdentifier")); + UIWidgets::EnhancementCheckbox("Show Hookshot Identifiers", CVAR_TRACKER_ITEM("HookshotIdentifier")); UIWidgets::InsertHelpHoverText("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot."); UIWidgets::Spacer(0); @@ -1260,10 +1260,10 @@ void ItemTrackerSettingsWindow::DrawElement() { } void ItemTrackerWindow::InitElement() { - float trackerBgR = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorR"), 0); - float trackerBgG = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorG"), 0); - float trackerBgB = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorB"), 0); - float trackerBgA = CVarGetFloat(ITEM_TRACKER_CVAR("BgColorA"), 1); + float trackerBgR = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorR"), 0); + float trackerBgG = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorG"), 0); + float trackerBgB = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorB"), 0); + float trackerBgA = CVarGetFloat(CVAR_TRACKER_ITEM("BgColorA"), 1); ChromaKeyBackground = { trackerBgR, trackerBgG, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c91fd68d4..e8c88fc61 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1148,8 +1148,8 @@ extern "C" void InitOTR() { srand(now); #ifdef ENABLE_REMOTE_CONTROL SDLNet_Init(); - if (CVarGetInteger(REMOTE_CVAR("Enabled"), 0)) { - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + if (CVarGetInteger(CVAR_REMOTE("Enabled"), 0)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Enable(); break; @@ -1174,8 +1174,8 @@ extern "C" void DeinitOTR() { SaveManager_ThreadPoolWait(); OTRAudio_Exit(); #ifdef ENABLE_REMOTE_CONTROL - if (CVarGetInteger(REMOTE_CVAR("Enabled"), 0)) { - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + if (CVarGetInteger(CVAR_REMOTE("Enabled"), 0)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Disable(); break; @@ -1246,7 +1246,7 @@ extern "C" void Graph_StartFrame() { switch (dwScancode) { case KbScancode::LUS_KB_F5: { - if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { + if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; @@ -1268,7 +1268,7 @@ extern "C" void Graph_StartFrame() { break; } case KbScancode::LUS_KB_F6: { - if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { + if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; @@ -1283,7 +1283,7 @@ extern "C" void Graph_StartFrame() { break; } case KbScancode::LUS_KB_F7: { - if (CVarGetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0) == 0) { + if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; @@ -2535,12 +2535,12 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { RandomizerInf randoInf = (RandomizerInf)((textId - (TEXT_SHOP_ITEM_RANDOM + NUM_SHOP_ITEMS)) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1); messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SHOP_ITEM_RANDOM_CONFIRM); } - } else if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), 1) && + } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { messageEntry = Randomizer::GetRupeeMessage(textId); // In rando, replace Navi's general overworld hints with rando-related gameplay tips - } else if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), 1) && textId >= 0x0140 && textId <= 0x015F) { + } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= 0x0140 && textId <= 0x015F) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index f34b2fee5..49b41ce86 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -65,23 +65,21 @@ private: uint32_t IsGameMasterQuest(); #endif -#define RANDO_ENHANCEMENT_CVAR(var) "gRandoEnhancements." var -#define RANDOMIZER_SEED_CVAR(var) "gRandoSettings." var -#define COSMETIC_CVAR(var) "gCosmetics." var -#define AUDIO_CVAR(var) "gAudioEditor." var -#define REPL_SEQ_CVAR(var) AUDIO_CVAR("ReplacedSequences." var) -#define EXCL_SEQ_CVAR(var) AUDIO_CVAR("Excluded." var) -#define CHEAT_CVAR(var) "gCheats." var -#define ENHANCEMENT_CVAR(var) "gEnhancements." var -#define SETTING_CVAR(var) "gSettings." var -#define WINDOW_CVAR(var) "gOpenWindows." var -#define TRACKER_CVAR(var) "gTrackers." var -#define ITEM_TRACKER_CVAR(var) TRACKER_CVAR("ItemTracker." var) -#define CHECK_TRACKER_CVAR(var) TRACKER_CVAR("CheckTracker." var) -#define ENTRANCE_TRACKER_CVAR(var) TRACKER_CVAR("EntranceTracker." var) -#define DEV_TOOLS_CVAR(var) "gDeveloperTools." var -#define GENERAL_CVAR(var) "gGeneral." var -#define REMOTE_CVAR(var) "gRemote." var +#define CVAR_RANDOMIZER_ENHANCEMENT(var) "gRandoEnhancements." var +#define CVAR_RANDOMIZER_SETTING(var) "gRandoSettings." var +#define CVAR_COSMETIC(var) "gCosmetics." var +#define CVAR_AUDIO(var) "gAudioEditor." var +#define CVAR_CHEAT(var) "gCheats." var +#define CVAR_ENHANCEMENT(var) "gEnhancements." var +#define CVAR_SETTING(var) "gSettings." var +#define CVAR_WINDOW(var) "gOpenWindows." var +#define CVAR_TRACKER(var) "gTrackers." var +#define CVAR_TRACKER_ITEM(var) CVAR_TRACKER("ItemTracker." var) +#define CVAR_TRACKER_CHECK(var) CVAR_TRACKER("CheckTracker." var) +#define CVAR_TRACKER_ENTRANCE(var) CVAR_TRACKER("EntranceTracker." var) +#define CVAR_DEVELOPER_TOOLS(var) "gDeveloperTools." var +#define CVAR_GENERAL(var) "gGeneral." var +#define CVAR_REMOTE(var) "gRemote." var #ifndef __cplusplus void InitOTR(void); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 07a37c02a..eadfb75de 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -628,10 +628,10 @@ void SaveManager::InitFileDebug() { //don't apply gDebugSaveFileMode on the title screen if (gSaveContext.fileNum != 0xFF) { - if (CVarGetInteger("gDebugSaveFileMode", 1) == 2) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), 1) == 2) { InitFileMaxed(); return; - } else if (CVarGetInteger("gDebugSaveFileMode", 1) == 0) { + } else if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), 1) == 0) { return; } } diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index d10532ee3..28366a668 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -165,41 +165,41 @@ namespace SohGui { SPDLOG_ERROR("Could not find input editor window"); } - mAudioEditorWindow = std::make_shared(WINDOW_CVAR("AudioEditor"), "Audio Editor"); + mAudioEditorWindow = std::make_shared(CVAR_WINDOW("AudioEditor"), "Audio Editor"); gui->AddGuiWindow(mAudioEditorWindow); - mInputViewer = std::make_shared(WINDOW_CVAR("InputViewer"), "Input Viewer"); + mInputViewer = std::make_shared(CVAR_WINDOW("InputViewer"), "Input Viewer"); gui->AddGuiWindow(mInputViewer); - mInputViewerSettings = std::make_shared(WINDOW_CVAR("InputViewerSettings"), "Input Viewer Settings"); + mInputViewerSettings = std::make_shared(CVAR_WINDOW("InputViewerSettings"), "Input Viewer Settings"); gui->AddGuiWindow(mInputViewerSettings); - mCosmeticsEditorWindow = std::make_shared(WINDOW_CVAR("CosmeticsEditor"), "Cosmetics Editor"); + mCosmeticsEditorWindow = std::make_shared(CVAR_WINDOW("CosmeticsEditor"), "Cosmetics Editor"); gui->AddGuiWindow(mCosmeticsEditorWindow); - mActorViewerWindow = std::make_shared(WINDOW_CVAR("ActorViewer"), "Actor Viewer"); + mActorViewerWindow = std::make_shared(CVAR_WINDOW("ActorViewer"), "Actor Viewer"); gui->AddGuiWindow(mActorViewerWindow); - mColViewerWindow = std::make_shared(WINDOW_CVAR("CollisionViewer"), "Collision Viewer"); + mColViewerWindow = std::make_shared(CVAR_WINDOW("CollisionViewer"), "Collision Viewer"); gui->AddGuiWindow(mColViewerWindow); - mSaveEditorWindow = std::make_shared(WINDOW_CVAR("SaveEditor"), "Save Editor"); + mSaveEditorWindow = std::make_shared(CVAR_WINDOW("SaveEditor"), "Save Editor"); gui->AddGuiWindow(mSaveEditorWindow); - mDLViewerWindow = std::make_shared(WINDOW_CVAR("DLViewer"), "Display List Viewer"); + mDLViewerWindow = std::make_shared(CVAR_WINDOW("DLViewer"), "Display List Viewer"); gui->AddGuiWindow(mDLViewerWindow); - mValueViewerWindow = std::make_shared(WINDOW_CVAR("ValueViewer"), "Value Viewer"); + mValueViewerWindow = std::make_shared(CVAR_WINDOW("ValueViewer"), "Value Viewer"); gui->AddGuiWindow(mValueViewerWindow); - mMessageViewerWindow = std::make_shared(WINDOW_CVAR("MessageViewer"), "Message Viewer"); + mMessageViewerWindow = std::make_shared(CVAR_WINDOW("MessageViewer"), "Message Viewer"); gui->AddGuiWindow(mMessageViewerWindow); - mGameplayStatsWindow = std::make_shared(WINDOW_CVAR("GameplayStats"), "Gameplay Stats"); + mGameplayStatsWindow = std::make_shared(CVAR_WINDOW("GameplayStats"), "Gameplay Stats"); gui->AddGuiWindow(mGameplayStatsWindow); - mCheckTrackerWindow = std::make_shared(WINDOW_CVAR("CheckTracker"), "Check Tracker"); + mCheckTrackerWindow = std::make_shared(CVAR_WINDOW("CheckTracker"), "Check Tracker"); gui->AddGuiWindow(mCheckTrackerWindow); - mCheckTrackerSettingsWindow = std::make_shared(WINDOW_CVAR("CheckTrackerSettings"), "Check Tracker Settings"); + mCheckTrackerSettingsWindow = std::make_shared(CVAR_WINDOW("CheckTrackerSettings"), "Check Tracker Settings"); gui->AddGuiWindow(mCheckTrackerSettingsWindow); - mEntranceTrackerWindow = std::make_shared(WINDOW_CVAR("EntranceTracker"),"Entrance Tracker"); + mEntranceTrackerWindow = std::make_shared(CVAR_WINDOW("EntranceTracker"),"Entrance Tracker"); gui->AddGuiWindow(mEntranceTrackerWindow); - mItemTrackerWindow = std::make_shared(WINDOW_CVAR("ItemTracker"), "Item Tracker"); + mItemTrackerWindow = std::make_shared(CVAR_WINDOW("ItemTracker"), "Item Tracker"); gui->AddGuiWindow(mItemTrackerWindow); - mItemTrackerSettingsWindow = std::make_shared(WINDOW_CVAR("ItemTrackerSettings"), "Item Tracker Settings"); + mItemTrackerSettingsWindow = std::make_shared(CVAR_WINDOW("ItemTrackerSettings"), "Item Tracker Settings"); gui->AddGuiWindow(mItemTrackerSettingsWindow); - mRandomizerSettingsWindow = std::make_shared(WINDOW_CVAR("RandomizerSettings"), "Randomizer Settings"); + mRandomizerSettingsWindow = std::make_shared(CVAR_WINDOW("RandomizerSettings"), "Randomizer Settings"); gui->AddGuiWindow(mRandomizerSettingsWindow); - mAdvancedResolutionSettingsWindow = std::make_shared(WINDOW_CVAR("AdvancedResolutionEditor"), "Advanced Resolution Settings"); + mAdvancedResolutionSettingsWindow = std::make_shared(CVAR_WINDOW("AdvancedResolutionEditor"), "Advanced Resolution Settings"); gui->AddGuiWindow(mAdvancedResolutionSettingsWindow); mModalWindow = std::make_shared("gOpenWindows.modalWindowEnabled", "Modal Window"); gui->AddGuiWindow(mModalWindow); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index be75a6127..2169e3d02 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -248,12 +248,12 @@ void DrawSettingsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mInputViewer) { - if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger(WINDOW_CVAR("InputViewer"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { mInputViewer->ToggleVisibility(); } } if (mInputViewerSettings) { - if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger(WINDOW_CVAR("InputViewerSettings"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger(CVAR_WINDOW("InputViewerSettings"), 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { mInputViewerSettings->ToggleVisibility(); } } @@ -287,7 +287,7 @@ void DrawSettingsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); UIWidgets::Spacer(0); - if (ImGui::Button(GetWindowButtonText("Advanced Resolution", CVarGetInteger(WINDOW_CVAR("AdvancedResolutionEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Advanced Resolution", CVarGetInteger(CVAR_WINDOW("AdvancedResolutionEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mAdvancedResolutionSettingsWindow->ToggleVisibility(); } ImGui::PopStyleColor(1); @@ -547,7 +547,7 @@ extern std::shared_ptr mGameplayStatsWindow; void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Enhancements")) { - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS); @@ -1395,19 +1395,19 @@ void DrawEnhancementsMenu() { ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mCosmeticsEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVarGetInteger(WINDOW_CVAR("CosmeticsEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVarGetInteger(CVAR_WINDOW("CosmeticsEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mCosmeticsEditorWindow->ToggleVisibility(); } } if (mAudioEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Audio Editor", CVarGetInteger(WINDOW_CVAR("AudioEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Audio Editor", CVarGetInteger(CVAR_WINDOW("AudioEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mAudioEditorWindow->ToggleVisibility(); } } if (mGameplayStatsWindow) { - if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVarGetInteger(WINDOW_CVAR("GameplayStats"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Gameplay Stats", CVarGetInteger(CVAR_WINDOW("GameplayStats"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mGameplayStatsWindow->ToggleVisibility(); } } @@ -1430,7 +1430,7 @@ void DrawEnhancementsMenu() { void DrawCheatsMenu() { if (ImGui::BeginMenu("Cheats")) { - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 8.0f); ImGui::BeginTable("##cheatsMenu", 2, ImGuiTableFlags_SizingFixedFit); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); @@ -1440,32 +1440,32 @@ void DrawCheatsMenu() { ImGui::Text("Inventory:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementCheckbox("Super Tunic", CHEAT_CVAR("SuperTunic"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Super Tunic", CVAR_CHEAT("SuperTunic"), true, false); UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); - UIWidgets::PaddedEnhancementCheckbox("Easy ISG", CHEAT_CVAR("EasyISG"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy ISG", CVAR_CHEAT("EasyISG"), true, false); UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); - UIWidgets::PaddedEnhancementCheckbox("Easy QPA", CHEAT_CVAR("EasyQPA"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy QPA", CVAR_CHEAT("EasyQPA"), true, false); UIWidgets::Tooltip("Gives you the glitched damage value of the quick put away glitch."); - UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", CHEAT_CVAR("TimelessEquipment"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Timeless Equipment", CVAR_CHEAT("TimelessEquipment"), true, false); UIWidgets::Tooltip("Allows any item to be equipped, regardless of age\nAlso allows Child to use Adult strength upgrades"); - UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", CHEAT_CVAR("NoRestrictItems"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", CVAR_CHEAT("NoRestrictItems"), true, false); UIWidgets::Tooltip("Allows you to use any item at any location"); - UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", CHEAT_CVAR("FireproofDekuShield"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", CVAR_CHEAT("FireproofDekuShield"), true, false); UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); - UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", CHEAT_CVAR("ShieldTwoHanded"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", CVAR_CHEAT("ShieldTwoHanded"), true, false); UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); UIWidgets::Spacer(2.0f); ImGui::Text("Deku Sticks:"); - UIWidgets::EnhancementCombobox(CHEAT_CVAR("DekuStick"), DekuStickCheat, DEKU_STICK_NORMAL); + UIWidgets::EnhancementCombobox(CVAR_CHEAT("DekuStick"), DekuStickCheat, DEKU_STICK_NORMAL); UIWidgets::Spacer(2.0f); - UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.2fx", "##gBombTimerMultiplier", CHEAT_CVAR("BombTimerMultiplier"), 0.1f, 5.0f, "", 1.0f, false); - UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", CHEAT_CVAR("HookshotEverything"), true, false); + UIWidgets::EnhancementSliderFloat("Bomb Timer Multiplier: %.2fx", "##gBombTimerMultiplier", CVAR_CHEAT("BombTimerMultiplier"), 0.1f, 5.0f, "", 1.0f, false); + UIWidgets::PaddedEnhancementCheckbox("Hookshot Everything", CVAR_CHEAT("HookshotEverything"), true, false); UIWidgets::Tooltip("Makes every surface in the game hookshot-able"); UIWidgets::Spacer(0); - UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", CHEAT_CVAR("HookshotReachMultiplier"), 1.0f, 5.0f, "", 1.0f, false); + UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", CVAR_CHEAT("HookshotReachMultiplier"), 1.0f, 5.0f, "", 1.0f, false); UIWidgets::Spacer(2.0f); if (ImGui::Button("Change Age")) { - CVarSetInteger(GENERAL_CVAR("SwitchAge"), 1); + CVarSetInteger(CVAR_GENERAL("SwitchAge"), 1); } UIWidgets::Tooltip("Switches Link's age and reloads the area."); UIWidgets::Spacer(2.0f); @@ -1478,12 +1478,12 @@ void DrawCheatsMenu() { UIWidgets::Spacer(2.0f); if (ImGui::BeginMenu("Infinite...")) { - UIWidgets::EnhancementCheckbox("Money", CHEAT_CVAR("InfiniteMoney")); - UIWidgets::PaddedEnhancementCheckbox("Health", CHEAT_CVAR("InfiniteHealth"), true, false); - UIWidgets::PaddedEnhancementCheckbox("Ammo", CHEAT_CVAR("InfiniteAmmo"), true, false); - UIWidgets::PaddedEnhancementCheckbox("Magic", CHEAT_CVAR("InfiniteMagic"), true, false); - UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", CHEAT_CVAR("InfiniteNayru"), true, false); - UIWidgets::PaddedEnhancementCheckbox("Epona Boost", CHEAT_CVAR("InfiniteEponaBoost"), true, false); + UIWidgets::EnhancementCheckbox("Money", CVAR_CHEAT("InfiniteMoney")); + UIWidgets::PaddedEnhancementCheckbox("Health", CVAR_CHEAT("InfiniteHealth"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Ammo", CVAR_CHEAT("InfiniteAmmo"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Magic", CVAR_CHEAT("InfiniteMagic"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", CVAR_CHEAT("InfiniteNayru"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Epona Boost", CVAR_CHEAT("InfiniteEponaBoost"), true, false); ImGui::EndMenu(); } @@ -1501,13 +1501,13 @@ void DrawCheatsMenu() { UIWidgets::PaddedText("they WILL break across transitions and", true, false); UIWidgets::PaddedText("load zones (like doors). Support for", true, false); UIWidgets::PaddedText("related issues will not be provided.", true, false); - if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", CHEAT_CVAR("SaveStatePromise"), true, + if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", CVAR_CHEAT("SaveStatePromise"), true, false)) { - CVarSetInteger(CHEAT_CVAR("SaveStatesEnabled"), 0); + CVarSetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - if (CVarGetInteger(CHEAT_CVAR("SaveStatePromise"), 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", CHEAT_CVAR("SaveStatesEnabled"), true, + if (CVarGetInteger(CVAR_CHEAT("SaveStatePromise"), 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", CVAR_CHEAT("SaveStatesEnabled"), true, false); UIWidgets::Tooltip("F5 to save, F6 to change slots, F7 to load"); } @@ -1519,44 +1519,44 @@ void DrawCheatsMenu() { ImGui::Text("Behavior:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementCheckbox("No Clip", CHEAT_CVAR("NoClip"), true, false); + UIWidgets::PaddedEnhancementCheckbox("No Clip", CVAR_CHEAT("NoClip"), true, false); UIWidgets::Tooltip("Allows you to walk through walls"); - UIWidgets::PaddedEnhancementCheckbox("Climb Everything", CHEAT_CVAR("ClimbEverything"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Climb Everything", CVAR_CHEAT("ClimbEverything"), true, false); UIWidgets::Tooltip("Makes every surface in the game climbable"); - UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", CHEAT_CVAR("MoonJumpOnL"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", CVAR_CHEAT("MoonJumpOnL"), true, false); UIWidgets::Tooltip("Holding L makes you float into the air"); - UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", CHEAT_CVAR("EasyPauseBuffer"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Easy Frame Advancing", CVAR_CHEAT("EasyPauseBuffer"), true, false); UIWidgets::Tooltip("Continue holding START button when unpausing to only advance a single frame and then re-pause"); - const bool bEasyFrameAdvanceEnabled = CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0); - UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", CHEAT_CVAR("EasyInputBuffer"), true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled", UIWidgets::CheckboxGraphics::Checkmark); + const bool bEasyFrameAdvanceEnabled = CVarGetInteger(CVAR_CHEAT("EasyPauseBuffer"), 0); + UIWidgets::PaddedEnhancementCheckbox("Easy Input Buffering", CVAR_CHEAT("EasyInputBuffer"), true, false, bEasyFrameAdvanceEnabled, "Forced enabled when Easy Frame Advancing is enabled", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Inputs that are held down while the Subscreen is closing will be pressed when the game is resumed"); - UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", CHEAT_CVAR("DropsDontDie"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", CVAR_CHEAT("DropsDontDie"), true, false); UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); - UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", CHEAT_CVAR("NoFishDespawn"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fish Don't despawn", CVAR_CHEAT("NoFishDespawn"), true, false); UIWidgets::Tooltip("Prevents fish from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", CHEAT_CVAR("NoBugsDespawn"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Bugs Don't despawn", CVAR_CHEAT("NoBugsDespawn"), true, false); UIWidgets::Tooltip("Prevents bugs from automatically despawning after a while when dropped"); - UIWidgets::PaddedEnhancementCheckbox("Freeze Time", CHEAT_CVAR("FreezeTime"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Freeze Time", CVAR_CHEAT("FreezeTime"), true, false); UIWidgets::Tooltip("Freezes the time of day"); - UIWidgets::PaddedEnhancementCheckbox("Time Sync", CHEAT_CVAR("TimeSync"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Time Sync", CVAR_CHEAT("TimeSync"), true, false); UIWidgets::Tooltip("This syncs the ingame time with the real world time"); - UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", CHEAT_CVAR("NoRedeadFreeze"), true, false); + UIWidgets::PaddedEnhancementCheckbox("No ReDead/Gibdo Freeze", CVAR_CHEAT("NoRedeadFreeze"), true, false); UIWidgets::Tooltip("Prevents ReDeads and Gibdos from being able to freeze you with their scream"); - UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", CHEAT_CVAR("NoKeeseGuayTarget"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Keese/Guay don't target you", CVAR_CHEAT("NoKeeseGuayTarget"), true, false); UIWidgets::Tooltip("Keese and Guay no longer target you and simply ignore you as if you were wearing the skull mask"); { - static int32_t betaQuestEnabled = CVarGetInteger(CHEAT_CVAR("EnableBetaQuest"), 0); + static int32_t betaQuestEnabled = CVarGetInteger(CVAR_CHEAT("EnableBetaQuest"), 0); static int32_t lastBetaQuestEnabled = betaQuestEnabled; - static int32_t betaQuestWorld = CVarGetInteger(CHEAT_CVAR("BetaQuestWorld"), 0xFFEF); + static int32_t betaQuestWorld = CVarGetInteger(CVAR_CHEAT("BetaQuestWorld"), 0xFFEF); static int32_t lastBetaQuestWorld = betaQuestWorld; if (!isBetaQuestEnabled) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", CHEAT_CVAR("EnableBetaQuest"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", CVAR_CHEAT("EnableBetaQuest"), true, false); UIWidgets::Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); - betaQuestEnabled = CVarGetInteger(CHEAT_CVAR("EnableBetaQuest"), 0); + betaQuestEnabled = CVarGetInteger(CVAR_CHEAT("EnableBetaQuest"), 0); if (betaQuestEnabled) { if (betaQuestEnabled != lastBetaQuestEnabled) { betaQuestWorld = 0; @@ -1588,15 +1588,15 @@ void DrawCheatsMenu() { } else { lastBetaQuestWorld = betaQuestWorld = 0xFFEF; - CVarClear(CHEAT_CVAR("BetaQuestWorld")); + CVarClear(CVAR_CHEAT("BetaQuestWorld")); } if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) { // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. lastBetaQuestEnabled = betaQuestEnabled; lastBetaQuestWorld = betaQuestWorld; - CVarSetInteger(CHEAT_CVAR("EnableBetaQuest"), betaQuestEnabled); - CVarSetInteger(CHEAT_CVAR("BetaQuestWorld"), betaQuestWorld); + CVarSetInteger(CVAR_CHEAT("EnableBetaQuest"), betaQuestEnabled); + CVarSetInteger(CVAR_CHEAT("BetaQuestWorld"), betaQuestWorld); std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); @@ -1624,15 +1624,15 @@ extern std::shared_ptr mMessageViewerWindow; void DrawDeveloperToolsMenu() { if (ImGui::BeginMenu("Developer Tools")) { - ImGui::BeginDisabled(CVarGetInteger(SETTING_CVAR("DisableChanges"), 0)); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - UIWidgets::EnhancementCheckbox("OoT Debug Mode", DEV_TOOLS_CVAR("DebugEnabled")); + UIWidgets::EnhancementCheckbox("OoT Debug Mode", CVAR_DEVELOPER_TOOLS("DebugEnabled")); UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); - if (CVarGetInteger(DEV_TOOLS_CVAR("DebugEnabled"), 0)) { - UIWidgets::EnhancementCheckbox("OoT Registry Editor", DEV_TOOLS_CVAR("RegEditEnabled")); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { + UIWidgets::EnhancementCheckbox("OoT Registry Editor", CVAR_DEVELOPER_TOOLS("RegEditEnabled")); UIWidgets::Tooltip("Enables the registry editor"); ImGui::Text("Debug Save File Mode:"); - UIWidgets::EnhancementCombobox(DEV_TOOLS_CVAR("DebugSaveFileMode"), DebugSaveFileModes, 1); + UIWidgets::EnhancementCombobox(CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), DebugSaveFileModes, 1); UIWidgets::Tooltip( "Changes the behaviour of debug file select creation (creating a save file on slot 1 with debug mode on)\n" "- Off: The debug save file will be a normal savefile\n" @@ -1640,17 +1640,17 @@ void DrawDeveloperToolsMenu() { "- Maxed: The debug save file will be a save file with all of the items & upgrades" ); } - UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), true, false); + UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", CVAR_DEVELOPER_TOOLS("SkulltulaDebugEnabled"), true, false); UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); - UIWidgets::PaddedEnhancementCheckbox("Fast File Select", DEV_TOOLS_CVAR("SkipLogoTitle"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fast File Select", CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), true, false); UIWidgets::Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); - if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), 0)) { ImGui::Text("Loading:"); - UIWidgets::EnhancementCombobox(DEV_TOOLS_CVAR("SaveFileID"), FastFileSelect, 0); + UIWidgets::EnhancementCombobox(CVAR_DEVELOPER_TOOLS("SaveFileID"), FastFileSelect, 0); }; - UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", DEV_TOOLS_CVAR("BetterDebugWarpScreen"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Better Debug Warp Screen", CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), true, false); UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day"); - UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", DEV_TOOLS_CVAR("DebugWarpScreenTranslation"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Translate the Debug Warp Screen based on the game language"); if (gPlayState != NULL) { UIWidgets::PaddedSeparator(); @@ -1661,12 +1661,12 @@ void DrawDeveloperToolsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (ImGui::Button("Advance 1", ImVec2(ImGui::GetContentRegionAvail().x / 2.0f, 0.0f))) { - CVarSetInteger(GENERAL_CVAR("FrameAdvance"), 1); + CVarSetInteger(CVAR_GENERAL("FrameAdvance"), 1); } ImGui::SameLine(); ImGui::Button("Advance (Hold)"); if (ImGui::IsItemActive()) { - CVarSetInteger(GENERAL_CVAR("FrameAdvance"), 1); + CVarSetInteger(CVAR_GENERAL("FrameAdvance"), 1); } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); @@ -1692,37 +1692,37 @@ void DrawDeveloperToolsMenu() { } UIWidgets::Spacer(0); if (mSaveEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Save Editor", CVarGetInteger(WINDOW_CVAR("SaveEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Save Editor", CVarGetInteger(CVAR_WINDOW("SaveEditor"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mSaveEditorWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mColViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVarGetInteger(WINDOW_CVAR("CollisionViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVarGetInteger(CVAR_WINDOW("CollisionViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mColViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mActorViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVarGetInteger(WINDOW_CVAR("ActorViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVarGetInteger(CVAR_WINDOW("ActorViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mActorViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mDLViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Display List Viewer", CVarGetInteger(WINDOW_CVAR("DLViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Display List Viewer", CVarGetInteger(CVAR_WINDOW("DLViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mDLViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mValueViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Value Viewer", CVarGetInteger(WINDOW_CVAR("ValueViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Value Viewer", CVarGetInteger(CVAR_WINDOW("ValueViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mValueViewerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mMessageViewerWindow) { - if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger(WINDOW_CVAR("MessageViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Message Viewer", CVarGetInteger(CVAR_WINDOW("MessageViewer"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mMessageViewerWindow->ToggleVisibility(); } } @@ -1752,27 +1752,27 @@ bool isStringEmpty(std::string str) { #ifdef ENABLE_REMOTE_CONTROL void DrawRemoteControlMenu() { if (ImGui::BeginMenu("Network")) { - static std::string ip = CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1"); - static uint16_t port = CVarGetInteger(REMOTE_CVAR("Port"), 43384); - bool isFormValid = !isStringEmpty(CVarGetString(REMOTE_CVAR("IP"), "127.0.0.1")) && port > 1024 && port < 65535; + static std::string ip = CVarGetString(CVAR_REMOTE("IP"), "127.0.0.1"); + static uint16_t port = CVarGetInteger(CVAR_REMOTE("Port"), 43384); + bool isFormValid = !isStringEmpty(CVarGetString(CVAR_REMOTE("IP"), "127.0.0.1")) && port > 1024 && port < 65535; const char* remoteOptions[2] = { "Sail", "Crowd Control"}; ImGui::BeginDisabled(GameInteractor::Instance->isRemoteInteractorEnabled); ImGui::Text("Remote Interaction Scheme"); - if (UIWidgets::EnhancementCombobox(REMOTE_CVAR("Scheme"), remoteOptions, GI_SCHEME_SAIL)) { - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + if (UIWidgets::EnhancementCombobox(CVAR_REMOTE("Scheme"), remoteOptions, GI_SCHEME_SAIL)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: case GI_SCHEME_CROWD_CONTROL: - CVarSetString(REMOTE_CVAR("IP"), "127.0.0.1"); - CVarSetInteger(REMOTE_CVAR("Port"), 43384); + CVarSetString(CVAR_REMOTE("IP"), "127.0.0.1"); + CVarSetInteger(CVAR_REMOTE("Port"), 43384); ip = "127.0.0.1"; port = 43384; break; } LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: UIWidgets::InsertHelpHoverText( "Sail is a networking protocol designed to facilitate remote " @@ -1805,14 +1805,14 @@ void DrawRemoteControlMenu() { ImGui::Text("Remote IP & Port"); if (ImGui::InputText("##gRemote.IP", (char*)ip.c_str(), ip.capacity() + 1)) { - CVarSetString(REMOTE_CVAR("IP"), ip.c_str()); + CVarSetString(CVAR_REMOTE("IP"), ip.c_str()); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetFontSize() * 5); if (ImGui::InputScalar("##gRemote.Port", ImGuiDataType_U16, &port)) { - CVarSetInteger(REMOTE_CVAR("Port"), port); + CVarSetInteger(CVAR_REMOTE("Port"), port); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -1825,9 +1825,9 @@ void DrawRemoteControlMenu() { const char* buttonLabel = GameInteractor::Instance->isRemoteInteractorEnabled ? "Disable" : "Enable"; if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) { if (GameInteractor::Instance->isRemoteInteractorEnabled) { - CVarSetInteger(REMOTE_CVAR("Enabled"), 0); + CVarSetInteger(CVAR_REMOTE("Enabled"), 0); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Disable(); break; @@ -1836,9 +1836,9 @@ void DrawRemoteControlMenu() { break; } } else { - CVarSetInteger(REMOTE_CVAR("Enabled"), 1); + CVarSetInteger(CVAR_REMOTE("Enabled"), 1); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); - switch (CVarGetInteger(REMOTE_CVAR("Scheme"), GI_SCHEME_SAIL)) { + switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Enable(); break; @@ -1884,39 +1884,39 @@ void DrawRandomizerMenu() { static ImVec2 buttonSize(200.0f, 0.0f); #endif if (mRandomizerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger(WINDOW_CVAR("RandomizerSettings"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger(CVAR_WINDOW("RandomizerSettings"), 0)).c_str(), buttonSize)) { mRandomizerSettingsWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mItemTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger(WINDOW_CVAR("ItemTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger(CVAR_WINDOW("ItemTracker"), 0)).c_str(), buttonSize)) { mItemTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mItemTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVarGetInteger(WINDOW_CVAR("ItemTrackerSettings"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVarGetInteger(CVAR_WINDOW("ItemTrackerSettings"), 0)).c_str(), buttonSize)) { mItemTrackerSettingsWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mEntranceTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger(WINDOW_CVAR("EntranceTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger(CVAR_WINDOW("EntranceTracker"), 0)).c_str(), buttonSize)) { mEntranceTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mCheckTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger(WINDOW_CVAR("CheckTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger(CVAR_WINDOW("CheckTracker"), 0)).c_str(), buttonSize)) { mCheckTrackerWindow->ToggleVisibility(); } } UIWidgets::Spacer(0); if (mCheckTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVarGetInteger(WINDOW_CVAR("CheckTrackerSettings"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVarGetInteger(CVAR_WINDOW("CheckTrackerSettings"), 0)).c_str(), buttonSize)) { mCheckTrackerSettingsWindow->ToggleVisibility(); } } @@ -1927,11 +1927,11 @@ void DrawRandomizerMenu() { if (ImGui::BeginMenu("Rando Enhancements")) { - UIWidgets::EnhancementCheckbox("Rando-Relevant Navi Hints", RANDO_ENHANCEMENT_CVAR("RandoRelevantNavi"), false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::EnhancementCheckbox("Rando-Relevant Navi Hints", CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "Replace Navi's overworld quest hints with rando-related gameplay hints." ); - UIWidgets::PaddedEnhancementCheckbox("Random Rupee Names", RANDO_ENHANCEMENT_CVAR("RandomizeRupeeNames"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Random Rupee Names", CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "When obtaining rupees, randomize what the rupee is called in the textbox." ); @@ -1957,13 +1957,13 @@ void DrawRandomizerMenu() { "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; - UIWidgets::PaddedEnhancementCheckbox("Key Colors Match Dungeon", RANDO_ENHANCEMENT_CVAR("MatchKeyColors"), true, false, + UIWidgets::PaddedEnhancementCheckbox("Key Colors Match Dungeon", CVAR_RANDOMIZER_ENHANCEMENT("MatchKeyColors"), true, false, disableKeyColors, disableKeyColorsText, UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( "Matches the color of small keys and boss keys to the dungeon they belong to. " "This helps identify keys from afar and adds a little bit of flair.\n\nThis only " "applies to seeds with keys and boss keys shuffled to Any Dungeon, Overworld, or Anywhere."); - UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", CVAR_RANDOMIZER_ENHANCEMENT("QuestItemFanfares"), true, false); UIWidgets::Tooltip( "Play unique fanfares when obtaining quest items " "(medallions/stones/songs). Note that these fanfares are longer than usual." diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index b8e18c633..c7238cb39 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -4025,7 +4025,7 @@ void Audio_PlayFanfare_Rando(GetItemEntry getItem) { temp1 = NA_BGM_SMALL_ITEM_GET | 0x900; } // If the setting is toggled on and we get special quest items (longer fanfares): - if (CVarGetInteger(RANDO_ENHANCEMENT_CVAR("QuestItemFanfares"), 0) != 0) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("QuestItemFanfares"), 0) != 0) { // If we get a medallion, play the "get a medallion" fanfare if ((itemId >= ITEM_MEDALLION_FOREST) && (itemId <= ITEM_MEDALLION_LIGHT)) { temp1 = NA_BGM_MEDALLION_GET | 0x900; diff --git a/soh/src/code/game.c b/soh/src/code/game.c index d7c2e5256..5fca89dbd 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -93,7 +93,7 @@ void func_800C4344(GameState* gameState) { HREG(95) = CHECK_BTN_ALL(selectedInput->press.button, hReg82); } - if (CVarGetInteger("gRegEditEnabled", 0) || gIsCtrlr2Valid) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("RegEditEnabled"), 0) || gIsCtrlr2Valid) { func_8006390C(&gameState->input[1]); } @@ -162,7 +162,7 @@ void GameState_Draw(GameState* gameState, GraphicsContext* gfxCtx) { } sLastButtonPressed = gameState->input[0].press.button | gameState->input[0].cur.button; - if (R_DISABLE_INPUT_DISPLAY == 0 && CVarGetInteger("gDebugEnabled", 0)) { + if (R_DISABLE_INPUT_DISPLAY == 0 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { GameState_DrawInputDisplay(sLastButtonPressed, &newDList); } diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index d273e7643..d72a30277 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -424,7 +424,7 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) { sGraphUpdateTime = time; } - if (CVarGetInteger("gDebugEnabled", 0)) + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { if (CHECK_BTN_ALL(gameState->input[0].press.button, BTN_Z) && CHECK_BTN_ALL(gameState->input[0].cur.button, BTN_L | BTN_R)) { diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 2af8ef9ab..2a385f966 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -1902,7 +1902,7 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul s32 bgId2; f32 nx, ny, nz; // unit normal of polygon - if (CVarGetInteger(CHEAT_CVAR("NoClip"), 0) && actor != NULL && actor->id == ACTOR_PLAYER) { + if (CVarGetInteger(CVAR_CHEAT("NoClip"), 0) && actor != NULL && actor->id == ACTOR_PLAYER) { return false; } @@ -4025,7 +4025,7 @@ u32 func_80041D94(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { * SurfaceType Get Wall Flags */ s32 func_80041DB8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { - if (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0) { + if (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0) { return (1 << 3) | D_80119D90[func_80041D94(colCtx, poly, bgId)]; } else { return D_80119D90[func_80041D94(colCtx, poly, bgId)]; @@ -4122,7 +4122,7 @@ u32 SurfaceType_GetEcho(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) * SurfaceType Is Hookshot Surface */ u32 SurfaceType_IsHookshotSurface(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { - return CVarGetInteger(CHEAT_CVAR("HookshotEverything"), 0) || SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1; + return CVarGetInteger(CVAR_CHEAT("HookshotEverything"), 0) || SurfaceType_GetData(colCtx, poly, bgId, 1) >> 17 & 1; } /** diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 90634ea31..3f3c55f65 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -7619,7 +7619,7 @@ Vec3s Camera_Update(Camera* camera) { } // enable/disable debug cam - if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(D_8015BD7C->state.input[2].press.button, BTN_START)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && CHECK_BTN_ALL(D_8015BD7C->state.input[2].press.button, BTN_START)) { gDbgCamEnabled ^= 1; if (gDbgCamEnabled) { DbgCamera_Enable(&D_8015BD80, camera); @@ -7702,7 +7702,7 @@ Vec3s Camera_Update(Camera* camera) { } if (camera->timer != -1 && CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_DRIGHT) && - CVarGetInteger("gDebugEnabled", 0)) { + CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { camera->timer = 0; } diff --git a/soh/src/code/z_common_data.c b/soh/src/code/z_common_data.c index 491689880..31a25841d 100644 --- a/soh/src/code/z_common_data.c +++ b/soh/src/code/z_common_data.c @@ -8,7 +8,7 @@ void SaveContext_Init(void) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = NATURE_ID_DISABLED; gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; - gSaveContext.nextCutsceneIndex = CVarGetInteger(CHEAT_CVAR("BetaQuestWorld"), 0xFFEF); + gSaveContext.nextCutsceneIndex = CVarGetInteger(CVAR_CHEAT("BetaQuestWorld"), 0xFFEF); gSaveContext.cutsceneTrigger = 0; gSaveContext.chamberCutsceneNum = 0; gSaveContext.nextDayTime = 0xFFFF; diff --git a/soh/src/code/z_debug.c b/soh/src/code/z_debug.c index 267846eb4..1a814d745 100644 --- a/soh/src/code/z_debug.c +++ b/soh/src/code/z_debug.c @@ -133,7 +133,7 @@ void func_8006390C(Input* input) { InputCombo* input_combo; s32 i; - if (!CVarGetInteger("gDebugEnabled", 0)) + if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) return; regGroup = (gGameInfo->regGroup * REG_PAGES + gGameInfo->regPage) * REG_PER_PAGE - REG_PER_PAGE; @@ -216,7 +216,7 @@ void func_80063C04(GfxPrint* printer) { s32 pad; char name[3]; - if (!CVarGetInteger("gDebugEnabled", 0)) + if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) return; // set up register name string @@ -243,7 +243,7 @@ void func_80063D7C(GraphicsContext* gfxCtx) { GfxPrint printer; Gfx* tempRet; - if (!CVarGetInteger("gDebugEnabled", 0) || GameInteractor_NoUIActive()) { + if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) || GameInteractor_NoUIActive()) { return; } diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 9c0dd9b05..21ac5eae7 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -154,14 +154,14 @@ void func_80064558(PlayState* play, CutsceneContext* csCtx) { void func_800645A0(PlayState* play, CutsceneContext* csCtx) { Input* input = &play->state.input[0]; - if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(input->press.button, BTN_DLEFT) && + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && CHECK_BTN_ALL(input->press.button, BTN_DLEFT) && (csCtx->state == CS_STATE_IDLE) && (gSaveContext.sceneSetupIndex >= 4)) { D_8015FCC8 = 0; gSaveContext.cutsceneIndex = 0xFFFD; gSaveContext.cutsceneTrigger = 1; } - if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(input->press.button, BTN_DUP) && + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && CHECK_BTN_ALL(input->press.button, BTN_DUP) && (csCtx->state == CS_STATE_IDLE) && (gSaveContext.sceneSetupIndex >= 4) && !gDbgCamEnabled) { D_8015FCC8 = 1; gSaveContext.cutsceneIndex = 0xFFFD; @@ -499,7 +499,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB // cmd->base == 33: Zelda escaping with impa cutscene bool randoCsSkip = (IS_RANDO && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33)); bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) && - (gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0)); + (gSaveContext.fileNum != 0xFEDC) && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)); if ((gSaveContext.gameMode != 0) && (gSaveContext.gameMode != 3) && (play->sceneNum != SCENE_HYRULE_FIELD) && (csCtx->frames > 20) && @@ -1643,7 +1643,7 @@ void Cutscene_ProcessCommands(PlayState* play, CutsceneContext* csCtx, u8* cutsc return; } - if (CVarGetInteger("gDebugEnabled", 0) && CHECK_BTN_ALL(play->state.input[0].press.button, BTN_DRIGHT)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && CHECK_BTN_ALL(play->state.input[0].press.button, BTN_DRIGHT)) { csCtx->state = CS_STATE_UNSKIPPABLE_INIT; return; } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index e89bd86c0..136df2ef0 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -792,7 +792,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { if (this->unk_15A > 0) { this->unk_15A--; - if (CVarGetInteger(CHEAT_CVAR("DropsDontDie"), 0) && (this->unk_154 <= 0)) { + if (CVarGetInteger(CVAR_CHEAT("DropsDontDie"), 0) && (this->unk_154 <= 0)) { this->unk_15A++; } } diff --git a/soh/src/code/z_frame_advance.c b/soh/src/code/z_frame_advance.c index e48bd0c35..6fcd76ae7 100644 --- a/soh/src/code/z_frame_advance.c +++ b/soh/src/code/z_frame_advance.c @@ -18,10 +18,10 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input) { frameAdvCtx->enabled = !frameAdvCtx->enabled; } - if (!frameAdvCtx->enabled || CVarGetInteger("gFrameAdvance", 0) || (CHECK_BTN_ALL(input->cur.button, BTN_Z) && + if (!frameAdvCtx->enabled || CVarGetInteger(CVAR_GENERAL("FrameAdvance"), 0) || (CHECK_BTN_ALL(input->cur.button, BTN_Z) && (CHECK_BTN_ALL(input->press.button, BTN_R) || (CHECK_BTN_ALL(input->cur.button, BTN_R) && (++frameAdvCtx->timer >= 9))))) { - CVarClear("gFrameAdvance"); + CVarClear(CVAR_GENERAL("FrameAdvance")); frameAdvCtx->timer = 0; return true; } diff --git a/soh/src/code/z_kaleido_setup.c b/soh/src/code/z_kaleido_setup.c index 825adf237..e2feccf3c 100644 --- a/soh/src/code/z_kaleido_setup.c +++ b/soh/src/code/z_kaleido_setup.c @@ -18,7 +18,7 @@ void KaleidoSetup_Update(PlayState* play) { play->shootingGalleryStatus <= 1 && gSaveContext.magicState != MAGIC_STATE_STEP_CAPACITY && gSaveContext.magicState != MAGIC_STATE_FILL && (play->sceneNum != SCENE_BOMBCHU_BOWLING_ALLEY || !Flags_GetSwitch(play, 0x38))) { - u8 easyPauseBufferEnabled = CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0); + u8 easyPauseBufferEnabled = CVarGetInteger(CVAR_CHEAT("EasyPauseBuffer"), 0); u8 easyPauseBufferTimer = CVarGetInteger("gCheatEasyPauseBufferTimer", 0); // If start is not seen as pressed on the 2nd to last frame then we should end the easy frame advance flow diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 16d4434c9..60ac73cda 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -735,7 +735,7 @@ void Minimap_Draw(PlayState* play) { // If any of these CVars are enabled, disable toggling the minimap with L, unless gEnableMapToggle is set bool enableMapToggle = - !(CVarGetInteger("gDebugEnabled", 0) || CVarGetInteger(CHEAT_CVAR("MoonJumpOnL"), 0) || CVarGetInteger("gTurboOnL", 0)) || + !(CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) || CVarGetInteger(CVAR_CHEAT("MoonJumpOnL"), 0) || CVarGetInteger("gTurboOnL", 0)) || CVarGetInteger("gEnableMapToggle", 0); if (play->pauseCtx.state < 4) { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index fa1c61918..fa4c6c01b 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1655,11 +1655,11 @@ void Message_OpenText(PlayState* play, u16 textId) { //font->msgLength, __FILE__, __LINE__); } else if (CVarGetInteger("gAskToEquip", 0) && - (((LINK_IS_ADULT || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) && + (((LINK_IS_ADULT || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) && // 0C = Biggoron, 4B = Giant's, 4E = Mirror Shield, 50-51 = Tunics (textId == 0x0C || textId == 0x4B || textId == 0x4E || textId == 0x50 || textId == 0x51)) || - ((!LINK_IS_ADULT || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) && + ((!LINK_IS_ADULT || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) && // 4C = Deku Shield, A4 = Kokiri Sword (textId == 0x4C || textId == 0xA4)) || // 4D == Hylian Shield @@ -3007,7 +3007,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { * the last value being saved in a static variable. */ void Message_DrawDebugVariableChanged(s16* var, GraphicsContext* gfxCtx) { - if (!CVarGetInteger("gDebugEnabled", 0)) { return; } + if (!CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { return; } static s16 sVarLastValue = 0; static s16 sFillTimer = 0; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index e642cb30f..e9788f7f8 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1539,7 +1539,7 @@ void Inventory_SwapAgeEquipment(void) { // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { + if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { Flags_SetInfTable(INFTABLE_SWORDLESS); gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; } @@ -1554,7 +1554,7 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) { + if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; @@ -1629,7 +1629,7 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger(GENERAL_CVAR("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && + if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { Flags_SetInfTable(INFTABLE_SWORDLESS); if (gSaveContext.childEquips.equipment == 0) { @@ -5720,7 +5720,7 @@ void Interface_Draw(PlayState* play) { if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0)) { if (gSaveContext.minigameState != 1) { // Carrots rendering if the action corresponds to riding a horse - if (interfaceCtx->unk_1EE == 8 && !CVarGetInteger(CHEAT_CVAR("InfiniteEponaBoost"), 0)) { + if (interfaceCtx->unk_1EE == 8 && !CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0)) { // Load Carrot Icon gDPLoadTextureBlock(OVERLAY_DISP++, gCarrotIconTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -6534,11 +6534,11 @@ void Interface_Update(PlayState* play) { D_80125A58 = Player_GetEnvironmentalHazard(play); if (D_80125A58 == 1) { - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_GORON || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_GORON || CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) != 0) { D_80125A58 = 0; } } else if ((Player_GetEnvironmentalHazard(play) >= 2) && (Player_GetEnvironmentalHazard(play) < 5)) { - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_ZORA || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == EQUIP_VALUE_TUNIC_ZORA || CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) != 0) { D_80125A58 = 0; } } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 09bafb53b..9bc72380e 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -675,7 +675,7 @@ void Play_Init(GameState* thisx) { Fault_AddClient(&D_801614B8, ZeldaArena_Display, NULL, NULL); // In order to keep bunny hood equipped on first load, we need to pre-set the age reqs for the item and slot - if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0)) { + if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) { gItemAgeReqs[ITEM_MASK_BUNNY] = AGE_REQ_NONE; if(INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY) gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_NONE; @@ -1846,7 +1846,7 @@ void Play_Main(GameState* thisx) { LOG_NUM("1", 1); } - if (CVarGetInteger(CHEAT_CVAR("TimeSync"), 0)) { + if (CVarGetInteger(CVAR_CHEAT("TimeSync"), 0)) { const int maxRealDaySeconds = 86400; const int maxInGameDayTicks = 65536; diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index afec990c8..90b721f3c 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -597,7 +597,7 @@ s32 Player_ActionToModelGroup(Player* this, s32 actionParam) { void Player_SetModelsForHoldingShield(Player* this) { if ((this->stateFlags1 & PLAYER_STATE1_SHIELDING) && ((this->itemAction < 0) || (this->itemAction == this->heldItemAction))) { - if ((CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || + if ((CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD; if (LINK_IS_CHILD && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) { @@ -793,7 +793,7 @@ s32 Player_GetStrength(void) { return PLAYER_STR_NONE; } - if (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || LINK_IS_ADULT) { + if (CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) || LINK_IS_ADULT) { return strengthUpgrade; } else if (strengthUpgrade != 0) { return PLAYER_STR_BRACELET; @@ -953,9 +953,9 @@ s32 Player_GetEnvironmentalHazard(PlayState* play) { triggerEntry = &sTextTriggers[var]; if ((triggerEntry->flag != 0) && !(gSaveContext.textTriggerFlags & triggerEntry->flag) && - (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)) || + (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)) || (((var == 1) || (var == 3)) && (this->currentBoots == PLAYER_BOOTS_IRON) && - (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)))) { + (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)))) { Message_StartTextbox(play, triggerEntry->textId, NULL); gSaveContext.textTriggerFlags |= triggerEntry->flag; } @@ -1914,7 +1914,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve if (func_8002DD78(this) != 0) { Matrix_Translate(500.0f, 300.0f, 0.0f, MTXMODE_APPLY); Player_DrawHookshotReticle( - play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat(CHEAT_CVAR("HookshotReachMultiplier"), 1.0f)); + play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f)); } } } else if (CVarGetInteger("gBowReticle", 0) && ( diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index f0188c42d..3b6085040 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -412,7 +412,7 @@ BgImage* func_80096A74(PolygonType1* polygon1, PlayState* play) { camera = GET_ACTIVE_CAM(play); camId = camera->camDataIdx; - if (camId == -1 && (CVarGetInteger(CHEAT_CVAR("NoRestrictItems"), 0) || CVarGetInteger("gCrowdControl", 0))) { + if (camId == -1 && (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) || CVarGetInteger("gCrowdControl", 0))) { // This prevents a crash when using items that change the // camera (such as din's fire), voiding out or dying on // scenes with prerendered backgrounds. diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 90a7eacf7..5b67eba1d 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -221,7 +221,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { u16* ptr; u16 checksum; - if (fileChooseCtx->buttonIndex != 0 || !CVarGetInteger("gDebugEnabled", 0)) { + if (fileChooseCtx->buttonIndex != 0 || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) { Sram_InitNewSave(); } else { Sram_InitDebugSave(); @@ -232,7 +232,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.dayTime = 0x6AAB; gSaveContext.cutsceneIndex = 0xFFF1; - if ((fileChooseCtx->buttonIndex == 0 && CVarGetInteger("gDebugEnabled", 0)) || CVarGetInteger("gNaviSkipCutscene", 0)) { + if ((fileChooseCtx->buttonIndex == 0 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) || CVarGetInteger("gNaviSkipCutscene", 0)) { gSaveContext.cutsceneIndex = 0; } diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index ab6747c5e..bb521ede9 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -85,7 +85,7 @@ void ArmsHook_Wait(ArmsHook* this, PlayState* play) { if (this->actor.parent == NULL) { Player* player = GET_PLAYER(play); // get correct timer length for hookshot or longshot - s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat(CHEAT_CVAR("HookshotReachMultiplier"), 1.0f); + s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f); ArmsHook_SetupAction(this, ArmsHook_Shoot); func_8002D9A4(&this->actor, 20.0f); diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 686d83134..baa1db8f5 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -110,8 +110,8 @@ void EnBom_Init(Actor* thisx, PlayState* play) { Actor_SetScale(thisx, 0.01f); } - if (CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f) != 1.0f) { - this->timer = (s32)(70 * CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f)); + if (CVarGetFloat(CVAR_CHEAT("BombTimerMultiplier"), 1.0f) != 1.0f) { + this->timer = (s32)(70 * CVarGetFloat(CVAR_CHEAT("BombTimerMultiplier"), 1.0f)); // Do the sound and scale immediately if GameInteractor hasn't already. if (!GameInteractor_GetRandomBombFuseTimerActive()) { Audio_PlayActorSound2(thisx, NA_SE_PL_TAKE_OUT_SHIELD); @@ -267,7 +267,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { } // With random bomb fuse timer or gBombTimerMultiplier, sound effect and scaling is already done on init. - if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f) == 1.0f) { + if (this->timer == 67 && !GameInteractor_GetRandomBombFuseTimerActive() && CVarGetFloat(CVAR_CHEAT("BombTimerMultiplier"), 1.0f) == 1.0f) { Audio_PlayActorSound2(thisx, NA_SE_PL_TAKE_OUT_SHIELD); Actor_SetScale(thisx, 0.01f); } @@ -281,7 +281,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { Actor_UpdateBgCheckInfo(play, thisx, 5.0f, 10.0f, 15.0f, 0x1F); if (thisx->params == BOMB_BODY) { - float timerMultiplier = CVarGetFloat(CHEAT_CVAR("BombTimerMultiplier"), 1.0f); + float timerMultiplier = CVarGetFloat(CVAR_CHEAT("BombTimerMultiplier"), 1.0f); if (this->timer < (timerMultiplier == 1.0f ? 63 : (s32)(70 * timerMultiplier - 7))) { dustAccel.y = 0.2f; diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index 5350bfe58..b1b967220 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -283,7 +283,7 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->actor.yDistToWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL) && - !CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { + !CVarGetInteger(CVAR_CHEAT("NoKeeseGuayTarget"), 0)) { EnCrow_SetupDiveAttack(this); } } @@ -321,7 +321,7 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || (this->collider.base.atFlags & AT_HIT) || (this->actor.bgCheckFlags & 9) || (player->stateFlags1 & PLAYER_STATE1_ON_HORSE) || (this->actor.yDistToWater > -40.0f) || - CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { + CVarGetInteger(CVAR_CHEAT("NoKeeseGuayTarget"), 0)) { if (this->collider.base.atFlags & AT_HIT) { this->collider.base.atFlags &= ~AT_HIT; Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_ATTACK); diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index e51896f24..3f8fd104c 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -416,7 +416,7 @@ void EnFirefly_FlyIdle(EnFirefly* this, PlayState* play) { } if ((this->timer == 0) && (this->actor.xzDistToPlayer < 200.0f) && (Player_GetMask(play) != PLAYER_MASK_SKULL) && - !CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { + !CVarGetInteger(CVAR_CHEAT("NoKeeseGuayTarget"), 0)) { EnFirefly_SetupDiveAttack(this); } } @@ -495,7 +495,7 @@ void EnFirefly_DiveAttack(EnFirefly* this, PlayState* play) { Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); } if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_SKULL) || - CVarGetInteger(CHEAT_CVAR("NoKeeseGuayTarget"), 0)) { + CVarGetInteger(CVAR_CHEAT("NoKeeseGuayTarget"), 0)) { EnFirefly_SetupFlyAway(this); } } diff --git a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c index 0b9a383ca..4061c218f 100644 --- a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c +++ b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c @@ -679,7 +679,7 @@ void EnFish_UpdateCutscene(EnFish* this, PlayState* play) { // Update functions and Draw void EnFish_OrdinaryUpdate(EnFish* this, PlayState* play) { - if (this->timer > 0 && CVarGetInteger(CHEAT_CVAR("NoFishDespawn"), 0) == 0) { + if (this->timer > 0 && CVarGetInteger(CVAR_CHEAT("NoFishDespawn"), 0) == 0) { this->timer--; } diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index 379ff8a2e..de3770988 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -3312,7 +3312,7 @@ void EnHorse_CheckBoost(EnHorse* thisx, PlayState* play2) { this->stateFlags |= ENHORSE_BOOST; this->stateFlags |= ENHORSE_FIRST_BOOST_REGEN; this->stateFlags |= ENHORSE_FLAG_8; - if (!CVarGetInteger(CHEAT_CVAR("InfiniteEponaBoost"), 0)) { this->numBoosts--; } + if (!CVarGetInteger(CVAR_CHEAT("InfiniteEponaBoost"), 0)) { this->numBoosts--; } this->boostTimer = 0; if (this->numBoosts == 0) { this->boostRegenTime = 140; diff --git a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c index 0d3691707..4cfa96e3e 100644 --- a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c +++ b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c @@ -213,7 +213,7 @@ void EnInsect_Init(Actor* thisx, PlayState* play2) { // For bugs that aren't linked to a soil patch, we remove the "short lived" flag to prevent them from despawning // And exit early to not increment the "bugs dropped count" - if (CVarGetInteger(CHEAT_CVAR("NoBugsDespawn"), 0) && this->soilActor == NULL) { + if (CVarGetInteger(CVAR_CHEAT("NoBugsDespawn"), 0) && this->soilActor == NULL) { this->unk_314 &= ~4; return; } diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index bd9eb288b..793c73865 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -338,7 +338,7 @@ void func_80AE2C1C(EnRd* this, PlayState* play) { PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_CLIMBING_LADDER)) && !(player->stateFlags2 & PLAYER_STATE2_GRABBED_BY_ENEMY)) { if (this->unk_306 == 0) { - if (!(this->unk_312 & PLAYER_STATE2_GRABBED_BY_ENEMY) && !CVarGetInteger(CHEAT_CVAR("NoRedeadFreeze"), 0)) { + if (!(this->unk_312 & PLAYER_STATE2_GRABBED_BY_ENEMY) && !CVarGetInteger(CVAR_CHEAT("NoRedeadFreeze"), 0)) { player->actor.freezeTimer = 40; func_8008EEAC(play, &this->actor); GET_PLAYER(play)->unk_684 = &this->actor; @@ -570,7 +570,7 @@ void func_80AE3834(EnRd* this, PlayState* play) { s16 temp_v0 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->unk_30E - this->unk_310; if (ABS(temp_v0) < 0x2008) { - if (!(this->unk_312 & 0x80) && !CVarGetInteger(CHEAT_CVAR("NoRedeadFreeze"), 0)) { + if (!(this->unk_312 & 0x80) && !CVarGetInteger(CVAR_CHEAT("NoRedeadFreeze"), 0)) { player->actor.freezeTimer = 60; func_800AA000(this->actor.xzDistToPlayer, 0xFF, 0x14, 0x96); func_8008EEAC(play, &this->actor); diff --git a/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c b/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c index c05ca317a..5012dff2b 100644 --- a/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c +++ b/soh/src/overlays/actors/ovl_En_River_Sound/z_en_river_sound.c @@ -42,7 +42,7 @@ void EnRiverSound_Init(Actor* thisx, PlayState* play) { } else if (this->actor.params == RS_SARIAS_SONG) { // Always have leading music in rando if ( - CVarGetInteger(AUDIO_CVAR("LostWoodsConsistentVolume"), 0) || + CVarGetInteger(CVAR_AUDIO("LostWoodsConsistentVolume"), 0) || ((!CHECK_QUEST_ITEM(QUEST_SONG_LULLABY) || CHECK_QUEST_ITEM(QUEST_SONG_SARIA)) && !IS_RANDO) ) { Actor_Kill(&this->actor); diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 2a69a1ada..834d9fb96 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2073,7 +2073,7 @@ void Player_InitExplosiveIA(PlayState* play, Player* this) { this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 0); if (spawnedActor != NULL) { if ((explosiveType != 0) && (play->bombchuBowlingStatus != 0)) { - if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { + if (!CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0)) { play->bombchuBowlingStatus--; } if (play->bombchuBowlingStatus == 0) { @@ -2493,10 +2493,10 @@ LinkAnimationHeader* func_808346C4(PlayState* play, Player* this) { if (this->unk_870 < 0.5f) { return D_808543A4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; + !(CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } else { return D_808543AC[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; + !(CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } } @@ -2748,11 +2748,11 @@ s32 func_808350A4(PlayState* play, Player* this) { func_80834380(play, this, &item, &arrowType); if (gSaveContext.minigameState == 1) { - if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { + if (!CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0)) { play->interfaceCtx.hbaAmmo--; } } else if (play->shootingGalleryStatus != 0) { - if (!CVarGetInteger(CHEAT_CVAR("InfiniteAmmo"), 0)) { + if (!CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0)) { play->shootingGalleryStatus--; } } else { @@ -4225,7 +4225,7 @@ s32 func_8083816C(s32 arg0) { } void func_8083819C(Player* this, PlayState* play) { - if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger(CHEAT_CVAR("FireproofDekuShield"), 0) == 0)) { + if (this->currentShield == PLAYER_SHIELD_DEKU && (CVarGetInteger(CVAR_CHEAT("FireproofDekuShield"), 0) == 0)) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_SHIELD, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, true); Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); @@ -4338,18 +4338,18 @@ s32 func_808382DC(Player* this, PlayState* play) { if (this->unk_870 < 0.5f) { anim = D_808543BC[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && + !(CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } else { anim = D_808543B4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && + !(CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]; } LinkAnimation_PlayOnce(play, &this->upperSkelAnime, anim); } else { Player_AnimPlayOnce(play, this, D_808543C4[Player_HoldsTwoHandedWeapon(this) && - !(CVarGetInteger(CHEAT_CVAR("ShieldTwoHanded"), 0) && + !(CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK))]); } } @@ -4406,7 +4406,7 @@ s32 func_808382DC(Player* this, PlayState* play) { ((sp48 >= 0) && SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) && (this->floorTypeTimer >= D_808544F4[sp48])) || - ((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0) || + ((sp48 >= 0) && ((this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0) || (this->floorTypeTimer >= D_808544F4[sp48])))) { this->floorTypeTimer = 0; this->actor.colChkInfo.damage = 4; @@ -5225,7 +5225,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) { if (BgCheck_EntityLineTest1(&play->colCtx, &this->actor.world.pos, &sp74, &sp68, &sp84, true, false, false, true, &sp80) && - ((ABS(sp84->normal.y) < 600) || (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0))) { + ((ABS(sp84->normal.y) < 600) || (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0))) { f32 nx = COLPOLY_GET_NORMAL(sp84->normal.x); f32 ny = COLPOLY_GET_NORMAL(sp84->normal.y); f32 nz = COLPOLY_GET_NORMAL(sp84->normal.z); @@ -8504,7 +8504,7 @@ void func_80842A28(PlayState* play, Player* this) { } void func_80842A88(PlayState* play, Player* this) { - if (CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Inventory_ChangeAmmo(ITEM_STICK, -1); Player_UseItem(play, this, ITEM_NONE); } @@ -8512,7 +8512,7 @@ void func_80842A88(PlayState* play, Player* this) { s32 func_80842AC4(PlayState* play, Player* this) { if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) { - if (AMMO(ITEM_STICK) != 0 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (AMMO(ITEM_STICK) != 0 && CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; @@ -8949,7 +8949,7 @@ static AnimSfxEntry D_808545F0[] = { }; void Player_Action_80843CEC(Player* this, PlayState* play) { - if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) == 0) { + if (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0) { if ((play->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3) || (sFloorType == 9) || ((func_80838144(sFloorType) >= 0) && !SurfaceType_IsWallDamage(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId))) { @@ -10654,7 +10654,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId); // conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant anyway - if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0)) { + if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0)) { /* This fixes the "started climbing a wall and then immediately fell off" bug. * The main idea is if a climbing wall is detected, double-check that it will * still be valid once climbing begins by doing a second raycast with a small @@ -10723,7 +10723,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { if ((this->actor.bgCheckFlags & 0x200) && (sShapeYawToTouchedWall < 0x3000)) { CollisionPoly* wallPoly = this->actor.wallPoly; - if ((ABS(wallPoly->normal.y) < 600) || (CVarGetInteger(CHEAT_CVAR("ClimbEverything"), 0) != 0)) { + if ((ABS(wallPoly->normal.y) < 600) || (CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0) != 0)) { f32 sp8C = COLPOLY_GET_NORMAL(wallPoly->normal.x); f32 sp88 = COLPOLY_GET_NORMAL(wallPoly->normal.y); f32 sp84 = COLPOLY_GET_NORMAL(wallPoly->normal.z); @@ -10914,7 +10914,7 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { seqMode = SEQ_MODE_STILL; } - if (play->actorCtx.targetCtx.bgmEnemy != NULL && !CVarGetInteger(AUDIO_CVAR("EnemyBGMDisable"), 0)) { + if (play->actorCtx.targetCtx.bgmEnemy != NULL && !CVarGetInteger(CVAR_AUDIO("EnemyBGMDisable"), 0)) { seqMode = SEQ_MODE_ENEMY; Audio_SetBgmEnemyVolume(sqrtf(play->actorCtx.targetCtx.bgmEnemy->xyzDistToPlayerSq)); } @@ -10934,7 +10934,7 @@ static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 }; void func_80848A04(PlayState* play, Player* this) { f32 temp; - if (CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { + if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { f32 temp2 = 1.0f; // Secondary temporary variable to use with the alleged draw flame function this->unk_860 = 200; // Keeps the stick's flame lit this->unk_85C = 1.0f; // Ensures the stick is the proper length @@ -10942,20 +10942,20 @@ void func_80848A04(PlayState* play, Player* this) { 0, 8); // I believe this draws the flame effect } - if (this->unk_85C == 0.0f && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (this->unk_85C == 0.0f && CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Player_UseItem(play, this, 0xFF); return; } temp = 1.0f; - if (DECR(this->unk_860) == 0 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + if (DECR(this->unk_860) == 0 && CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { Inventory_ChangeAmmo(ITEM_STICK, -1); this->unk_860 = 1; temp = 0.0f; this->unk_85C = temp; } else if (this->unk_860 > 200) { temp = (210 - this->unk_860) / 10.0f; - } else if (this->unk_860 < 20 && CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + } else if (this->unk_860 < 20 && CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { temp = this->unk_860 / 20.0f; this->unk_85C = temp; } @@ -11001,7 +11001,7 @@ void Player_UpdateBodyBurn(PlayState* play, Player* this) { s32 sp58; s32 sp54; - if (this->currentTunic == PLAYER_TUNIC_GORON || CVarGetInteger(CHEAT_CVAR("SuperTunic"), 0) != 0) { + if (this->currentTunic == PLAYER_TUNIC_GORON || CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) != 0) { sp54 = 20; } else { sp54 = (s32)(this->linearVelocity * 0.4f) + 1; @@ -11256,7 +11256,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { func_808473D4(play, this); func_80836BEC(this, play); - if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger(CHEAT_CVAR("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { + if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { func_80848A04(play, this); } else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) { this->unk_860++; @@ -14374,7 +14374,7 @@ void Player_Action_8084FBF4(Player* this, PlayState* play) { s32 func_8084FCAC(Player* this, PlayState* play) { sControlInput = &play->state.input[0]; - if (CVarGetInteger("gDebugEnabled", 0) && + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && ((CHECK_BTN_ALL(sControlInput->cur.button, BTN_A | BTN_L | BTN_R) && CHECK_BTN_ALL(sControlInput->press.button, BTN_B)) || (CHECK_BTN_ALL(sControlInput->cur.button, BTN_L) && CHECK_BTN_ALL(sControlInput->press.button, BTN_DRIGHT)))) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 155462c33..327c1dd11 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1025,7 +1025,7 @@ void FileChoose_UpdateRandomizer() { return; } - if (!SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && !CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { + if (!SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && !CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { CVarSetString("gSpoilerLog", ""); fileSelectSpoilerFileLoaded = false; } @@ -1053,7 +1053,7 @@ void FileChoose_UpdateRandomizer() { Randomizer_LoadEntranceOverrides(fileLoc, silent); fileSelectSpoilerFileLoaded = true; - if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && CVarGetInteger(RANDOMIZER_SEED_CVAR("DontGenerateSpoiler"), 0)) { + if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { remove(fileLoc); } } @@ -2945,7 +2945,7 @@ void FileChoose_LoadGame(GameState* thisx) { gSaveContext.fileNum = this->buttonIndex; gSaveContext.gameMode = 0; - if ((this->buttonIndex == FS_BTN_SELECT_FILE_1 && CVarGetInteger("gDebugEnabled", 0)) || this->buttonIndex == 0xFF) { + if ((this->buttonIndex == FS_BTN_SELECT_FILE_1 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) || this->buttonIndex == 0xFF) { if (this->buttonIndex == 0xFF) { Sram_InitDebugSave(); } else { @@ -3286,15 +3286,15 @@ void FileChoose_Main(GameState* thisx) { gSaveContext.skyboxTime += 0x10; } - if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0) && CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1) <= FASTFILE_3 && !isFastFileIdIncompatible) { - if (Save_Exist(CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1)) && FileChoose_IsSaveCompatible(Save_GetSaveMetaInfo(CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1)))) { - this->buttonIndex = CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), 0) && CVarGetInteger(CVAR_DEVELOPER_TOOLS("SaveFileID"), FASTFILE_1) <= FASTFILE_3 && !isFastFileIdIncompatible) { + if (Save_Exist(CVarGetInteger(CVAR_DEVELOPER_TOOLS("SaveFileID"), FASTFILE_1)) && FileChoose_IsSaveCompatible(Save_GetSaveMetaInfo(CVarGetInteger(CVAR_DEVELOPER_TOOLS("SaveFileID"), FASTFILE_1)))) { + this->buttonIndex = CVarGetInteger(CVAR_DEVELOPER_TOOLS("SaveFileID"), FASTFILE_1); this->menuMode = FS_MENU_MODE_SELECT; this->selectMode = SM_LOAD_GAME; } else { isFastFileIdIncompatible = 1; } - } else if (CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0) && CVarGetInteger(DEV_TOOLS_CVAR("SaveFileID"), FASTFILE_1) == FASTFILE_MAP_SELECT) { + } else if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), 0) && CVarGetInteger(CVAR_DEVELOPER_TOOLS("SaveFileID"), FASTFILE_1) == FASTFILE_MAP_SELECT) { this->buttonIndex = 0xFF; this->menuMode = FS_MENU_MODE_SELECT; this->selectMode = SM_LOAD_GAME; diff --git a/soh/src/overlays/gamestates/ovl_select/z_select.c b/soh/src/overlays/gamestates/ovl_select/z_select.c index dbc7e1796..65c23b685 100644 --- a/soh/src/overlays/gamestates/ovl_select/z_select.c +++ b/soh/src/overlays/gamestates/ovl_select/z_select.c @@ -1078,7 +1078,7 @@ void Select_PrintMenu(SelectContext* this, GfxPrint* printer) { GfxPrint_SetColor(printer, 200, 200, 55, 255); } - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1105,7 +1105,7 @@ void Select_PrintMenu(SelectContext* this, GfxPrint* printer) { GfxPrint_SetColor(printer, 155, 55, 150, 255); // Small position hack of the OPT=X text since german Link's Age overlap if translated - if (CVarGetInteger("gDebugWarpScreenTranslation", 1) && gSaveContext.language == LANGUAGE_GER) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1) && gSaveContext.language == LANGUAGE_GER) { GfxPrint_SetPos(printer, 26, 26); } else { GfxPrint_SetPos(printer, 20, 26); @@ -1134,7 +1134,7 @@ void Better_Select_PrintMenu(SelectContext* this, GfxPrint* printer) { GfxPrint_SetColor(printer, 175, 175, 175, 255); } - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1160,7 +1160,7 @@ void Better_Select_PrintMenu(SelectContext* this, GfxPrint* printer) { GfxPrint_SetColor(printer, 205, 100, 200, 255); GfxPrint_SetPos(printer, 3, 26); - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1200,7 +1200,7 @@ void Select_PrintLoadingMessage(SelectContext* this, GfxPrint* printer) { GfxPrint_SetPos(printer, 10, 15); GfxPrint_SetColor(printer, 255, 255, 255, 255); randomMsg = Rand_ZeroOne() * ARRAY_COUNT(sLoadingMessages); - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1231,7 +1231,7 @@ static BetterSceneSelectAgeLabels sBetterAgeLabels[] = { void Select_PrintAgeSetting(SelectContext* this, GfxPrint* printer, s32 age) { GfxPrint_SetPos(printer, 4, 26); GfxPrint_SetColor(printer, 255, 255, 55, 255); - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1252,7 +1252,7 @@ void Select_PrintAgeSetting(SelectContext* this, GfxPrint* printer, s32 age) { void Better_Select_PrintAgeSetting(SelectContext* this, GfxPrint* printer, s32 age) { GfxPrint_SetPos(printer, 25, 25); GfxPrint_SetColor(printer, 100, 100, 100, 255); - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: case LANGUAGE_FRA: @@ -1268,7 +1268,7 @@ void Better_Select_PrintAgeSetting(SelectContext* this, GfxPrint* printer, s32 a } GfxPrint_SetColor(printer, 55, 200, 50, 255); - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1304,7 +1304,7 @@ void Select_PrintCutsceneSetting(SelectContext* this, GfxPrint* printer, u16 csI }; char* label; - int lang = CVarGetInteger("gDebugWarpScreenTranslation", 1) ? gSaveContext.language + 1 : 0; + int lang = CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1) ? gSaveContext.language + 1 : 0; GfxPrint_SetPos(printer, 4, 25); GfxPrint_SetColor(printer, 255, 255, 55, 255); @@ -1367,7 +1367,7 @@ void Better_Select_PrintTimeSetting(SelectContext* this, GfxPrint* printer) { GfxPrint_SetColor(printer, 100, 100, 100, 255); if (gSaveContext.dayTime > 0xC000 || gSaveContext.dayTime < 0x4555) { - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1384,7 +1384,7 @@ void Better_Select_PrintTimeSetting(SelectContext* this, GfxPrint* printer) { label = "Night"; } } else { - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1401,7 +1401,7 @@ void Better_Select_PrintTimeSetting(SelectContext* this, GfxPrint* printer) { label = "Day"; } } - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1436,7 +1436,7 @@ void Better_Select_PrintMQSetting(SelectContext* this, GfxPrint* printer) { GfxPrint_Printf(printer, "MQ:"); } - if (CVarGetInteger("gDebugWarpScreenTranslation", 1)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), 1)) { switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -1533,7 +1533,7 @@ void Select_Draw(SelectContext* this) { void Select_Main(GameState* thisx) { SelectContext* this = (SelectContext*)thisx; - if (this->isBetterWarp != CVarGetInteger("gBetterDebugWarpScreen", 0)) { + if (this->isBetterWarp != CVarGetInteger(CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), 0)) { Select_SwitchBetterWarpMode(this, !this->isBetterWarp); } @@ -1639,5 +1639,5 @@ void Select_Init(GameState* thisx) { CVarClear("gBetterDebugWarpScreenMQMode"); CVarClear("gBetterDebugWarpScreenMQModeScene"); - Select_SwitchBetterWarpMode(this, CVarGetInteger("gBetterDebugWarpScreen", 0)); + Select_SwitchBetterWarpMode(this, CVarGetInteger(CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), 0)); } diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index b4f9a6744..59afae8a5 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -245,13 +245,13 @@ void Title_Main(GameState* thisx) { POLY_OPA_DISP = gfx; } - if (this->exit || CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) { + if (this->exit || CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), 0)) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = 0xFF; gSaveContext.gameMode = 1; this->state.running = false; - if (gLoadFileSelect || CVarGetInteger(DEV_TOOLS_CVAR("SkipLogoTitle"), 0)) + if (gLoadFileSelect || CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkipLogoTitle"), 0)) SET_NEXT_GAMESTATE(&this->state, FileChoose_Init, FileChooseContext); else SET_NEXT_GAMESTATE(&this->state, Opening_Init, OpeningContext); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 17de25ee4..d9d03d7cc 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -756,7 +756,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { for (rowStart = 0, j = 0, temp = 0, i = 0; i < 4; i++, rowStart += 4, j += 16) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->equipVtx[j], 16, 0); - bool drawGreyItems = !CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0); + bool drawGreyItems = !CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0); if (LINK_AGE_IN_YEARS == YEARS_CHILD) { point = CUR_UPG_VALUE(sChildUpgrades[i]); if ((point != 0) && (CUR_UPG_VALUE(sChildUpgrades[i]) != 0)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 68185ef30..1060131ab 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -340,7 +340,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { gSlotAgeReqs[SLOT_TRADE_CHILD] = ( ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || - CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) + CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) ) && INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY ? AGE_REQ_NONE @@ -349,7 +349,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { //also update the age requirement for the bunny hood itself gItemAgeReqs[ITEM_MASK_BUNNY] = ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || - CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) + CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) ? AGE_REQ_NONE : AGE_REQ_CHILD; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h index 583cbe942..6c5fe7ba8 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h @@ -20,9 +20,9 @@ extern u8 gAreaGsFlags[]; #define AGE_REQ_CHILD LINK_AGE_CHILD #define AGE_REQ_NONE 9 -#define CHECK_AGE_REQ_EQUIP(i, j) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gEquipAgeReqs[i][j] == AGE_REQ_NONE) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge))) -#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) -#define CHECK_AGE_REQ_ITEM(itemIndex) (CVarGetInteger(CHEAT_CVAR("TimelessEquipment"), 0) || (gItemAgeReqs[itemIndex] == AGE_REQ_NONE) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge)) +#define CHECK_AGE_REQ_EQUIP(i, j) (CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) || (gEquipAgeReqs[i][j] == AGE_REQ_NONE) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge))) +#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) +#define CHECK_AGE_REQ_ITEM(itemIndex) (CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) || (gItemAgeReqs[itemIndex] == AGE_REQ_NONE) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge)) void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx); s32 KaleidoScope_UpdateQuestStatusPoint(PauseContext* pauseCtx, s32 point); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 45f644372..12fa4d19e 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1084,7 +1084,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { PageLeft_BTN = BTN_L; } - if (CVarGetInteger("gDebugEnabled", 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) { pauseCtx->debugState = 1; return; } @@ -1963,7 +1963,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { POLY_KAL_DISP = KaleidoScope_QuadTextureIA4(POLY_KAL_DISP, pauseCtx->nameSegment, 128, 16, 0); } - if (pauseCtx->pageIndex == PAUSE_MAP && CVarGetInteger(DEV_TOOLS_CVAR("SkulltulaDebugEnabled"), 0) != 0) { + if (pauseCtx->pageIndex == PAUSE_MAP && CVarGetInteger(CVAR_DEVELOPER_TOOLS("SkulltulaDebugEnabled"), 0) != 0) { if (YREG(7) != 0) { osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf("キンスタ数(%d) Get_KIN_STA=%x (%x) (%x)\n", YREG(6), GET_GS_FLAGS(YREG(6)), @@ -3994,7 +3994,7 @@ void KaleidoScope_Update(PlayState* play) // Boss Rush skips past the "Save?" window when pressing B while paused. if (CHECK_BTN_ALL(input->press.button, BTN_START) || (CHECK_BTN_ALL(input->press.button, BTN_B) && IS_BOSS_RUSH)) { - if (CVarGetInteger(CHEAT_CVAR("EasyPauseBuffer"), 0) || CVarGetInteger(CHEAT_CVAR("EasyInputBuffer"), 0)) { + if (CVarGetInteger(CVAR_CHEAT("EasyPauseBuffer"), 0) || CVarGetInteger(CVAR_CHEAT("EasyInputBuffer"), 0)) { // Easy pause buffer is 13 frames, 12 for kaledio to end, and one more to advance a single frame CVarSetInteger("gCheatEasyPauseBufferTimer", 13); } From a554c1550dd63f66caddaed44e5b1edc4b4d8685 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 21 Apr 2024 18:53:15 -0500 Subject: [PATCH 177/300] Fix shadow & spirit rewards, remove remaning usage of duplicate dungeon done flags --- soh/soh/Enhancements/boss-rush/BossRush.cpp | 36 +++++++++---------- .../Enhancements/debugger/debugSaveEditor.h | 6 ---- soh/soh/Enhancements/presets.h | 2 ++ .../Enhancements/randomizer/hook_handlers.cpp | 11 +++++- .../Enhancements/randomizer/location_list.cpp | 12 +++---- .../Enhancements/randomizer/randomizer_inf.h | 6 ---- soh/src/code/z_map_exp.c | 2 +- soh/src/code/z_play.c | 12 +++---- .../z_bg_spot06_objects.c | 8 ++--- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 2 +- 10 files changed, 48 insertions(+), 49 deletions(-) diff --git a/soh/soh/Enhancements/boss-rush/BossRush.cpp b/soh/soh/Enhancements/boss-rush/BossRush.cpp index 63414f88c..9dbbad527 100644 --- a/soh/soh/Enhancements/boss-rush/BossRush.cpp +++ b/soh/soh/Enhancements/boss-rush/BossRush.cpp @@ -129,15 +129,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) { // Spawn blue warps in Chamber of Sages based on what bosses have been defeated. if (gSaveContext.linkAge == LINK_AGE_CHILD) { // Forest Medallion (Gohma) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); } // Fire Medallion (King Dodongo) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); } // Water Medallion (Barinade) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); } } else { @@ -146,15 +146,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1, false); } // Forest Medallion (Phantom Ganondorf) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); } // Fire Medallion (Volvagia) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); } // Water Medallion (Morpha) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); } // Spirit Medallion (Twinrova) @@ -242,22 +242,22 @@ void BossRush_HandleCompleteBoss(PlayState* play) { gSaveContext.isBossRushPaused = 1; switch (play->sceneNum) { case SCENE_DEKU_TREE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); + Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); break; case SCENE_DODONGOS_CAVERN_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); + Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); break; case SCENE_JABU_JABU_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); break; case SCENE_FOREST_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); break; case SCENE_FIRE_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); break; case SCENE_WATER_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); break; case SCENE_SPIRIT_TEMPLE_BOSS: Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); @@ -432,13 +432,13 @@ void BossRush_InitSave() { // Set flags and Link's age based on chosen settings. if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT || gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); } diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 047df95f8..53cd4b7ae 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -349,12 +349,6 @@ const std::vector flagTables = { { 0x30, "Entered the Market" }, } }, { "Randomizer Inf Flags", RANDOMIZER_INF, 16, { - { RAND_INF_DUNGEONS_DONE_DEKU_TREE, "DUNGEONS_DONE_DEKU_TREE" }, - { RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, "DUNGEONS_DONE_DODONGOS_CAVERN" }, - { RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, "DUNGEONS_DONE_JABU_JABUS_BELLY" }, - { RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE, "DUNGEONS_DONE_FOREST_TEMPLE" }, - { RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE, "DUNGEONS_DONE_FIRE_TEMPLE" }, - { RAND_INF_DUNGEONS_DONE_WATER_TEMPLE, "DUNGEONS_DONE_WATER_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" }, diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 3cce3dd74..83cf25bd9 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -292,6 +292,8 @@ const std::vector enhancementsCvars = { "gTimeSavers.SkipMiscInteractions", "gTimeSavers.DisableTitleCard", "gTimeSavers.SkipGetItemAnimation", + "gTimeSavers.SkipChildStealth", + "gTimeSavers.SkipTowerEscape", }; const std::vector cheatCvars = { diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index a2fe8697e..42dabae88 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -642,7 +642,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { GET_PLAYER(gPlayState)->exchangeItemId = EXCH_ITEM_LETTER_RUTO; } - *should = Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); break; } case GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: { @@ -1053,6 +1053,15 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = MeetsRainbowBridgeRequirements(); break; } + case GI_VB_PLAY_BLUE_WARP_CS: { + // We need to override just these two temples because they check medallions instead of flags + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { + *should = !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); + } else if (gPlayState->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { + *should = !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); + } + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 1dfa2f5e4..fbe80d638 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1282,12 +1282,12 @@ void Rando::StaticData::InitLocationTable() { // // Bosses locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_NONE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LINKS_POCKET), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(0x07), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(0x25), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(0x37), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x48), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x49), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0x4A), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8bd2cc7c1..f1ae83121 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1,12 +1,6 @@ #pragma once typedef enum { - RAND_INF_DUNGEONS_DONE_DEKU_TREE, - RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, - RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, - RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE, - RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE, - RAND_INF_DUNGEONS_DONE_WATER_TEMPLE, RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 213ee018d..5ed13f810 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -395,7 +395,7 @@ void Map_InitData(PlayState* play, s16 room) { } else if (play->sceneNum == SCENE_LAKE_HYLIA) { if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) { + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) { extendedMapIndex = 0x15; } } else if (play->sceneNum == SCENE_GERUDO_VALLEY) { diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 43d30f54b..4e27e6cb8 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -277,27 +277,27 @@ u8 CheckMedallionCount() { u8 CheckDungeonCount() { u8 dungeonCount = 0; - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { dungeonCount++; } diff --git a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c index 816f96aa4..0a4738092 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c @@ -217,7 +217,7 @@ void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play) { // Due to Ships resource caching, the water box collisions for the river have to be manually reset play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; - if (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // For randomizer when leaving lake hylia while the water level is lowered, // reset the "raise lake hylia water" flag back to on if the water temple is cleared Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); @@ -461,7 +461,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { Object_Spawn(&play->objectCtx, OBJECT_GAMEPLAY_DANGEON_KEEP); s16 switchParams; - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // Toggle-able floor switch, // linked to temp_switch 0x1E (room temporary, cleared when room unloads) switchParams = 0x3E10; @@ -477,7 +477,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { 0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF), false); // Spawn a Navi check spot when Water Temple isn't cleared - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF), false); } @@ -485,7 +485,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { actionCounter++; return; } else if (actionCounter == 1) { - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // Remove the link to ice block so melting it doesn't set the flag lakeControlFloorSwitch->params = 0x3E01; } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index a2c1f5f9a..afa825e57 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -535,7 +535,7 @@ void EnOssan_TalkGoronShopkeeper(PlayState* play) { Message_ContinueTextbox(play, 0x300F); } } else if ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) { + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP))) { Message_ContinueTextbox(play, 0x3057); } else { Message_ContinueTextbox(play, 0x305B); From 49f891f2e53b3a66a49df8deb8c2889edc366db0 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:16:59 -0400 Subject: [PATCH 178/300] move `RawJson` to LUS (#4063) --- libultraship | 2 +- soh/soh/Enhancements/tts/tts.cpp | 12 ++++++------ soh/soh/OTRGlobals.cpp | 2 -- soh/soh/resource/importer/RawJsonFactory.cpp | 19 ------------------- soh/soh/resource/importer/RawJsonFactory.h | 11 ----------- soh/soh/resource/type/RawJson.cpp | 14 -------------- soh/soh/resource/type/RawJson.h | 20 -------------------- soh/soh/resource/type/SohResourceType.h | 1 - 8 files changed, 7 insertions(+), 74 deletions(-) delete mode 100644 soh/soh/resource/importer/RawJsonFactory.cpp delete mode 100644 soh/soh/resource/importer/RawJsonFactory.h delete mode 100644 soh/soh/resource/type/RawJson.cpp delete mode 100644 soh/soh/resource/type/RawJson.h diff --git a/libultraship b/libultraship index 26ecbc197..8a079ed15 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 26ecbc19784347773f750aa838190e45172b63e6 +Subproject commit 8a079ed15852fbd26e701fd317afc14530578a92 diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index f4b498815..3a375230f 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,7 +13,6 @@ #include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/resource/type/SohResourceType.h" -#include "soh/resource/type/RawJson.h" extern "C" { extern MapData* gMapData; @@ -1041,19 +1041,19 @@ void InitTTSBank() { auto initData = std::make_shared(); initData->Format = RESOURCE_FORMAT_BINARY; - initData->Type = static_cast(SOH::ResourceType::SOH_RawJson); + initData->Type = static_cast(LUS::ResourceType::Json); initData->ResourceVersion = 0; - sceneMap = std::static_pointer_cast( + sceneMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; - miscMap = std::static_pointer_cast( + miscMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; - kaleidoMap = std::static_pointer_cast( + kaleidoMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; - fileChooseMap = std::static_pointer_cast( + fileChooseMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index e8c88fc61..48489d542 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -118,7 +118,6 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/BackgroundFactory.h" -#include "soh/resource/importer/RawJsonFactory.h" #include "soh/config/ConfigUpdaters.h" @@ -343,7 +342,6 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast(SOH::ResourceType::SOH_AudioSoundFont), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); - loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast(SOH::ResourceType::SOH_RawJson), 0); gSaveStateMgr = std::make_shared(); gRandomizer = std::make_shared(); diff --git a/soh/soh/resource/importer/RawJsonFactory.cpp b/soh/soh/resource/importer/RawJsonFactory.cpp deleted file mode 100644 index 4978f6f96..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "soh/resource/importer/RawJsonFactory.h" -#include "soh/resource/type/RawJson.h" -#include "spdlog/spdlog.h" - -namespace SOH { -std::shared_ptr ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr file) { - if (!FileHasValidFormatAndReader(file)) { - return nullptr; - } - - auto rawJson = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); - - rawJson->DataSize = file->Buffer->size(); - rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true); - - return rawJson; -} -} // namespace SOH diff --git a/soh/soh/resource/importer/RawJsonFactory.h b/soh/soh/resource/importer/RawJsonFactory.h deleted file mode 100644 index d5fa656b6..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include "resource/ResourceFactoryBinary.h" - -namespace SOH { -class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary { - public: - std::shared_ptr ReadResource(std::shared_ptr file) override; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/RawJson.cpp b/soh/soh/resource/type/RawJson.cpp deleted file mode 100644 index 3022a67ef..000000000 --- a/soh/soh/resource/type/RawJson.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "RawJson.h" - -namespace SOH { -RawJson::RawJson() : Resource(std::shared_ptr()) { -} - -void* RawJson::GetPointer() { - return &Data; -} - -size_t RawJson::GetPointerSize() { - return DataSize * sizeof(char); -} -} // namespace SOH diff --git a/soh/soh/resource/type/RawJson.h b/soh/soh/resource/type/RawJson.h deleted file mode 100644 index 47e0323cc..000000000 --- a/soh/soh/resource/type/RawJson.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include - -namespace SOH { - -class RawJson : public LUS::Resource { - public: - using Resource::Resource; - - RawJson(); - - void* GetPointer() override; - size_t GetPointerSize() override; - - nlohmann::json Data; - size_t DataSize; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index 3ef4163fe..fdf39031e 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -17,6 +17,5 @@ enum class ResourceType { SOH_AudioSequence = 0x4F534551, // OSEQ SOH_Background = 0x4F424749, // OBGI SOH_SceneCommand = 0x4F52434D, // ORCM - SOH_RawJson = 0x4A534F4E, // JSON }; } // namespace SOH From 3c6c46d95dea547bbff236e4c2347ab8a26368f5 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 21 Apr 2024 21:09:52 -0500 Subject: [PATCH 179/300] Fix for some chests not appearing --- soh/soh/Enhancements/timesaver_hook_handlers.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 700e55e18..27947f3ea 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -26,6 +26,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; +extern int32_t D_8011D3AC; } #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() @@ -315,6 +316,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case GI_VB_PLAY_ONEPOINT_ACTOR_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { Actor* actor = static_cast(opt); + + // there are a few checks throughout the game (such as chest spawns) that rely on this + // the checks are for func_8005B198() == this->dyna.actor.category + // func_8005B198 just returns D_8011D3AC + // D_8011D3AC is set to camera->target->category in Camera_Demo5 + D_8011D3AC = actor->category; + switch (actor->category) { case ACTORCAT_BG: if (actor->id == ACTOR_BG_DDAN_KD) { From 4c75fd14a77018a2dfce2679e8e8a15af6f233b1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Mon, 22 Apr 2024 13:29:05 -0400 Subject: [PATCH 180/300] Fix hint generation bugs on develop-rando (#4001) * Fix hint generation bugs on develop-rando 1. Fixed Ganon Non-hint text from loading as Saria's Magic Hint. 2. Fixed Ganon Non-hint text from not getting saved correctly. 3. Fixed gossip stone hint generation from not generating any non-always hints on No Logic. For #3, the hint distribution and placement algorithm was bailing out too early when it wasn't able to place a hint. For No Logic, what it was doing was failing to place WOTH hints (since No Logic seeds don't calculate WOTH candidacy), returning the amount of hints it failed to place, and then it called the function to redistribute the hints, but did not call the function to attempt to place the remaining hints. Additionally, it was not accounting for the fact that we shouldn't redistribute the hints into the categories we failed to place a hint in, so it would redistribute hints right back into those categories. I changed it so that when DistributeHints gets called after PlaceHints fails to place the hint, it checks if the distribution settings copies attribute was set to 0. In this case, it breaks while looping for the type distribution settings, and moves on to the next category. Also, it now repeatedly attempts to distribute and place hints until PlaceHints returns 0 (meaning it placed all of its hints successfully). * Fixes some further seed-bleed type issues with hint generation. --- soh/soh/Enhancements/randomizer/3drando/hints.cpp | 8 +++++--- soh/soh/Enhancements/randomizer/3drando/text.hpp | 10 ++++++++-- soh/soh/Enhancements/randomizer/hint.cpp | 4 ++++ soh/soh/Enhancements/randomizer/randomizer.cpp | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index ce29c95d0..ba4fce24b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -287,7 +287,7 @@ Text AutoFormatHintText(const Text& unformattedHintText, const std::vector dungeonInfoData; @@ -615,6 +615,7 @@ void CreateGanonAndSheikText() { } ctx->AddHint(RH_GANONDORF_HINT, AutoFormatHintText(ganonHintText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea); + ctx->AddHint(RH_GANONDORF_NOHINT, AutoFormatHintText(ganonText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea); if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { sheikText = ::Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + LightArrowAreaText + "%w."; @@ -963,7 +964,7 @@ static void DistributeHints(std::vector& selected, size_t stoneCount, s for (uint8_t distribution = 0; distribution < distTable.size(); distribution++){ currentWeight -= distTable[distribution].weight; if (currentWeight <= 0){ - if (stoneCount >= distTable[distribution].copies){ + if (stoneCount >= distTable[distribution].copies || distTable[distribution].copies == 0){ selected[distribution] += 1; stoneCount -= distTable[distribution].copies; break; @@ -1074,8 +1075,9 @@ void CreateStoneHints() { while(totalStones != 0){ totalStones = PlaceHints(selectedHints, distTable); - if (totalStones != 0){ + while (totalStones != 0){ DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight, false); + totalStones = PlaceHints(selectedHints, distTable); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/text.hpp b/soh/soh/Enhancements/randomizer/3drando/text.hpp index 7f7d16736..49e598f63 100644 --- a/soh/soh/Enhancements/randomizer/3drando/text.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/text.hpp @@ -13,13 +13,19 @@ public: : english(std::move(english_)), french(std::move(french_)), spanish(std::move(spanish_)), - german(std::move("")) {} + german(std::move("")) { + // german defaults to english text until a translation is provided. + german = english; + } Text(std::string english_, std::string french_, std::string spanish_, std::string german_) : english(std::move(english_)), french(std::move(french_)), spanish(std::move(spanish_)), german(std::move(german_)) {} - Text(std::string english_) : english(std::move(english_)), french(std::move("")), spanish(std::move("")), german(std::move("")) {} + Text(std::string english_) : english(std::move(english_)), french(std::move("")), spanish(std::move("")), german(std::move("")) { + // default unprovided languages to english text + french = spanish = german = english; + } const std::string& GetEnglish() const { return english; diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index 3827c40f8..ff9dfdf81 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -47,6 +47,10 @@ const std::string& Hint::GetDistribution() { void Hint::ResetVariables() { hintedLocation = RC_UNKNOWN_CHECK; + text = Text{}; + distribution = ""; + hintedArea = RA_NONE; + hintType = HINT_TYPE_STATIC; addedToPool = false; } } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5d32e7a35..3e861962b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -271,7 +271,7 @@ void Randomizer::LoadHintMessages() { CustomMessage(ctx->GetHint(RH_GANONDORF_HINT)->GetText())); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT, - CustomMessage(ctx->GetHint(RH_SARIA)->GetText()));//RANDOTODO: Change to RH_BLANK or remove {{message}} replacment + CustomMessage(ctx->GetHint(RH_GANONDORF_NOHINT)->GetText())); CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_SHEIK_NEED_HOOK, CustomMessage("{{message}}", "{{message}}", "{{message}}")); From b65a15028b926e8aac73988f7241c01edcfecda2 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:44:12 +0200 Subject: [PATCH 181/300] Update z_horse.c (#4014) --- soh/src/code/z_horse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/src/code/z_horse.c b/soh/src/code/z_horse.c index 6f7aa2d3a..48c76396f 100644 --- a/soh/src/code/z_horse.c +++ b/soh/src/code/z_horse.c @@ -75,6 +75,9 @@ void func_8006D0EC(PlayState* play, Player* player) { } else if ((play->sceneNum == gSaveContext.horseData.scene) && (((Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) != 0) && (!IS_RANDO || (IS_RANDO && CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && + Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP) && + Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) && + Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) && (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE)))) || DREG(1) != 0)) { // "Set by existence of horse %d %d %d" osSyncPrintf("馬存在によるセット %d %d %d\n", gSaveContext.horseData.scene, Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED), From 6b831f9256333933388b167785b7f98bb214afbf Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:44:59 +0200 Subject: [PATCH 182/300] Fix swim softlock (#3965) * Update mods.cpp * Update mods.cpp --- soh/soh/Enhancements/mods.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 0c157110b..5d86b11f4 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1464,40 +1464,44 @@ typedef struct { //special respawns used when voided out without swim to prevent infinite loops std::map swimSpecialRespawnInfo = { { - 0x1D9,//hf to zr in water + ENTR_ZORAS_RIVER_3,//hf to zr in water { { -1455.443, -20, 1384.826 }, 28761 } }, { - 0x311,//zr to hf in water + ENTR_HYRULE_FIELD_14,//zr to hf in water { { 5830.209, -92.16, 3925.911 }, -20025 } }, { - 0x4DA,//zr to lw + ENTR_LOST_WOODS_7,//zr to lw { { 1978.718, -36.908, -855 }, -16384 } }, { - 0x1DD,//lw to zr + ENTR_ZORAS_RIVER_4,//lw to zr { { 4082.366, 860.442, -1018.949 }, -32768 } }, { - 0x219,//gv to lh + ENTR_LAKE_HYLIA_1,//gv to lh { { -3276.416, -1033, 2908.421 }, 11228 } }, { - 0x10,//lh to water temple + ENTR_WATER_TEMPLE_0,//lh to water temple { { -182, 780, 759.5 }, -32768 } }, { - 0x21D,//water temple to lh + ENTR_LAKE_HYLIA_2,//water temple to lh { { -955.028, -1306.9, 6768.954 }, -32768 } }, { - 0x328,//lh to zd + ENTR_ZORAS_DOMAIN_4,//lh to zd { { -109.86, 11.396, -9.933 }, -29131 } }, { - 0x560,//zd to lh + ENTR_LAKE_HYLIA_7,//zd to lh { { -912, -1326.967, 3391 }, 0 } + }, + { + ENTR_GERUDO_VALLEY_1,//caught by gerudos as child + { { -424, -2051, -74 }, 16384 } } }; From 5174a48be1c39b08a8b8bc1966188b8793f3841f Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 22 Apr 2024 19:16:58 -0500 Subject: [PATCH 183/300] Point LUS to fork temporarily for dl fix --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index b135db823..b505413e8 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968 +Subproject commit b505413e85591ffc633c063ee2fe43cd7810b981 From 3070fb474612362aa8ee49d0f7bcd60316184d21 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:57:33 -0400 Subject: [PATCH 184/300] support lus gameoverlay changes (and bump LUS) (#4067) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 6 ++++++ soh/src/code/audio_load.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libultraship b/libultraship index 8a079ed15..81f04fdce 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 8a079ed15852fbd26e701fd317afc14530578a92 +Subproject commit 81f04fdcedeb5186b56b105fb0cc5cb0a478ae90 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 48489d542..f5d504afa 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -320,6 +320,12 @@ OTRGlobals::OTRGlobals() { auto sohInputEditorWindow = std::make_shared("gControllerConfigurationEnabled", "Input Editor"); context->InitWindow(sohInputEditorWindow); + + auto overlay = context->GetInstance()->GetWindow()->GetGui()->GetGameOverlay(); + overlay->LoadFont("Press Start 2P", "fonts/PressStart2P-Regular.ttf", 12.0f); + overlay->LoadFont("Fipps", "fonts/Fipps-Regular.otf", 32.0f); + overlay->SetCurrentFont(CVarGetString(CVAR_GAME_OVERLAY_FONT, "Press Start 2P")); + context->InitAudio(); SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c index 914366f91..cb7ba60bb 100644 --- a/soh/src/code/audio_load.c +++ b/soh/src/code/audio_load.c @@ -632,7 +632,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { // Keep track of the previous sequence/scene so we don't repeat notifications static uint16_t previousSeqId = UINT16_MAX; static int16_t previousSceneNum = INT16_MAX; - if (CVarGetInteger("gSeqNameOverlay", 0) && + if (CVarGetInteger(CVAR_AUDIO("SeqNameOverlay"), 0) && playerIdx == SEQ_PLAYER_BGM_MAIN && (seqId != previousSeqId || (gPlayState != NULL && gPlayState->sceneNum != previousSceneNum))) { @@ -642,7 +642,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { } const char* sequenceName = AudioCollection_GetSequenceName(seqId); if (sequenceName != NULL) { - Overlay_DisplayText_Seconds(CVarGetInteger("gSeqNameOverlayDuration", 5), sequenceName); + Overlay_DisplayText_Seconds(CVarGetInteger(CVAR_AUDIO("SeqNameOverlayDuration"), 5), sequenceName); } } } From 854e20680ad9cfbf814727a3af978102ab5efff9 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Tue, 23 Apr 2024 09:17:57 -0500 Subject: [PATCH 185/300] Fix forest temple entrance cs skip --- soh/soh/Enhancements/timesaver_hook_handlers.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 27947f3ea..46b4353ee 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -866,10 +866,12 @@ void TimeSaverOnActorInitHandler(void* actorRef) { } // Forest Temple entrance cutscene - if (actor->id == ACTOR_EN_PO_SISTERS && actor->params == 4124) { + // This is a bit of a hack, we can't effectively override the behavior of the torches + // or poes from which the cutscene is triggered until we can have a "BeforeActorInit" hook. + // So for now we're just going to set the flag before they get to the room the cutscene is in + if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && actor->id == ACTOR_EN_ST && !Flags_GetSwitch(gPlayState, 0x1B)) { if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { Flags_SetSwitch(gPlayState, 0x1B); - Actor_Kill(actor); } } From 39e62697317cc58c8afd49f5f57d996d9b9bba8d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 23 Apr 2024 10:26:59 -0400 Subject: [PATCH 186/300] Fixes bugs with spoiler file parsing (#4066) * Fix bugs with spoiler file parsing * Hopefully fix mac build issue * fix typo --- soh/soh/Enhancements/randomizer/context.cpp | 56 +++++++------------ soh/soh/Enhancements/randomizer/context.h | 2 - soh/soh/Enhancements/randomizer/item_list.cpp | 12 ++++ .../Enhancements/randomizer/location_list.cpp | 11 ++++ .../Enhancements/randomizer/randomizer.cpp | 22 +------- soh/soh/Enhancements/randomizer/settings.cpp | 2 +- soh/soh/Enhancements/randomizer/static_data.h | 4 ++ 7 files changed, 49 insertions(+), 60 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 5cf0dc087..3f5e09db3 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -20,19 +20,6 @@ namespace Rando { std::weak_ptr Context::mContext; Context::Context() { - mSpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK; - mSpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET; - - for (auto& item : StaticData::GetItemTable()) { - // Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE - // entry - if (item.GetName().english.empty()) { - continue; - } - mSpoilerfileGetNameToEnum[item.GetName().english] = item.GetRandomizerGet(); - mSpoilerfileGetNameToEnum[item.GetName().french] = item.GetRandomizerGet(); - } - mSpoilerfileHintTypeNameToEnum = { { "Static", HINT_TYPE_STATIC }, { "Trial", HINT_TYPE_TRIAL }, @@ -93,9 +80,6 @@ Context::Context() { mTrials = std::make_shared(); mSettings = std::make_shared(); mFishsanity = std::make_shared(); - for (auto& location : StaticData::GetLocationTable()) { - mSpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck(); - } } RandomizerArea Context::GetAreaFromString(std::string str) { @@ -409,22 +393,22 @@ void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) { void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) { nlohmann::json locationsJson = spoilerFileJson["locations"]; for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) { - RandomizerCheck rc = mSpoilerfileCheckNameToEnum[it.key()]; + RandomizerCheck rc = StaticData::SpoilerfileCheckNameToEnum[it.key()]; if (it->is_structured()) { nlohmann::json itemJson = *it; for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) { if (itemit.key() == "item") { - itemLocationTable[rc].SetPlacedItem(mSpoilerfileGetNameToEnum[itemit.value().get()]); + itemLocationTable[rc].SetPlacedItem(StaticData::SpoilerfileItemNameToEnum[itemit.value().get()]); } else if (itemit.key() == "price") { itemLocationTable[rc].SetCustomPrice(itemit.value().get()); } else if (itemit.key() == "model") { - overrides[rc] = ItemOverride(rc, mSpoilerfileGetNameToEnum[itemit.value().get()]); + overrides[rc] = ItemOverride(rc, StaticData::SpoilerfileItemNameToEnum[itemit.value().get()]); } else if (itemit.key() == "trickName") { overrides[rc].SetTrickName(Text(itemit.value().get())); } } } else { - itemLocationTable[rc].SetPlacedItem(mSpoilerfileGetNameToEnum[it.value().get()]); + itemLocationTable[rc].SetPlacedItem(StaticData::SpoilerfileItemNameToEnum[it.value().get()]); } } } @@ -433,23 +417,23 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { // Child Altar std::string childAltarText = spoilerFileJson["childAltar"]["hintText"].get(); AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE); - mEmeraldLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]]; - mRubyLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]]; - mSapphireLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]]; + mEmeraldLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]]; + mRubyLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]]; + mSapphireLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]]; // Adult Altar std::string adultAltarText = spoilerFileJson["adultAltar"]["hintText"].get(); AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE); - mForestMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"].get()]; - mFireMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"].get()]; - mWaterMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"].get()]; - mShadowMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"].get()]; - mSpiritMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"].get()]; - mLightMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"].get()]; + mForestMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"].get()]; + mFireMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"].get()]; + mWaterMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"].get()]; + mShadowMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"].get()]; + mSpiritMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"].get()]; + mLightMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"].get()]; // Ganondorf and Sheik Light Arrow Hints std::string ganonHintText = spoilerFileJson["ganonHintText"].get(); - RandomizerCheck lightArrowLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"].get()]; + RandomizerCheck lightArrowLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"].get()]; std::string lightArrowRegion = spoilerFileJson["lightArrowArea"].get(); AddHint(RH_GANONDORF_HINT, Text(ganonHintText), lightArrowLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[lightArrowRegion]); if (spoilerFileJson.contains("sheikText")) { @@ -463,7 +447,7 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { if (spoilerFileJson.contains("dampeText")) { std::string dampeText = spoilerFileJson["dampeText"].get(); std::string dampeRegion = spoilerFileJson["dampeRegion"].get(); - RandomizerCheck dampeHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"].get()]; + RandomizerCheck dampeHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"].get()]; AddHint(RH_DAMPES_DIARY, Text(dampeText), dampeHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[dampeRegion]); } @@ -471,7 +455,7 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { if (spoilerFileJson.contains("gregText")) { std::string gregText = spoilerFileJson["gregText"].get(); std::string gregRegion = spoilerFileJson["gregRegion"].get(); - RandomizerCheck gregLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"].get()]; + RandomizerCheck gregLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"].get()]; AddHint(RH_GREG_RUPEE, Text(gregText), gregLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[gregRegion]); } @@ -479,7 +463,7 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { if (spoilerFileJson.contains("sariaText")) { std::string sariaText = spoilerFileJson["sariaText"].get(); std::string sariaRegion = spoilerFileJson["sariaRegion"].get(); - RandomizerCheck sariaHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"].get()]; + RandomizerCheck sariaHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"].get()]; AddHint(RH_SARIA, Text(sariaText), sariaHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[sariaRegion]); } @@ -487,7 +471,7 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { if(spoilerFileJson.contains("fishingPoleText")) { std::string fishingPoleText = spoilerFileJson["fishingPoleText"].get(); std::string fishingPoleRegion = spoilerFileJson["fishingPoleRegion"].get(); - RandomizerCheck fishingPoleHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["fishingPoleHintLoc"].get()]; + RandomizerCheck fishingPoleHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["fishingPoleHintLoc"].get()]; AddHint(RH_FISHING_POLE, Text(fishingPoleText), fishingPoleHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[fishingPoleRegion]); } @@ -520,11 +504,11 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { // Gossip Stones nlohmann::json hintsJson = spoilerFileJson["hints"]; for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) { - RandomizerCheck gossipStoneLoc = mSpoilerfileCheckNameToEnum[it.key()]; + RandomizerCheck gossipStoneLoc = StaticData::SpoilerfileCheckNameToEnum[it.key()]; nlohmann::json hintInfo = it.value(); std::string hintText = hintInfo["hint"].get(); HintType hintType = mSpoilerfileHintTypeNameToEnum[hintInfo["type"].get()]; - RandomizerCheck hintedLocation = hintInfo.contains("location") ? mSpoilerfileCheckNameToEnum[hintInfo["location"]] : RC_UNKNOWN_CHECK; + RandomizerCheck hintedLocation = hintInfo.contains("location") ? StaticData::SpoilerfileCheckNameToEnum[hintInfo["location"]] : RC_UNKNOWN_CHECK; RandomizerArea hintedArea = hintInfo.contains("area") ? mSpoilerfileAreaNameToEnum[hintInfo["area"].get()] : RA_NONE; std::string distribution = hintInfo["distribution"].get(); AddHint(static_cast(gossipStoneLoc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), hintedLocation, hintType, distribution, hintedArea); diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h index cef9e5292..06dd44628 100644 --- a/soh/soh/Enhancements/randomizer/context.h +++ b/soh/soh/Enhancements/randomizer/context.h @@ -87,14 +87,12 @@ class Context { std::vector possibleIceTrapModels = {}; std::unordered_map iceTrapModels = {}; std::array hashIconIndexes = {}; - std::unordered_map mSpoilerfileCheckNameToEnum; bool playthroughBeatable = false; bool allLocationsReachable = false; RandomizerArea GetAreaFromString(std::string str); private: static std::weak_ptr mContext; - std::unordered_map mSpoilerfileGetNameToEnum; std::unordered_map mSpoilerfileHintTypeNameToEnum; std::unordered_map mSpoilerfileAreaNameToEnum; std::array hintTable = {}; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 343f680b1..4541550e8 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -8,6 +8,7 @@ using namespace Rando; std::array Rando::StaticData::itemTable; +std::unordered_map Rando::StaticData::SpoilerfileItemNameToEnum; void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); @@ -320,6 +321,17 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, &logic->TriforcePieces, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + + // Init SpoilerfileItemNameToEnum + for (auto& item : itemTable) { + // Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE + // entry + if (item.GetName().english.empty()) { + continue; + } + SpoilerfileItemNameToEnum[item.GetName().english] = item.GetRandomizerGet(); + SpoilerfileItemNameToEnum[item.GetName().french] = item.GetRandomizerGet(); + } } Item& Rando::StaticData::RetrieveItem(const RandomizerGet rgid) { diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index ea4775d46..c5418dda2 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -3,6 +3,8 @@ #define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) std::array Rando::StaticData::locationTable; +std::unordered_map Rando::StaticData::SpoilerfileCheckNameToEnum; +std::multimap, RandomizerCheck> Rando::StaticData::CheckFromActorMultimap; std::vector KF_ShopLocations = { RC_KF_SHOP_ITEM_1, RC_KF_SHOP_ITEM_2, RC_KF_SHOP_ITEM_3, RC_KF_SHOP_ITEM_4, @@ -1569,6 +1571,15 @@ void Rando::StaticData::InitLocationTable() { locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on + + // Init SpoilerfileCheckNameToEnum + SpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK; + SpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET; + + for (auto& location : locationTable) { + SpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck(); + CheckFromActorMultimap.emplace(std::make_tuple((int16_t)location.GetActorID(), (int16_t)location.GetScene(), location.GetActorParams()), location.GetRandomizerCheck()); + } } Location* Rando::StaticData::GetLocation(RandomizerCheck locKey) { diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3e861962b..1a4d21f7d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -47,11 +47,8 @@ extern std::array hintTypeNames; using json = nlohmann::json; using namespace std::literals::string_literals; -std::unordered_map SpoilerfileCheckNameToEnum; -std::unordered_map SpoilerfileGetNameToEnum; std::unordered_map SpoilerfileAreaNameToEnum; std::unordered_map SpoilerfileHintTypeNameToEnum; -std::multimap, RandomizerCheck> checkFromActorMultimap; std::set excludedLocations; std::set spoilerExcludedLocations; std::set enabledTricks; @@ -129,24 +126,7 @@ static const char* frenchRupeeNames[36] = { Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); - for (auto& location : Rando::StaticData::GetLocationTable()) { - SpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck(); - checkFromActorMultimap.emplace(std::make_tuple((s16)location.GetActorID(), (s16)location.GetScene(), location.GetActorParams()), location.GetRandomizerCheck()); - } - SpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK; - SpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET; - for (auto& item: Rando::StaticData::GetItemTable()) { - // Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE entry - if (item.GetName().english.empty()) continue; - SpoilerfileGetNameToEnum[item.GetName().english] = item.GetRandomizerGet(); - SpoilerfileGetNameToEnum[item.GetName().french] = item.GetRandomizerGet(); - EnumToSpoilerfileGetName[item.GetRandomizerGet()] = { - item.GetName().english, - item.GetName().english, - item.GetName().french, - }; - } for (auto area : rcAreaNames) { SpoilerfileAreaNameToEnum[area.second] = area.first; } @@ -1758,7 +1738,7 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, return Rando::StaticData::GetLocation(specialRc); } - auto range = checkFromActorMultimap.equal_range(std::make_tuple(actorId, sceneNum, actorParams)); + auto range = Rando::StaticData::CheckFromActorMultimap.equal_range(std::make_tuple(actorId, sceneNum, actorParams)); for (auto it = range.first; it != range.second; ++it) { if ( diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index ac947d4da..b664b0898 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -2644,7 +2644,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { ctx->AddExcludedOptions(); for (auto it = jsonExcludedLocations.begin(); it != jsonExcludedLocations.end(); ++it) { - const RandomizerCheck rc = ctx->mSpoilerfileCheckNameToEnum[it.value()]; + const RandomizerCheck rc = StaticData::SpoilerfileCheckNameToEnum[it.value()]; ctx->GetItemLocation(rc)->GetExcludedOption()->SetSelectedIndex(RO_GENERIC_ON); } diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index 7650b5dc4..0e5ba4c03 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "randomizerTypes.h" #include "item.h" @@ -27,6 +28,9 @@ class StaticData { static void InitLocationTable(); static Location* GetLocation(RandomizerCheck locKey); static std::array& GetLocationTable(); + static std::unordered_map SpoilerfileCheckNameToEnum; + static std::unordered_map SpoilerfileItemNameToEnum; + static std::multimap, RandomizerCheck> CheckFromActorMultimap; static std::vector overworldLocations; static std::vector dungeonRewardLocations; static std::vector> shopLocationLists; From 99fbecd951bfd0710ccbd14ac8086b965ea1e143 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 23 Apr 2024 12:30:30 -0400 Subject: [PATCH 187/300] Fix issue with item name replacement at runtime. (#4068) --- soh/soh/Enhancements/randomizer/randomizer.cpp | 13 +++++++++++-- soh/soh/Enhancements/randomizer/randomizer.h | 3 --- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1a4d21f7d..99d8961a5 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2613,7 +2613,11 @@ CustomMessage Randomizer::ReplaceWithItemName(CustomMessage message, std::string ctx->overrides[hintedCheck].GetTrickName().english }; } else { - itemName = EnumToSpoilerfileGetName[targetRG]; + itemName = { + Rando::StaticData::RetrieveItem(targetRG).GetName().english, + Rando::StaticData::RetrieveItem(targetRG).GetName().french, + Rando::StaticData::RetrieveItem(targetRG).GetName().english, + }; } message.Replace(std::move(toReplace), std::move(itemName[0]), std::move(itemName[1]), std::move(itemName[2])); return message; @@ -2745,7 +2749,12 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te std::string(ctx->overrides[rc].GetTrickName().english) }; } else { - shopItemName = EnumToSpoilerfileGetName[shopItemGet]; + auto shopItem = Rando::StaticData::RetrieveItem(shopItemGet); + shopItemName = { + shopItem.GetName().english, + shopItem.GetName().french, + shopItem.GetName().english, + }; } u16 shopItemPrice = ctx->GetItemLocation(rc)->GetPrice(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 4d5a2ff30..5f567cd54 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -39,9 +39,6 @@ class Randomizer { static const std::string IceTrapRandoMessageTableID; static const std::string randoMiscHintsTableID; - // Public for now to be accessed by SaveManager, will be made private again soon :tm: - std::unordered_map> EnumToSpoilerfileGetName; - static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); void LoadMerchantMessages(); From c67d8f4baaf7702703dc15e07c68b67ff2d61d9a Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Tue, 23 Apr 2024 11:31:34 -0500 Subject: [PATCH 188/300] Add missing RHT entries --- .../randomizer/3drando/hint_list.cpp | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index c6269d5de..54d2cf056 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -404,6 +404,81 @@ void HintTable_Init() { /*french*/ "la #cinquième salle# de la Chasse-aux-Trésors contient", /*spanish*/ "#en la quinta sala del Cofre del Tesoro# aguarda" }); + hintTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_1] = HintText::Sometimes( + { + // obscure text + Text{ "#gambling once# grants", /*french*/ "#parier une fois# donne", + /*spanish*/ "#apostar solo una vez# revelará" }, + Text{ "the #first or second game chest# contains", + /*french*/ "le #premier ou deuxième coffre à jeu# contient", + /*spanish*/ "#el primer o segundo cofre del azar# revela" }, + }, + {}, + // clear text + Text{ "the #first locked room# in the chest game contains", + /*french*/ "la #première salle# de la Chasse-aux-Trésors contient", + /*spanish*/ "#en la primera sala del Cofre del Tesoro# aguarda" }); + + hintTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_2] = HintText::Sometimes( + { + // obscure text + Text{ "#gambling twice# grants", /*french*/ "#parier deux fois# donne", + /*spanish*/ "#apostar dos veces# revelará" }, + Text{ "the #third or fourth game chest# contains", + /*french*/ "le #troisième ou quatrième coffre à jeu# contient", + /*spanish*/ "#el tercer o cuarto cofre del azar# revela" }, + }, + {}, + // clear text + Text{ "the #second locked room# in the chest game contains", + /*french*/ "la #deuxième salle# de la Chasse-aux-Trésors contient", + /*spanish*/ "#en la segunda sala del Cofre del Tesoro# aguarda" }); + + hintTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_3] = HintText::Sometimes( + { + // obscure text + Text{ "#gambling 3 times# grants", /*french*/ "#parier trois fois# donne", + /*spanish*/ "#apostar tres veces# revelará" }, + Text{ "the #fifth or sixth game chest# contains", + /*french*/ "le #cinquième ou sixième coffre à jeu# contient", + /*spanish*/ "#el quinto o sexto cofre del azar# revela" }, + }, + {}, + // clear text + Text{ "the #third locked room# in the chest game contains", + /*french*/ "la #troisième salle# de la Chasse-aux-Trésors contient", + /*spanish*/ "#en la tercera sala del Cofre del Tesoro# aguarda" }); + + hintTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_4] = HintText::Sometimes( + { + // obscure text + Text{ "#gambling 4 times# grants", /*french*/ "#parier quatre fois# donne", + /*spanish*/ "#apostar cuatro veces# revelará" }, + Text{ "the #seventh or eighth game chest# contains", + /*french*/ "le #septième ou huitième coffre à jeu# contient", + /*spanish*/ "#el séptimo u octavo cofre del azar# revela" }, + }, + {}, + // clear text + Text{ "the #fourth locked room# in the chest game contains", + /*french*/ "la #quatrième salle# de la Chasse-aux-Trésors contient", + /*spanish*/ "#en la cuarta sala del Cofre del Tesoro# aguarda" }); + + hintTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_5] = HintText::Sometimes( + { + // obscure text + Text{ "#gambling 5 times# grants", /*french*/ "#parier cinq fois# donne", + /*spanish*/ "#apostar cinco veces# revelará" }, + Text{ "the #ninth or tenth game chest# contains", + /*french*/ "le #neuvième ou dixième coffre à jeu# contient", + /*spanish*/ "#el noveno o décimo cofre del azar# revela" }, + }, + {}, + // clear text + Text{ "the #fifth locked room# in the chest game contains", + /*french*/ "la #cinquième salle# de la Chasse-aux-Trésors contient", + /*spanish*/ "#en la quinta sala del Cofre del Tesoro# aguarda" }); + hintTable[RHT_GF_HBA_1500_POINTS] = HintText::Sometimes( { // obscure text From 65c580633339f9bd3bd5bd0cb1d9b408869df5e7 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 24 Apr 2024 17:09:49 -0400 Subject: [PATCH 189/300] Better fix for blank hint issue. (#4070) --- soh/soh/Enhancements/randomizer/3drando/hints.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index ba4fce24b..e007c06af 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -964,7 +964,12 @@ static void DistributeHints(std::vector& selected, size_t stoneCount, s for (uint8_t distribution = 0; distribution < distTable.size(); distribution++){ currentWeight -= distTable[distribution].weight; if (currentWeight <= 0){ - if (stoneCount >= distTable[distribution].copies || distTable[distribution].copies == 0){ + if (distTable[distribution].copies == 0) { + // This should only happen if we ran out of locations to place hints of a certain distribution earlier. Skip + // to the next distribution. + break; + } + if (stoneCount >= distTable[distribution].copies){ selected[distribution] += 1; stoneCount -= distTable[distribution].copies; break; From d22dbd69338e770eb2f944d458fdb65ab3560dac Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:16:59 -0400 Subject: [PATCH 190/300] move `RawJson` to LUS (#4063) --- soh/soh/Enhancements/tts/tts.cpp | 12 ++++++------ soh/soh/OTRGlobals.cpp | 2 -- soh/soh/resource/importer/RawJsonFactory.cpp | 19 ------------------- soh/soh/resource/importer/RawJsonFactory.h | 11 ----------- soh/soh/resource/type/RawJson.cpp | 14 -------------- soh/soh/resource/type/RawJson.h | 20 -------------------- soh/soh/resource/type/SohResourceType.h | 1 - 7 files changed, 6 insertions(+), 73 deletions(-) delete mode 100644 soh/soh/resource/importer/RawJsonFactory.cpp delete mode 100644 soh/soh/resource/importer/RawJsonFactory.h delete mode 100644 soh/soh/resource/type/RawJson.cpp delete mode 100644 soh/soh/resource/type/RawJson.h diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index f4b498815..3a375230f 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,7 +13,6 @@ #include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/resource/type/SohResourceType.h" -#include "soh/resource/type/RawJson.h" extern "C" { extern MapData* gMapData; @@ -1041,19 +1041,19 @@ void InitTTSBank() { auto initData = std::make_shared(); initData->Format = RESOURCE_FORMAT_BINARY; - initData->Type = static_cast(SOH::ResourceType::SOH_RawJson); + initData->Type = static_cast(LUS::ResourceType::Json); initData->ResourceVersion = 0; - sceneMap = std::static_pointer_cast( + sceneMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; - miscMap = std::static_pointer_cast( + miscMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; - kaleidoMap = std::static_pointer_cast( + kaleidoMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; - fileChooseMap = std::static_pointer_cast( + fileChooseMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c7e363ad7..d62e75703 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -120,7 +120,6 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/BackgroundFactory.h" -#include "soh/resource/importer/RawJsonFactory.h" #include "soh/config/ConfigUpdaters.h" @@ -349,7 +348,6 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast(SOH::ResourceType::SOH_AudioSoundFont), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); - loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast(SOH::ResourceType::SOH_RawJson), 0); gSaveStateMgr = std::make_shared(); gRandoContext = Rando::Context::CreateInstance(); diff --git a/soh/soh/resource/importer/RawJsonFactory.cpp b/soh/soh/resource/importer/RawJsonFactory.cpp deleted file mode 100644 index 4978f6f96..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "soh/resource/importer/RawJsonFactory.h" -#include "soh/resource/type/RawJson.h" -#include "spdlog/spdlog.h" - -namespace SOH { -std::shared_ptr ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr file) { - if (!FileHasValidFormatAndReader(file)) { - return nullptr; - } - - auto rawJson = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); - - rawJson->DataSize = file->Buffer->size(); - rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true); - - return rawJson; -} -} // namespace SOH diff --git a/soh/soh/resource/importer/RawJsonFactory.h b/soh/soh/resource/importer/RawJsonFactory.h deleted file mode 100644 index d5fa656b6..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include "resource/ResourceFactoryBinary.h" - -namespace SOH { -class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary { - public: - std::shared_ptr ReadResource(std::shared_ptr file) override; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/RawJson.cpp b/soh/soh/resource/type/RawJson.cpp deleted file mode 100644 index 3022a67ef..000000000 --- a/soh/soh/resource/type/RawJson.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "RawJson.h" - -namespace SOH { -RawJson::RawJson() : Resource(std::shared_ptr()) { -} - -void* RawJson::GetPointer() { - return &Data; -} - -size_t RawJson::GetPointerSize() { - return DataSize * sizeof(char); -} -} // namespace SOH diff --git a/soh/soh/resource/type/RawJson.h b/soh/soh/resource/type/RawJson.h deleted file mode 100644 index 47e0323cc..000000000 --- a/soh/soh/resource/type/RawJson.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include - -namespace SOH { - -class RawJson : public LUS::Resource { - public: - using Resource::Resource; - - RawJson(); - - void* GetPointer() override; - size_t GetPointerSize() override; - - nlohmann::json Data; - size_t DataSize; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index 3ef4163fe..fdf39031e 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -17,6 +17,5 @@ enum class ResourceType { SOH_AudioSequence = 0x4F534551, // OSEQ SOH_Background = 0x4F424749, // OBGI SOH_SceneCommand = 0x4F52434D, // ORCM - SOH_RawJson = 0x4A534F4E, // JSON }; } // namespace SOH From b2041df311fa68331836246b55f58dbd515aefca Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 24 Apr 2024 21:21:22 -0400 Subject: [PATCH 191/300] latest lus main --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index b505413e8..493639d5d 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b505413e85591ffc633c063ee2fe43cd7810b981 +Subproject commit 493639d5daf75c8fa5d374f96fc95b652714299f From 1fff8fd6d5da26b089f7ec1ec0ef7e4bce17f1ee Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 24 Apr 2024 21:48:31 -0400 Subject: [PATCH 192/300] don't skip item give animation in chu bowling --- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 42dabae88..bd71f7e0c 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -244,6 +244,9 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { // Skipping ItemGet animation incompatible with checks that require closing a text box to finish rc != RC_HF_OCARINA_OF_TIME_ITEM && rc != RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && + rc != RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE && + rc != RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE && + rc != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS && // Always show ItemGet animation for ice traps !(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) && ( From a4fb67745a187e564b215f2ed98c85bdfeb3d78f Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:55:16 -0400 Subject: [PATCH 193/300] nlohmann from package managers (#4071) --- .github/workflows/apt-deps.txt | 2 +- .github/workflows/generate-builds.yml | 37 ++++++++++++++++++++ .github/workflows/macports-deps.txt | 2 +- .github/workflows/test-builds-on-distros.yml | 3 ++ CMakeLists.txt | 2 +- OTRExporter | 2 +- libultraship | 2 +- 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index e9f7e07e1..af6f8aabd 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev ninja-build diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 96ae2f270..4b8153a07 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -190,6 +190,21 @@ jobs: cmake .. make sudo make install + - name: Install latest nlohmann + if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} + run: | + sudo apt-get remove nlohmann-json3-dev + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + if [ ! -d "json-3.11.3" ]; then + wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz + tar -xzvf v3.11.3.tar.gz + fi + cd json-3.11.3 + mkdir build + cd build + cmake .. + make + sudo make install - name: Install latest SDL_net if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | @@ -247,6 +262,17 @@ jobs: cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake make make install + cd ../.. + wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz + tar -xzvf v3.11.3.tar.gz + cd json-3.11.3 + mkdir build + cd build + cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake + make + make install + cd ../.. + - name: Fix dubious ownership error if: ${{ vars.LINUX_RUNNER }} run: git config --global --add safe.directory '*' @@ -300,6 +326,17 @@ jobs: cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake make make install + cd ../.. + wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz + tar -xzvf v3.11.3.tar.gz + cd json-3.11.3 + mkdir build + cd build + cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake + make + make install + cd ../.. + - uses: actions/checkout@v3 with: submodules: true diff --git a/.github/workflows/macports-deps.txt b/.github/workflows/macports-deps.txt index 084428d16..96bb9d40a 100644 --- a/.github/workflows/macports-deps.txt +++ b/.github/workflows/macports-deps.txt @@ -1 +1 @@ -libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal \ No newline at end of file +libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal \ No newline at end of file diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index 190599a44..82709d1af 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -1,3 +1,6 @@ +# todo: +# nlohmann + name: test-builds-on-distros on: workflow_dispatch: # by request diff --git a/CMakeLists.txt b/CMakeLists.txt index f5227169d..386142065 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") set(VCPKG_TARGET_TRIPLET x64-windows-static) vcpkg_bootstrap() - vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3) + vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json) if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) diff --git a/OTRExporter b/OTRExporter index e93bd2be0..467434c56 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit e93bd2be062b13106fdb29d98cf4ada4d7ad6827 +Subproject commit 467434c5666e11a3a7b756ff04401cd54da5c3f2 diff --git a/libultraship b/libultraship index 81f04fdce..85f6de497 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 81f04fdcedeb5186b56b105fb0cc5cb0a478ae90 +Subproject commit 85f6de497f6d375390cc3b4ba55eae5ef9c1b153 From 56d8dd6d8b754e2f77aa6f27169f58b73701172a Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 25 Apr 2024 17:31:28 -0700 Subject: [PATCH 194/300] All MenuBar enhancement CVars done. (#4064) --- .../cosmetics/CosmeticsEditor.cpp | 2 +- .../cosmetics/authenticGfxPatches.cpp | 7 +- soh/soh/Enhancements/debugconsole.cpp | 2 +- .../Enhancements/debugger/MessageViewer.cpp | 2 +- soh/soh/Enhancements/enemyrandomizer.cpp | 3 +- soh/soh/Enhancements/gameplaystats.cpp | 3 +- soh/soh/Enhancements/mods.cpp | 90 +- soh/soh/Enhancements/presets.h | 872 +++++++++--------- .../randomizer/randomizer_check_tracker.cpp | 2 +- .../randomizer/randomizer_entrance.c | 2 +- soh/soh/OTRGlobals.cpp | 12 +- soh/soh/SohMenuBar.cpp | 532 +++++------ soh/src/code/code_80097A00.c | 2 +- soh/src/code/code_800EC960.c | 16 +- soh/src/code/shrink_window.c | 4 +- soh/src/code/z_actor.c | 12 +- soh/src/code/z_camera.c | 10 +- soh/src/code/z_collision_check.c | 4 +- soh/src/code/z_construct.c | 4 +- soh/src/code/z_demo.c | 6 +- soh/src/code/z_en_item00.c | 58 +- soh/src/code/z_face_reaction.c | 2 +- soh/src/code/z_fcurve_data_skelanime.c | 2 +- soh/src/code/z_lifemeter.c | 4 +- soh/src/code/z_map_exp.c | 6 +- soh/src/code/z_message_PAL.c | 26 +- soh/src/code/z_olib.c | 2 +- soh/src/code/z_onepointdemo.c | 6 +- soh/src/code/z_parameter.c | 22 +- soh/src/code/z_play.c | 8 +- soh/src/code/z_player_lib.c | 46 +- soh/src/code/z_skelanime.c | 6 +- soh/src/code/z_sram.c | 4 +- .../actors/ovl_Bg_Breakwall/z_bg_breakwall.c | 2 +- .../overlays/actors/ovl_Bg_Haka/z_bg_haka.c | 2 +- .../actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c | 4 +- .../actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c | 4 +- .../ovl_Bg_Heavy_Block/z_bg_heavy_block.c | 6 +- .../ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c | 6 +- .../ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c | 2 +- .../actors/ovl_Bg_Jya_Cobra/z_bg_jya_cobra.c | 4 +- .../actors/ovl_Bg_Jya_Lift/z_bg_jya_lift.c | 2 +- .../ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c | 2 +- .../z_bg_mori_kaitenkabe.c | 4 +- .../actors/ovl_Bg_Po_Event/z_bg_po_event.c | 6 +- .../ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c | 6 +- .../ovl_Bg_Spot18_Basket/z_bg_spot18_basket.c | 2 +- .../actors/ovl_Boss_Ganon/z_boss_ganon.c | 2 +- .../actors/ovl_Boss_Ganon2/z_boss_ganon2.c | 2 +- .../actors/ovl_Boss_Goma/z_boss_goma.c | 6 +- .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 6 +- .../overlays/actors/ovl_Door_Ana/z_door_ana.c | 2 +- .../overlays/actors/ovl_Elf_Msg/z_elf_msg.c | 2 +- soh/src/overlays/actors/ovl_En_Am/z_en_am.c | 2 +- .../ovl_En_Anubice_Fire/z_en_anubice_fire.c | 2 +- .../actors/ovl_En_Blkobj/z_en_blkobj.c | 4 +- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 6 +- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 6 +- .../actors/ovl_En_Bom_Chu/z_en_bom_chu.c | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 6 +- .../actors/ovl_En_Clear_Tag/z_en_clear_tag.c | 4 +- soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c | 2 +- .../overlays/actors/ovl_En_Crow/z_en_crow.c | 2 +- soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c | 6 +- .../overlays/actors/ovl_En_Door/z_en_door.c | 4 +- soh/src/overlays/actors/ovl_En_Du/z_en_du.c | 6 +- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 8 +- .../actors/ovl_En_Encount1/z_en_encount1.c | 8 +- .../actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c | 2 +- .../actors/ovl_En_G_Switch/z_en_g_switch.c | 4 +- soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c | 2 +- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 6 +- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 2 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 4 +- .../actors/ovl_En_Heishi4/z_en_heishi4.c | 4 +- soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c | 2 +- soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c | 8 +- .../actors/ovl_En_Kakasi2/z_en_kakasi2.c | 2 +- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c | 2 +- .../overlays/actors/ovl_En_Kusa/z_en_kusa.c | 4 +- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 4 +- soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c | 12 +- soh/src/overlays/actors/ovl_En_Md/z_en_md.c | 2 +- soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c | 2 +- .../actors/ovl_En_Nutsball/z_en_nutsball.c | 4 +- .../overlays/actors/ovl_En_Okuta/z_en_okuta.c | 4 +- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c | 16 +- .../actors/ovl_En_Peehat/z_en_peehat.c | 2 +- soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c | 4 +- soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c | 2 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 4 +- soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c | 4 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 6 +- soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c | 4 +- .../ovl_En_Syateki_Itm/z_en_syateki_itm.c | 6 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 6 +- soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c | 16 +- .../actors/ovl_En_Torch2/z_en_torch2.c | 4 +- .../overlays/actors/ovl_En_Toryo/z_en_toryo.c | 2 +- .../overlays/actors/ovl_En_Vali/z_en_vali.c | 2 +- .../actors/ovl_En_Wallmas/z_en_wallmas.c | 4 +- soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c | 2 +- .../actors/ovl_En_Wood02/z_en_wood02.c | 6 +- soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c | 2 +- .../overlays/actors/ovl_Fishing/z_fishing.c | 12 +- .../overlays/actors/ovl_Obj_Comb/z_obj_comb.c | 2 +- .../ovl_Obj_Lightswitch/z_obj_lightswitch.c | 2 +- .../overlays/actors/ovl_Obj_Mure/z_obj_mure.c | 4 +- .../actors/ovl_Obj_Mure2/z_obj_mure2.c | 4 +- .../actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c | 6 +- .../ovl_Obj_Roomtimer/z_obj_roomtimer.c | 2 +- .../actors/ovl_Oceff_Wipe/z_oceff_wipe.c | 2 +- .../actors/ovl_Oceff_Wipe2/z_oceff_wipe2.c | 2 +- .../actors/ovl_Oceff_Wipe3/z_oceff_wipe3.c | 2 +- .../actors/ovl_Oceff_Wipe4/z_oceff_wipe4.c | 2 +- .../actors/ovl_player_actor/z_player.c | 174 ++-- .../z_eff_ss_solder_srch_ball.c | 2 +- .../ovl_file_choose/z_file_choose.c | 16 +- .../overlays/gamestates/ovl_title/z_title.c | 6 +- .../misc/ovl_kaleido_scope/z_kaleido_debug.c | 2 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 36 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 20 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 26 +- 123 files changed, 1203 insertions(+), 1200 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 0b0f94f21..8dbabd460 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1248,7 +1248,7 @@ void Draw_Placements(){ ImGui::EndTable(); } } - if (CVarGetInteger("gVisualAgony",0) && ImGui::CollapsingHeader("Visual stone of agony position")) { + if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"),0) && ImGui::CollapsingHeader("Visual stone of agony position")) { if (ImGui::BeginTable("tabledvisualstoneofagony", 1, FlagsTable)) { ImGui::TableSetupColumn("Visual stone of agony settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); diff --git a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp index 709854c35..310517299 100644 --- a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp +++ b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp @@ -1,5 +1,6 @@ #include #include +#include "soh/OTRGlobals.h" extern "C" { #include @@ -81,7 +82,7 @@ void PatchDekuStickTextureOverflow() { const char* dlist = gLinkChildLinkDekuStickDL; int start = 5; - if (!CVarGetInteger("gFixTexturesOOB", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { // Unpatch the other texture fix for (size_t i = 0; i < 7; i++) { int instruction = start + (i == 0 ? 0 : i + 1); @@ -121,7 +122,7 @@ void PatchFreezardTextureOverflow() { char patchNameBuf[24]; // Patch using custom overflowed texture - if (!CVarGetInteger("gFixTexturesOOB", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { // Unpatch the other texture fix for (size_t i = 0; i < 7; i++) { int instruction = start + (i == 0 ? 0 : i + 1); @@ -163,7 +164,7 @@ void PatchIronKnuckleTextureOverflow() { // Until this is solved, Iron Knuckle will be hardcoded to always display with the "authentic" texture fix // Patch using custom overflowed texture - // if (!CVarGetInteger("gFixTexturesOOB", 0)) { + // if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { // Unpatch the other texture fix for (size_t i = 0; i < 7; i++) { int instruction = start + (i == 0 ? 0 : i + 1); diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index bbf72a6d3..e75450c7c 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -471,7 +471,7 @@ static bool FWHandler(std::shared_ptr Console, const std::vector @@ -233,7 +234,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po } EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) { - if (CVarGetInteger("gRandomizedEnemies", ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) { uint32_t finalSeed = seed + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt); Random_Init(finalSeed); } diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index efcf44efb..fa35edfb6 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -14,6 +14,7 @@ extern "C" { #include #include #include "soh/Enhancements/enhancementTypes.h" +#include "soh/OTRGlobals.h" extern "C" { #include @@ -538,7 +539,7 @@ void DrawGameplayStatsCountsTab() { GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_SWORD_SWINGS])); GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_STEPS])); // If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time) - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) { GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] / 2)); } GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_ROLLS])); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index b32e7d798..a10dd559b 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -253,7 +253,7 @@ void RegisterOcarinaTimeTravel() { GameInteractor::Instance->RegisterGameHook([]() { if (!GameInteractor::IsSaveLoaded(true)) { - CVarClear("gTimeTravel"); + CVarClear(CVAR_ENHANCEMENT("TimeTravel")); return; } @@ -267,7 +267,7 @@ void RegisterOcarinaTimeTravel() { uint8_t hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME); // If TimeTravel + Player have the Ocarina of Time + Have Master Sword + is in proper range // TODO: Once Swordless Adult is fixed: Remove the Master Sword check - if (((CVarGetInteger("gTimeTravel", 0) == 1 && hasOcarinaOfTime) || CVarGetInteger("gTimeTravel", 0) == 2) && hasMasterSword && + if (((CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 1 && hasOcarinaOfTime) || CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2) && hasMasterSword && gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME && !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyFrogs) { @@ -289,13 +289,13 @@ void AutoSave(GetItemEntry itemEntry) { // Don't autosave immediately after buying items from shops to prevent getting them for free! // Don't autosave in the Chamber of Sages since resuming from that map breaks the game // Don't autosave during the Ganon fight when picking up the Master Sword - if ((CVarGetInteger("gAutosave", AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) && + if ((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) && (gPlayState->gameplayFrames > 60 && gSaveContext.cutsceneIndex < 0xFFF0) && (gPlayState->sceneNum != SCENE_GANON_BOSS) && (gPlayState->sceneNum != SCENE_CHAMBER_OF_THE_SAGES)) { - if (((CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) { + if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) { // Autosave for all items performSave = true; - } else if (((CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS) || (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_MAJOR_ITEMS)) && (item != ITEM_NONE)) { + } else if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_MAJOR_ITEMS)) && (item != ITEM_NONE)) { // Autosave for major items if (itemEntry.modIndex == 0) { switch (item) { @@ -335,7 +335,7 @@ void AutoSave(GetItemEntry itemEntry) { case ITEM_BOMBCHU: case ITEM_BOMBCHUS_5: case ITEM_BOMBCHUS_20: - if (!CVarGetInteger("gBombchuDrops", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("BombchuDrops"), 0)) { performSave = true; } break; @@ -346,9 +346,9 @@ void AutoSave(GetItemEntry itemEntry) { } else if (itemEntry.modIndex == 1 && item != RG_ICE_TRAP) { performSave = true; } - } else if (CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS || - CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS || - CVarGetInteger("gAutosave", AUTOSAVE_OFF) == AUTOSAVE_LOCATION) { + } else if (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS || + CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS || + CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION) { performSave = true; } if (performSave) { @@ -366,13 +366,13 @@ void RegisterAutoSave() { void RegisterRupeeDash() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gRupeeDash", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) { return; } // Initialize Timer static uint16_t rupeeDashTimer = 0; - uint16_t rdmTime = CVarGetInteger("gDashInterval", 5) * 20; + uint16_t rdmTime = CVarGetInteger(CVAR_ENHANCEMENT("RupeeDashInterval"), 5) * 20; // Did time change by DashInterval? if (rupeeDashTimer >= rdmTime) { @@ -394,7 +394,7 @@ void RegisterShadowTag() { static uint16_t delayTimer = 60; GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gShadowTag", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) { return; } if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene @@ -425,7 +425,7 @@ static bool hasAffectedHealth = false; void UpdatePermanentHeartLossState() { if (!GameInteractor::IsSaveLoaded()) return; - if (!CVarGetInteger("gPermanentHeartLoss", 0) && hasAffectedHealth) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) { uint8_t heartContainers = gSaveContext.sohStats.heartContainers; // each worth 16 health uint8_t heartPieces = gSaveContext.sohStats.heartPieces; // each worth 4 health, but only in groups of 4 uint8_t startingHealth = 16 * 3; @@ -445,7 +445,7 @@ void RegisterPermanentHeartLoss() { }); GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gPermanentHeartLoss", 0) || !GameInteractor::IsSaveLoaded()) return; + if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) return; if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) { gSaveContext.healthCapacity -= 16; @@ -457,7 +457,7 @@ void RegisterPermanentHeartLoss() { void RegisterDeleteFileOnDeath() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gDeleteFileOnDeath", 0) || !GameInteractor::IsSaveLoaded() || &gPlayState->gameOverCtx == NULL || &gPlayState->pauseCtx == NULL) return; + if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || &gPlayState->gameOverCtx == NULL || &gPlayState->pauseCtx == NULL) return; if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); @@ -478,7 +478,7 @@ using DayTimeGoldSkulltulasList = std::vector; void RegisterDaytimeGoldSkultullas() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gNightGSAlwaysSpawn", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0)) { return; } @@ -524,7 +524,7 @@ void RegisterDaytimeGoldSkultullas() { } bool IsHyperBossesActive() { - return CVarGetInteger("gHyperBosses", 0) || + return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) || (IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES); } @@ -592,7 +592,7 @@ void UpdateHyperEnemiesState() { actorUpdateHookId = 0; } - if (CVarGetInteger("gHyperEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) { actorUpdateHookId = GameInteractor::Instance->RegisterGameHook([](void* refActor) { // Run the update function a second time to make enemies and minibosses move and act twice as fast. @@ -604,7 +604,7 @@ void UpdateHyperEnemiesState() { bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. - if (CVarGetInteger("gHyperEnemies", 0) && isEnemy && !isExcludedEnemy && + if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy && !Player_InBlockingCsMode(gPlayState, player)) { GameInteractor::RawAction::UpdateActor(actor); } @@ -614,7 +614,7 @@ void UpdateHyperEnemiesState() { void RegisterBonkDamage() { GameInteractor::Instance->RegisterGameHook([]() { - uint8_t bonkOption = CVarGetInteger("gBonkDamageMul", BONK_DAMAGE_NONE); + uint8_t bonkOption = CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE); if (bonkOption == BONK_DAMAGE_NONE) { return; } @@ -660,7 +660,7 @@ void UpdateDirtPathFixState(int32_t sceneNum) { case SCENE_HYRULE_FIELD: case SCENE_KOKIRI_FOREST: case SCENE_HYRULE_CASTLE: - CVarSetInteger("gZFightingMode", CVarGetInteger("gSceneSpecificDirtPathFix", ZFIGHT_FIX_DISABLED)); + CVarSetInteger("gZFightingMode", CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED)); return; default: CVarClear("gZFightingMode"); @@ -677,7 +677,7 @@ void UpdateMirrorModeState(int32_t sceneNum) { static bool prevMirroredWorld = false; bool nextMirroredWorld = false; - int16_t mirroredMode = CVarGetInteger("gMirroredWorldMode", MIRRORED_WORLD_OFF); + int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF); int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) || (sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) || (sceneNum == SCENE_GANON_BOSS); @@ -718,7 +718,7 @@ void RegisterMirrorModeHandler() { } void UpdatePatchHand() { - if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_CHILD) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_CHILD) { ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); @@ -746,7 +746,7 @@ void UpdatePatchHand() { ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1"); ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2"); } - if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_ADULT) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_ADULT) { ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); @@ -767,7 +767,7 @@ void RegisterPatchHandHandler() { void RegisterResetNaviTimer() { GameInteractor::Instance->RegisterGameHook([](int32_t sceneNum) { - if (CVarGetInteger("gEnhancements.ResetNaviTimer", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ResetNaviTimer"), 0)) { gSaveContext.naviTimer = 0; } }); @@ -1021,16 +1021,16 @@ typedef enum { } AltTrapType; const char* altTrapTypeCvars[] = { - "gAddTraps.Ice", - "gAddTraps.Burn", - "gAddTraps.Shock", - "gAddTraps.Knock", - "gAddTraps.Speed", - "gAddTraps.Bomb", - "gAddTraps.Void", - "gAddTraps.Ammo", - "gAddTraps.Kill", - "gAddTraps.Tele" + CVAR_ENHANCEMENT("ExtraTraps.Ice"), + CVAR_ENHANCEMENT("ExtraTraps.Burn"), + CVAR_ENHANCEMENT("ExtraTraps.Shock"), + CVAR_ENHANCEMENT("ExtraTraps.Knockback"), + CVAR_ENHANCEMENT("ExtraTraps.Speed"), + CVAR_ENHANCEMENT("ExtraTraps.Bomb"), + CVAR_ENHANCEMENT("ExtraTraps.Void"), + CVAR_ENHANCEMENT("ExtraTraps.Ammo"), + CVAR_ENHANCEMENT("ExtraTraps.Kill"), + CVAR_ENHANCEMENT("ExtraTraps.Teleport") }; std::vector getEnabledAddTraps () { @@ -1052,7 +1052,7 @@ void RegisterAltTrapTypes() { static int eventTimer = -1; GameInteractor::Instance->RegisterGameHook([](GetItemEntry itemEntry) { - if (!CVarGetInteger("gAddTraps.enabled", 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) { return; } roll = RandomElement(getEnabledAddTraps()); @@ -1195,7 +1195,7 @@ void UpdateHurtContainerModeState(bool newState) { void RegisterHurtContainerModeHandler() { GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) { - UpdateHurtContainerModeState(CVarGetInteger("gHurtContainer", 0)); + UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); }); } @@ -1214,7 +1214,7 @@ void RegisterRandomizedEnemySizes() { actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH; // Only apply to enemies and bosses. - if (!CVarGetInteger("gRandomizedEnemySizes", 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) { return; } @@ -1237,7 +1237,7 @@ void RegisterRandomizedEnemySizes() { Actor_SetScale(actor, actor->scale.z * randomScale); - if (CVarGetInteger("gEnemySizeScalesHealth", 0) && (actor->category == ACTORCAT_ENEMY)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EnemySizeScalesHealth"), 0) && (actor->category == ACTORCAT_ENEMY)) { // Scale the health based on a smaller factor than randomScale float healthScalingFactor = 0.8f; // Adjust this factor as needed float scaledHealth = actor->colChkInfo.health * (randomScale * healthScalingFactor); @@ -1254,7 +1254,7 @@ void RegisterOpenAllHours() { GameInteractor::Instance->RegisterGameHook([](void* refActor) { Actor* actor = static_cast(refActor); - if (CVarGetInteger("gEnhancements.OpenAllHours", 0) && (actor->id == ACTOR_EN_DOOR)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR)) { switch (actor->params) { case 4753: // Night Market Bazaar case 1678: // Night Potion Shop @@ -1281,7 +1281,7 @@ void RegisterOpenAllHours() { void PatchToTMedallions() { // TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect // effects to take effect in there - if (CVarGetInteger("gToTMedallionsColors", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0)) { ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale", 7, gsSPGrayscale(true)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true)); @@ -1347,13 +1347,13 @@ void PatchToTMedallions() { void RegisterToTMedallions() { GameInteractor::Instance->RegisterGameHook([](GetItemEntry _unused) { - if (!CVarGetInteger("gToTMedallionsColors", 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) { return; } PatchToTMedallions(); }); GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { - if (!CVarGetInteger("gToTMedallionsColors", 0) || sceneNum != SCENE_TEMPLE_OF_TIME) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || sceneNum != SCENE_TEMPLE_OF_TIME) { return; } PatchToTMedallions(); @@ -1364,7 +1364,7 @@ void RegisterToTMedallions() { void RegisterFloorSwitchesHook() { GameInteractor::Instance->RegisterGameHook([](void* refActor) { Actor* actor = static_cast(refActor); - if (actor->id != ACTOR_OBJ_SWITCH || !CVarGetInteger("gEnhancements.FixFloorSwitches", 0)) { + if (actor->id != ACTOR_OBJ_SWITCH || !CVarGetInteger(CVAR_ENHANCEMENT("FixFloorSwitches"), 0)) { return; } @@ -1380,7 +1380,7 @@ void RegisterFloorSwitchesHook() { void RegisterPauseMenuHooks() { static bool pauseWarpHooksRegistered = false; GameInteractor::Instance->RegisterGameHook([&]() { - if (!GameInteractor::IsSaveLoaded() || !CVarGetInteger("gPauseWarp", 0)) { + if (!GameInteractor::IsSaveLoaded() || !CVarGetInteger(CVAR_ENHANCEMENT("PauseWarp"), 0)) { pauseWarpHooksRegistered = false; return; } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index fc202b94f..930b89b80 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -66,219 +66,219 @@ const std::vector enhancementsCvars = { "gRStickOcarina", "gDpadEquips", "gPauseAnyCursor", - "gDpadNoDropOcarinaInput", + CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), "gNaviOnL", "gInvertXAxis", "gInvertYAxis", "gRightStickAiming", "gDisableAutoCenterViewFirstPerson", - "gTextSpeed", - "gMweepSpeed", - "gForgeTime", - "gClimbSpeed", - "gFasterBlockPush", - "gCrawlSpeed", - "gFasterHeavyBlockLift", - "gNoForcedNavi", - "gSkulltulaFreeze", - "gMMBunnyHood", - "gAdultBunnyHood", - "gFastChests", - "gChestSizeAndTextureMatchesContents", - "gFastDrops", - "gBetterOwl", - "gFastOcarinaPlayback", - "gInstantPutaway", - "gFastBoomerang", - "gAskToEquip", - "gMaskSelect", - "gRememberSaveLocation", - "gDamageMul", - "gFallDamageMul", - "gVoidDamageMul", - "gBonkDamageMul", - "gNoRandomDrops", - "gNoHeartDrops", - "gBombchuDrops", - "gGoronPot", - "gFullHealthSpawn", - "gDampeWin", - "gRedPotionEffect", - "gRedPotionHealth", - "gRedPercentRestore", - "gGreenPotionEffect", - "gGreenPotionMana", - "gGreenPercentRestore", - "gBluePotionEffects", - "gBluePotionHealth", - "gBlueHealthPercentRestore", - "gBluePotionMana", - "gBlueManaPercentRestore", - "gMilkEffect", - "gMilkHealth", - "gMilkPercentRestore", - "gSeparateHalfMilkEffect", - "gHalfMilkHealth", - "gHalfMilkPercentRestore", - "gFairyEffect", - "gFairyHealth", - "gFairyPercentRestore", - "gFairyReviveEffect", - "gFairyReviveHealth", - "gFairyRevivePercentRestore", - "gCustomizeFishing", - "gInstantFishing", - "gGuaranteeFishingBite", - "gFishNeverEscape", - "gChildMinimumWeightFish", - "gAdultMinimumWeightFish", - "gLowHpAlarm", - "gMinimalUI", - "gDisableNaviCallAudio", - "gVisualAgony", - "gAssignableTunicsAndBoots", - "gEquipmentCanBeRemoved", - "gCowOfTime", - "gGuardVision", - "gTimeFlowFileSelect", - "gInjectItemCounts", - "gDayGravePull", - "gDampeAllNight", - "gQuitFishingAtDoor", - "gSkipSwimDeepEndAnim", - "gSkipScarecrow", - "gBlueFireArrows", - "gSunlightArrows", - "gPauseLiveLinkRotation", - "gPauseLiveLink", - "gMinFrameCount", + CVAR_ENHANCEMENT("TextSpeed"), + CVAR_ENHANCEMENT("MweepSpeed"), + CVAR_ENHANCEMENT("ForgeTime"), + CVAR_ENHANCEMENT("ClimbSpeed"), + CVAR_ENHANCEMENT("FasterBlockPush"), + CVAR_ENHANCEMENT("CrawlSpeed"), + CVAR_ENHANCEMENT("FasterHeavyBlockLift"), + CVAR_ENHANCEMENT("NoForcedNavi"), + CVAR_ENHANCEMENT("SkulltulaFreeze"), + CVAR_ENHANCEMENT("MMBunnyHood"), + CVAR_ENHANCEMENT("AdultBunnyHood"), + CVAR_ENHANCEMENT("FastChests"), + CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), + CVAR_ENHANCEMENT("FastDrops"), + CVAR_ENHANCEMENT("BetterOwl"), + CVAR_ENHANCEMENT("FastOcarinaPlayback"), + CVAR_ENHANCEMENT("InstantPutaway"), + CVAR_ENHANCEMENT("FastBoomerang"), + CVAR_ENHANCEMENT("AskToEquip"), + CVAR_ENHANCEMENT("MaskSelect"), + CVAR_ENHANCEMENT("RememberSaveLocation"), + CVAR_ENHANCEMENT("DamageMult"), + CVAR_ENHANCEMENT("FallDamageMult"), + CVAR_ENHANCEMENT("VoidDamageMult"), + CVAR_ENHANCEMENT("BonkDamageMult"), + CVAR_ENHANCEMENT("NoRandomDrops"), + CVAR_ENHANCEMENT("NoHeartDrops"), + CVAR_ENHANCEMENT("BombchuDrops"), + CVAR_ENHANCEMENT("GoronPot"), + CVAR_ENHANCEMENT("FullHealthSpawn"), + CVAR_ENHANCEMENT("DampeWin"), + CVAR_ENHANCEMENT("RedPotionEffect"), + CVAR_ENHANCEMENT("RedPotionHealth"), + CVAR_ENHANCEMENT("RedPercentRestore"), + CVAR_ENHANCEMENT("GreenPotionEffect"), + CVAR_ENHANCEMENT("GreenPotionMana"), + CVAR_ENHANCEMENT("GreenPercentRestore"), + CVAR_ENHANCEMENT("BluePotionEffects"), + CVAR_ENHANCEMENT("BluePotionHealth"), + CVAR_ENHANCEMENT("BlueHealthPercentRestore"), + CVAR_ENHANCEMENT("BluePotionMana"), + CVAR_ENHANCEMENT("BlueManaPercentRestore"), + CVAR_ENHANCEMENT("MilkEffect"), + CVAR_ENHANCEMENT("MilkHealth"), + CVAR_ENHANCEMENT("MilkPercentRestore"), + CVAR_ENHANCEMENT("SeparateHalfMilkEffect"), + CVAR_ENHANCEMENT("HalfMilkHealth"), + CVAR_ENHANCEMENT("HalfMilkPercentRestore"), + CVAR_ENHANCEMENT("FairyEffect"), + CVAR_ENHANCEMENT("FairyHealth"), + CVAR_ENHANCEMENT("FairyPercentRestore"), + CVAR_ENHANCEMENT("FairyReviveEffect"), + CVAR_ENHANCEMENT("FairyReviveHealth"), + CVAR_ENHANCEMENT("FairyRevivePercentRestore"), + CVAR_ENHANCEMENT("CustomizeFishing"), + CVAR_ENHANCEMENT("InstantFishing"), + CVAR_ENHANCEMENT("GuaranteeFishingBite"), + CVAR_ENHANCEMENT("FishNeverEscape"), + CVAR_ENHANCEMENT("MinimumFishWeightChild"), + CVAR_ENHANCEMENT("MinimumFishWeightAdult"), + CVAR_ENHANCEMENT("LowHpAlarm"), + CVAR_ENHANCEMENT("MinimalUI"), + CVAR_ENHANCEMENT("DisableNaviCallAudio"), + CVAR_ENHANCEMENT("VisualAgony"), + CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), + CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), + CVAR_ENHANCEMENT("CowOfTime"), + CVAR_ENHANCEMENT("GuardVision"), + CVAR_ENHANCEMENT("TimeFlowFileSelect"), + CVAR_ENHANCEMENT("InjectItemCounts"), + CVAR_ENHANCEMENT("DayGravePull"), + CVAR_ENHANCEMENT("DampeAllNight"), + CVAR_ENHANCEMENT("QuitFishingAtDoor"), + CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), + CVAR_ENHANCEMENT("InstantScarecrow"), + CVAR_ENHANCEMENT("BlueFireArrows"), + CVAR_ENHANCEMENT("SunlightArrows"), + CVAR_ENHANCEMENT("PauseLiveLinkRotation"), + CVAR_ENHANCEMENT("PauseLiveLink"), + CVAR_ENHANCEMENT("MinFrameCount"), "gN64Mode", - "gNewDrops", - "gDisableBlackBars", - "gDynamicWalletIcon", - "gAlwaysShowDungeonMinimapIcon", - "gUniformLR", - "gNGCKaleidoSwitcher", - "gFixDungeonMinimapIcon", - "gTwoHandedIdle", - "gGravediggingTourFix", - "gDekuNutUpgradeFix", - "gNaviTextFix", - "gAnubisFix", - "gCrouchStabHammerFix", - "gCrouchStabFix", - "gGerudoWarriorClothingFix", - "gFixCameraDrift", - "gFixCameraSwing", - "gFixHangingLedgeSwingRate", - "gRedGanonBlood", - "gHoverFishing", - "gN64WeirdFrames", - "gBombchusOOB", - "gQuickPutaway", - "gGsCutscene", - "gRestoreRBAValues", - "gSkipSaveConfirmation", - "gAutosave", - "gDisableCritWiggle", - "gChestSizeDependsStoneOfAgony", - "gSkipArrowAnimation", - "gSeparateArrows", - "gCustomizeShootingGallery", - "gInstantShootingGalleryWin", - "gConstantAdultGallery", - "gChildShootingGalleryAmmunition", - "gAdultShootingGalleryAmmunition", - "gCustomizeBombchuBowling", - "gBombchuBowlingNoSmallCucco", - "gBombchuBowlingNoBigCucco", - "gBombchuBowlingAmmunition", - "gCustomizeOcarinaGame", - "gInstantOcarinaGameWin", - "gOcarinaGameNoteSpeed", - "gOcarinaUnlimitedFailTime", - "gOcarinaGameStartingNotes", - "gOcarinaGameRoundOneNotes", - "gOcarinaGameRoundTwoNotes", - "gOcarinaGameRoundThreeNotes", - "gCreditsFix", - "gSilverRupeeJingleExtend", - "gStaticExplosionRadius", - "gNoInputForCredits", - "gFastFarores", - "gNightGSAlwaysSpawn", - "gSkipText", - "gLinkDefaultName", - "gMarketSneak", - "gTimeTravel", - "gNutsExplodeBombs", - "gBowSlingShotAmmoFix", - "gBetterFW", - "gDisableFirstPersonChus", - "gHyperBosses", - "gRupeeDash", - "gDashInterval", - "gDogFollowsEverywhere", - "gDisableTunicWarningText", - "gDisableLOD", - "gDisableDrawDistance", - "gDisableKokiriDrawDistance", + CVAR_ENHANCEMENT("NewDrops"), + CVAR_ENHANCEMENT("DisableBlackBars"), + CVAR_ENHANCEMENT("DynamicWalletIcon"), + CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), + CVAR_ENHANCEMENT("FixMenuLR"), + CVAR_ENHANCEMENT("NGCKaleidoSwitcher"), + CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), + CVAR_ENHANCEMENT("TwoHandedIdle"), + CVAR_ENHANCEMENT("GravediggingTourFix"), + CVAR_ENHANCEMENT("DekuNutUpgradeFix"), + CVAR_ENHANCEMENT("NaviTextFix"), + CVAR_ENHANCEMENT("AnubixFix"), + CVAR_ENHANCEMENT("CrouchStabHammerFix"), + CVAR_ENHANCEMENT("CrouchStabFix"), + CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), + CVAR_ENHANCEMENT("FixCameraDrift"), + CVAR_ENHANCEMENT("FixCameraSwing"), + CVAR_ENHANCEMENT("FixHangingLedgeSwingRate"), + CVAR_ENHANCEMENT("RedGanonBlood"), + CVAR_ENHANCEMENT("HoverFishing"), + CVAR_ENHANCEMENT("N64WeirdFrames"), + CVAR_ENHANCEMENT("BombchusOOB"), + CVAR_ENHANCEMENT("QuickPutaway"), + CVAR_ENHANCEMENT("GSCutscene"), + CVAR_ENHANCEMENT("RestoreRBAValues"), + CVAR_ENHANCEMENT("SkipSaveConfirmation"), + CVAR_ENHANCEMENT("Autosave"), + CVAR_ENHANCEMENT("DisableCritWiggle"), + CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), + CVAR_ENHANCEMENT("SkipArrowAnimation"), + CVAR_ENHANCEMENT("SeparateArrows"), + CVAR_ENHANCEMENT("CustomizeShootingGallery"), + CVAR_ENHANCEMENT("InstantShootingGalleryWin"), + CVAR_ENHANCEMENT("ConstantAdultGallery"), + CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), + CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), + CVAR_ENHANCEMENT("CustomizeBombchuBowling"), + CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco"), + CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), + CVAR_ENHANCEMENT("BombchuBowlingAmmo"), + CVAR_ENHANCEMENT("CustomizeOcarinaGame"), + CVAR_ENHANCEMENT("InstantOcarinaGameWin"), + CVAR_ENHANCEMENT("OcarinaGame.NoteSpeed"), + CVAR_ENHANCEMENT("OcarinaUnlimitedFailTime"), + CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), + CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), + CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), + CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), + CVAR_ENHANCEMENT("CreditsFix"), + CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), + CVAR_ENHANCEMENT("StaticExplosionRadius"), + CVAR_ENHANCEMENT("NoInputForCredits"), + CVAR_ENHANCEMENT("FastFarores"), + CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), + CVAR_ENHANCEMENT("SkipText"), + CVAR_ENHANCEMENT("LinkDefaultName"), + CVAR_ENHANCEMENT("MarketSneak"), + CVAR_ENHANCEMENT("TimeTravel"), + CVAR_ENHANCEMENT("NutsExplodeBombs"), + CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), + CVAR_ENHANCEMENT("BetterFarore"), + CVAR_ENHANCEMENT("DisableFirstPersonChus"), + CVAR_ENHANCEMENT("HyperBosses"), + CVAR_ENHANCEMENT("RupeeDash"), + CVAR_ENHANCEMENT("RupeeDashInterval"), + CVAR_ENHANCEMENT("DogFollowsEverywhere"), + CVAR_ENHANCEMENT("DisableTunicWarningText"), + CVAR_ENHANCEMENT("DisableLOD"), + CVAR_ENHANCEMENT("DisableDrawDistance"), + CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), "gLowResMode", - "gDrawLineupTick", - "gQuickBongoKill", - "gFPSGauntlets", - "gSceneSpecificDirtPathFix", + CVAR_ENHANCEMENT("DrawLineupTick"), + CVAR_ENHANCEMENT("QuickBongoKill"), + CVAR_ENHANCEMENT("FirstPersonGauntlets"), + CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), "gZFightingMode", - "gAuthenticLogo", - "gPauseLiveLinkRotationSpeed", - "gBowReticle", - "gFixTexturesOOB", - "gIvanCoopModeEnabled", - "gEnemySpawnsOverWaterboxes", - "gTreeStickDrops", - "gShadowTag", - "gRandomizedEnemySizes", - "gRandomizedEnemies", - "gMirroredWorldMode", + CVAR_ENHANCEMENT("AuthenticLogo"), + CVAR_ENHANCEMENT("PauseLiveLinkRotationSpeed"), + CVAR_ENHANCEMENT("BowReticle"), + CVAR_ENHANCEMENT("FixTexturesOOB"), + CVAR_ENHANCEMENT("IvanCoopModeEnabled"), + CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), + CVAR_ENHANCEMENT("TreesDropSticks"), + CVAR_ENHANCEMENT("ShadowTag"), + CVAR_ENHANCEMENT("RandomizedEnemySizes"), + CVAR_ENHANCEMENT("RandomizedEnemies"), + CVAR_ENHANCEMENT("MirroredWorldMode"), "gMirroredWorld", - "gHyperEnemies", - "gHookshotableReticle", - "gHideBunnyHood", - "gFixVineFall", - "gFileSelectMoreInfo", - "gEnemyHealthBar", - "gBushDropFix", - "gAllDogsRichard", - "gAddTraps.enabled", - "gAddTraps.Ammo", - "gAddTraps.Bomb", - "gAddTraps.Burn", - "gAddTraps.Ice", - "gAddTraps.Kill", - "gAddTraps.Knock", - "gAddTraps.Shock", - "gAddTraps.Speed", - "gAddTraps.Tele", - "gAddTraps.Void", - "gToTMedallionsColors", - "gCuccoStayDurationMultiplier", - "gDeleteFileOnDeath", - "gEnemySizeScalesHealth", - "gEnhancements.BetterAmmoRendering", - "gEnhancements.EquimentAlwaysVisible", - "gEnhancements.FixDaruniaDanceSpeed", - "gEnhancements.OpenAllHours", - "gEnhancements.ResetNaviTimer", - "gEnhancements.ScaleAdultEquimentAsChild", - "gEnhancements.LeeverSpawnRate", - "gEnhancements.SwordToggle", - "gEnhancements.FixFloorSwitches", - "gFixZoraHintDialogue", - "gHurtContainer", - "gPauseWarp", - "gPermanentHeartLoss", - "gRemoveExplosiveLimit", - "gToggleStrength", + CVAR_ENHANCEMENT("HyperEnemies"), + CVAR_ENHANCEMENT("HookshotableReticle"), + CVAR_ENHANCEMENT("HideBunnyHood"), + CVAR_ENHANCEMENT("FixVineFall"), + CVAR_ENHANCEMENT("FileSelectMoreInfo"), + CVAR_ENHANCEMENT("EnemyHealthBar"), + CVAR_ENHANCEMENT("BushDropFix"), + CVAR_ENHANCEMENT("AllDogsRichard"), + CVAR_ENHANCEMENT("ExtraTraps.Enabled"), + CVAR_ENHANCEMENT("ExtraTraps.Ammo"), + CVAR_ENHANCEMENT("ExtraTraps.Bomb"), + CVAR_ENHANCEMENT("ExtraTraps.Burn"), + CVAR_ENHANCEMENT("ExtraTraps.Ice"), + CVAR_ENHANCEMENT("ExtraTraps.Kill"), + CVAR_ENHANCEMENT("ExtraTraps.Knockback"), + CVAR_ENHANCEMENT("ExtraTraps.Shock"), + CVAR_ENHANCEMENT("ExtraTraps.Speed"), + CVAR_ENHANCEMENT("ExtraTraps.Teleport"), + CVAR_ENHANCEMENT("ExtraTraps.Void"), + CVAR_ENHANCEMENT("ToTMedallionsColors"), + CVAR_ENHANCEMENT("CuccoStayDurationMult"), + CVAR_ENHANCEMENT("DeleteFileOnDeath"), + CVAR_ENHANCEMENT("EnemySizeScalesHealth"), + CVAR_ENHANCEMENT("BetterAmmoRendering"), + CVAR_ENHANCEMENT("EquimentAlwaysVisible"), + CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), + CVAR_ENHANCEMENT("OpenAllHours"), + CVAR_ENHANCEMENT("ResetNaviTimer"), + CVAR_ENHANCEMENT("ScaleAdultEquimentAsChild"), + CVAR_ENHANCEMENT("LeeverSpawnRate"), + CVAR_ENHANCEMENT("SwordToggle"), + CVAR_ENHANCEMENT("FixFloorSwitches"), + CVAR_ENHANCEMENT("FixZoraHintDialogue"), + CVAR_ENHANCEMENT("HurtContainer"), + CVAR_ENHANCEMENT("PauseWarp"), + CVAR_ENHANCEMENT("PermanentHeartLoss"), + CVAR_ENHANCEMENT("RemoveExplosiveLimit"), + CVAR_ENHANCEMENT("ToggleStrength"), }; const std::vector cheatCvars = { @@ -293,11 +293,11 @@ const std::vector cheatCvars = { "gWalkModifierTwo", "gSwimModifierOne", "gSwimModifierTwo", - "gGoronPot", - "gDampeWin", - "gCustomizeShootingGallery", - "gCustomizeBombchuBowling", - "gCustomizeFishing", + CVAR_ENHANCEMENT("GoronPot"), + CVAR_ENHANCEMENT("DampeWin"), + CVAR_ENHANCEMENT("CustomizeShootingGallery"), + CVAR_ENHANCEMENT("CustomizeBombchuBowling"), + CVAR_ENHANCEMENT("CustomizeFishing"), CVAR_CHEAT("InfiniteAmmo"), CVAR_CHEAT("InfiniteEponaBoost"), CVAR_CHEAT("InfiniteHealth"), @@ -351,7 +351,7 @@ const std::vector cheatCvars = { "gCosmetics.Link_HeadScale.Value", "gCosmetics.Link_SwordScale.Changed", "gCosmetics.Link_SwordScale.Value", - "gEnhancements.RememberMapToggleState", + CVAR_ENHANCEMENT("RememberMapToggleState"), }; const std::vector randomizerCvars = { @@ -501,65 +501,65 @@ const std::vector vanillaPlusPresetEntries = { // D-pad as Equip Items PRESET_ENTRY_S32("gDpadEquips", 1), // Prevent Dropped Ocarina Inputs - PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming PRESET_ENTRY_S32("gRightStickAiming", 1), // Text Speed (1 to 5) - PRESET_ENTRY_S32("gTextSpeed", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), // Skip Text - PRESET_ENTRY_S32("gSkipText", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), // King Zora Speed (1 to 5) - PRESET_ENTRY_S32("gMweepSpeed", 2), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 2), // Faster Block Push (+0 to +5) - PRESET_ENTRY_S32("gFasterBlockPush", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), // Better Owl - PRESET_ENTRY_S32("gBetterOwl", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), // Assignable Tunics and Boots - PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1), // Enable passage of time on file select - PRESET_ENTRY_S32("gTimeFlowFileSelect", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), // Inject Item Counts in messages - PRESET_ENTRY_S32("gInjectItemCounts", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), // Pause link animation (0 to 16) - PRESET_ENTRY_S32("gPauseLiveLink", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseLiveLink"), 1), // Dynamic Wallet Icon - PRESET_ENTRY_S32("gDynamicWalletIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1), // Always show dungeon entrances - PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 1), // Fix L&R Pause menu - PRESET_ENTRY_S32("gUniformLR", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1), // Fix Dungeon entrances - PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), // Fix Two Handed idle animations - PRESET_ENTRY_S32("gTwoHandedIdle", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), // Fix the Gravedigging Tour Glitch - PRESET_ENTRY_S32("gGravediggingTourFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), // Fix Deku Nut upgrade - PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), // Fix Navi text HUD position - PRESET_ENTRY_S32("gNaviTextFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1), // Extend Silver Rupee Jingle - PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), // Fix some Floor Switches - PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), // Red Ganon blood - PRESET_ENTRY_S32("gRedGanonBlood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), // Fish while hovering - PRESET_ENTRY_S32("gHoverFishing", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), // N64 Weird Frames - PRESET_ENTRY_S32("gN64WeirdFrames", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1), // Bombchus out of bounds - PRESET_ENTRY_S32("gBombchusOOB", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), // Quick Putaway - PRESET_ENTRY_S32("gQuickPutaway", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1), // Skip save confirmation - PRESET_ENTRY_S32("gSkipSaveConfirmation", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), }; const std::vector enhancedPresetEntries = { @@ -572,123 +572,123 @@ const std::vector enhancedPresetEntries = { // D-pad as Equip Items PRESET_ENTRY_S32("gDpadEquips", 1), // Prevent Dropped Ocarina Inputs - PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming PRESET_ENTRY_S32("gRightStickAiming", 1), // Text Speed (1 to 5) - PRESET_ENTRY_S32("gTextSpeed", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), // Skip Text - PRESET_ENTRY_S32("gSkipText", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), // King Zora Speed (1 to 5) - PRESET_ENTRY_S32("gMweepSpeed", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 5), // Faster Block Push (+0 to +5) - PRESET_ENTRY_S32("gFasterBlockPush", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), // Better Owl - PRESET_ENTRY_S32("gBetterOwl", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), // Assignable Tunics and Boots - PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1), // Enable passage of time on file select - PRESET_ENTRY_S32("gTimeFlowFileSelect", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), // Inject Item Counts in messages - PRESET_ENTRY_S32("gInjectItemCounts", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), // Pause link animation (0 to 16) - PRESET_ENTRY_S32("gPauseLiveLink", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseLiveLink"), 1), // Dynamic Wallet Icon - PRESET_ENTRY_S32("gDynamicWalletIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1), // Always show dungeon entrances - PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 1), // Fix L&R Pause menu - PRESET_ENTRY_S32("gUniformLR", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1), // Fix Dungeon entrances - PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), // Fix Two Handed idle animations - PRESET_ENTRY_S32("gTwoHandedIdle", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), // Fix the Gravedigging Tour Glitch - PRESET_ENTRY_S32("gGravediggingTourFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), // Fix Deku Nut upgrade - PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), // Fix Navi text HUD position - PRESET_ENTRY_S32("gNaviTextFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1), // Extend Silver Rupee Jingle - PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), // Fix enemies not spawning on ground over water - PRESET_ENTRY_S32("gEnemySpawnsOverWaterboxes", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1), // Fix some Floor Switches - PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), // Red Ganon blood - PRESET_ENTRY_S32("gRedGanonBlood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), // Fish while hovering - PRESET_ENTRY_S32("gHoverFishing", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), // N64 Weird Frames - PRESET_ENTRY_S32("gN64WeirdFrames", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1), // Bombchus out of bounds - PRESET_ENTRY_S32("gBombchusOOB", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), // Quick Putaway - PRESET_ENTRY_S32("gQuickPutaway", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1), // Skip save confirmation - PRESET_ENTRY_S32("gSkipSaveConfirmation", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), // Biggoron Forge Time (0 to 3) - PRESET_ENTRY_S32("gForgeTime", 0), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0), // Vine/Ladder Climb speed (+0 to +12) - PRESET_ENTRY_S32("gClimbSpeed", 3), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3), // Faster Heavy Block Lift - PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), // No Forced Navi - PRESET_ENTRY_S32("gNoForcedNavi", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1), // No Skulltula Freeze - PRESET_ENTRY_S32("gSkulltulaFreeze", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), // MM Bunny Hood - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST_AND_JUMP), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST_AND_JUMP), // Adult Bunny Hood - PRESET_ENTRY_S32("gAdultBunnyHood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), // Fast Chests - PRESET_ENTRY_S32("gFastChests", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), // Fast Drops - PRESET_ENTRY_S32("gFastDrops", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1), // Fast Ocarina Playback - PRESET_ENTRY_S32("gFastOcarinaPlayback", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), // Instant Putaway - PRESET_ENTRY_S32("gInstantPutaway", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), // Instant Boomerang Recall - PRESET_ENTRY_S32("gFastBoomerang", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), // Nuts Explode Bombs - PRESET_ENTRY_S32("gNutsExplodeBombs", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1), // Ask to Equip New Items - PRESET_ENTRY_S32("gAskToEquip", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AskToEquip"), 1), // Mask Select in Inventory - PRESET_ENTRY_S32("gMaskSelect", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1), // Always Win Goron Pot - PRESET_ENTRY_S32("gGoronPot", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1), // Always Win Dampe Digging - PRESET_ENTRY_S32("gDampeWin", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1), // Skip Magic Arrow Equip Animation - PRESET_ENTRY_S32("gSkipArrowAnimation", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), // Equip arrows on multiple slots - PRESET_ENTRY_S32("gSeparateArrows", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), // Disable Navi Call Audio - PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1), // Equipment Toggle - PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1), // Link's Cow in Both Time Periods - PRESET_ENTRY_S32("gCowOfTime", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CowOfTime"), 1), // Enable 3D Dropped items/projectiles - PRESET_ENTRY_S32("gNewDrops", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32("gAnubisFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), // Autosave - PRESET_ENTRY_S32("gAutosave", AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), }; const std::vector randomizerPresetEntries = { @@ -701,206 +701,206 @@ const std::vector randomizerPresetEntries = { // D-pad as Equip Items PRESET_ENTRY_S32("gDpadEquips", 1), // Prevent Dropped Ocarina Inputs - PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming PRESET_ENTRY_S32("gRightStickAiming", 1), // Text Speed (1 to 5) - PRESET_ENTRY_S32("gTextSpeed", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), // Skip Text - PRESET_ENTRY_S32("gSkipText", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), // King Zora Speed (1 to 5) - PRESET_ENTRY_S32("gMweepSpeed", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 5), // Faster Block Push (+0 to +5) - PRESET_ENTRY_S32("gFasterBlockPush", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), // Better Owl - PRESET_ENTRY_S32("gBetterOwl", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), // Assignable Tunics and Boots - PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1), // Enable passage of time on file select - PRESET_ENTRY_S32("gTimeFlowFileSelect", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), // Inject Item Counts in messages - PRESET_ENTRY_S32("gInjectItemCounts", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), // Dynamic Wallet Icon - PRESET_ENTRY_S32("gDynamicWalletIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1), // Always show dungeon entrances - PRESET_ENTRY_S32("gAlwaysShowDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 1), // Fix L&R Pause menu - PRESET_ENTRY_S32("gUniformLR", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1), // Fix Dungeon entrances - PRESET_ENTRY_S32("gFixDungeonMinimapIcon", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), // Fix Two Handed idle animations - PRESET_ENTRY_S32("gTwoHandedIdle", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), // Fix the Gravedigging Tour Glitch - PRESET_ENTRY_S32("gGravediggingTourFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), // Fix Deku Nut upgrade - PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), // Fix Navi text HUD position - PRESET_ENTRY_S32("gNaviTextFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1), // Extend Silver Rupee Jingle - PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), // Fix some Floor Switches - PRESET_ENTRY_S32("gEnhancements.FixFloorSwitches", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), // Red Ganon blood - PRESET_ENTRY_S32("gRedGanonBlood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), // Fish while hovering - PRESET_ENTRY_S32("gHoverFishing", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), // N64 Weird Frames - PRESET_ENTRY_S32("gN64WeirdFrames", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1), // Bombchus out of bounds - PRESET_ENTRY_S32("gBombchusOOB", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), // Quick Putaway - PRESET_ENTRY_S32("gQuickPutaway", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1), // Skip save confirmation - PRESET_ENTRY_S32("gSkipSaveConfirmation", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), // Biggoron Forge Time (0 to 3) - PRESET_ENTRY_S32("gForgeTime", 0), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0), // Vine/Ladder Climb speed (+0 to +12) - PRESET_ENTRY_S32("gClimbSpeed", 3), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3), // Faster Heavy Block Lift - PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), // No Forced Navi - PRESET_ENTRY_S32("gNoForcedNavi", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1), // No Skulltula Freeze - PRESET_ENTRY_S32("gSkulltulaFreeze", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), // MM Bunny Hood - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST_AND_JUMP), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST_AND_JUMP), // Adult Bunny Hood - PRESET_ENTRY_S32("gAdultBunnyHood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), // Fast Chests - PRESET_ENTRY_S32("gFastChests", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), // Fast Drops - PRESET_ENTRY_S32("gFastDrops", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1), // Fast Ocarina Playback - PRESET_ENTRY_S32("gFastOcarinaPlayback", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), // Instant Putaway - PRESET_ENTRY_S32("gInstantPutaway", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), // Instant Boomerang Recall - PRESET_ENTRY_S32("gFastBoomerang", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), // Nuts Explode Bombs - PRESET_ENTRY_S32("gNutsExplodeBombs", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1), // Ask to Equip New Items - PRESET_ENTRY_S32("gAskToEquip", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AskToEquip"), 1), // Mask Select in Inventory - PRESET_ENTRY_S32("gMaskSelect", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1), // Always Win Goron Pot - PRESET_ENTRY_S32("gGoronPot", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1), // Always Win Dampe Digging - PRESET_ENTRY_S32("gDampeWin", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1), // Skip Magic Arrow Equip Animation - PRESET_ENTRY_S32("gSkipArrowAnimation", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), // Exit Market at Night - PRESET_ENTRY_S32("gMarketSneak", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MarketSneak"), 1), // Equip arrows on multiple slots - PRESET_ENTRY_S32("gSeparateArrows", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), // Disable Navi Call Audio - PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1), // Equipment Toggle - PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1), // Link's Cow in Both Time Periods - PRESET_ENTRY_S32("gCowOfTime", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CowOfTime"), 1), // Enable 3D Dropped items/projectiles - PRESET_ENTRY_S32("gNewDrops", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32("gAnubisFix", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), // Autosave - PRESET_ENTRY_S32("gAutosave", AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), // Customize Fishing Behaviour - PRESET_ENTRY_S32("gCustomizeFishing", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1), // Guarantee Bite - PRESET_ENTRY_S32("gGuaranteeFishingBite", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1), // Fish Never Escape - PRESET_ENTRY_S32("gFishNeverEscape", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FishNeverEscape"), 1), // Child Minimum Weight (6 to 10) - PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3), // Adult Minimum Weight (8 to 13) - PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6), // Customize Lost Woods Ocarina Game Behavior - PRESET_ENTRY_S32("gCustomizeOcarinaGame", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 1), // Start With Five Notes - PRESET_ENTRY_S32("gOcarinaGameStartingNotes", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 5), // Round One Notes - PRESET_ENTRY_S32("gOcarinaGameRoundOneNotes", 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), 5), // Visual Stone of Agony - PRESET_ENTRY_S32("gVisualAgony", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), // Pull grave during the day - PRESET_ENTRY_S32("gDayGravePull", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DayGravePull"), 1), // Pull out Ocarina to Summon Scarecrow - PRESET_ENTRY_S32("gSkipScarecrow", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1), // Chest size & texture matches contents - PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", CSMC_BOTH), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_BOTH), // Color Temple of Time's Medallions - PRESET_ENTRY_S32("gToTMedallionsColors", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1), // Pause link animation (0 to 16) - PRESET_ENTRY_S32("gPauseLiveLink", 16), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseLiveLink"), 16), // Frames to wait - PRESET_ENTRY_S32("gMinFrameCount", 200), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinFrameCount"), 200), - PRESET_ENTRY_S32("gNoInputForCredits", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), - PRESET_ENTRY_S32("gFastFarores", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1), }; const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LogicRules"), 0), - PRESET_ENTRY_S32("gTextSpeed", 5), - PRESET_ENTRY_S32("gMweepSpeed", 5), - PRESET_ENTRY_S32("gClimbSpeed", 4), - PRESET_ENTRY_S32("gFasterBlockPush", 5), - PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), - PRESET_ENTRY_S32("gNoForcedNavi", 1), - PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), - PRESET_ENTRY_S32("gFastChests", 1), - PRESET_ENTRY_S32("gFastDrops", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 4), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1), PRESET_ENTRY_S32("gDpadText", 1), PRESET_ENTRY_S32("gDpadOcarina", 1), PRESET_ENTRY_S32("gRStickOcarina", 1), PRESET_ENTRY_S32("gDpadEquips", 1), - PRESET_ENTRY_S32("gFastOcarinaPlayback", 1), - PRESET_ENTRY_S32("gSkipScarecrow", 1), - PRESET_ENTRY_S32("gMarketSneak", 1), - PRESET_ENTRY_S32("gInstantPutaway", 1), - PRESET_ENTRY_S32("gFastBoomerang", 1), - PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), - PRESET_ENTRY_S32("gSeparateArrows", 1), - PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), - PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), - PRESET_ENTRY_S32("gDayGravePull", 1), - PRESET_ENTRY_S32("gNewDrops", 1), - PRESET_ENTRY_S32("gCreditsFix", 1), - PRESET_ENTRY_S32("gSkipText", 1), - PRESET_ENTRY_S32("gSkulltulaFreeze", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MarketSneak"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DayGravePull"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), PRESET_ENTRY_S32("gPauseAnyCursor", 1), - PRESET_ENTRY_S32("gFastFarores", 1), - PRESET_ENTRY_S32("gNoInputForCredits", 1), - PRESET_ENTRY_S32("gMaskSelect", 1), - PRESET_ENTRY_S32("gInjectItemCounts", 1), - PRESET_ENTRY_S32("gCustomizeFishing", 1), - PRESET_ENTRY_S32("gFishNeverEscape", 1), - PRESET_ENTRY_S32("gInstantFishing", 1), - PRESET_ENTRY_S32("gGuaranteeFishingBite", 1), - PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), - PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), - PRESET_ENTRY_S32("gGoronPot", 1), - PRESET_ENTRY_S32("gForgeTime", 0), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FishNeverEscape"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantFishing"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0), PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1), - PRESET_ENTRY_S32("gDampeAllNight", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1), @@ -944,41 +944,41 @@ const std::vector spockRacePresetEntries = { }; const std::vector spockRaceNoLogicPresetEntries = { - PRESET_ENTRY_S32("gAdultBunnyHood", 1), - PRESET_ENTRY_S32("gAdultMinimumWeightFish", 6), - PRESET_ENTRY_S32("gAssignableTunicsAndBoots", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1), PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1), - PRESET_ENTRY_S32("gChildMinimumWeightFish", 3), - PRESET_ENTRY_S32("gClimbSpeed", 4), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 4), PRESET_ENTRY_S32("gCosmetics.Goron_NeckLength", 1000), - PRESET_ENTRY_S32("gCreditsFix", 1), - PRESET_ENTRY_S32("gCustomizeFishing", 1), - PRESET_ENTRY_S32("gDampeAllNight", 1), - PRESET_ENTRY_S32("gDayGravePull", 1), - PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), - PRESET_ENTRY_S32("gDpadNoDropOcarinaInput", 1), - PRESET_ENTRY_S32("gEquipmentCanBeRemoved", 1), - PRESET_ENTRY_S32("gFastBoomerang", 1), - PRESET_ENTRY_S32("gFastChests", 1), - PRESET_ENTRY_S32("gFastDrops", 1), - PRESET_ENTRY_S32("gFastFarores", 1), - PRESET_ENTRY_S32("gFastOcarinaPlayback", 1), - PRESET_ENTRY_S32("gFasterBlockPush", 5), - PRESET_ENTRY_S32("gFasterHeavyBlockLift", 1), - PRESET_ENTRY_S32("gFishNeverEscape", 1), - PRESET_ENTRY_S32("gForgeTime", 0), - PRESET_ENTRY_S32("gGoronPot", 1), - PRESET_ENTRY_S32("gGuaranteeFishingBite", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DayGravePull"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FishNeverEscape"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1), PRESET_ENTRY_S32("gHideBuildInfo", 1), - PRESET_ENTRY_S32("gInjectItemCounts", 1), - PRESET_ENTRY_S32("gInstantFishing", 1), - PRESET_ENTRY_S32("gInstantPutaway", 1), - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), - PRESET_ENTRY_S32("gMarketSneak", 1), - PRESET_ENTRY_S32("gMaskSelect", 1), - PRESET_ENTRY_S32("gMweepSpeed", 5), - PRESET_ENTRY_S32("gNoForcedNavi", 1), - PRESET_ENTRY_S32("gNoInputForCredits", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantFishing"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MarketSneak"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 5), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), PRESET_ENTRY_S32("gPauseAnyCursor", 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1), @@ -1029,16 +1029,16 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1), - PRESET_ENTRY_S32("gSeparateArrows", 1), - PRESET_ENTRY_S32("gSkipScarecrow", 1), - PRESET_ENTRY_S32("gSkulltulaFreeze", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), }; const std::vector s6PresetEntries = { - PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", CSMC_BOTH), - PRESET_ENTRY_S32("gFastChests", 1), - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), - PRESET_ENTRY_S32("gAdultBunnyHood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_BOTH), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 4), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN), @@ -1069,10 +1069,10 @@ const std::vector s6PresetEntries = { }; const std::vector hellModePresetEntries = { - PRESET_ENTRY_S32("gChestSizeAndTextureMatchesContents", CSMC_BOTH), - PRESET_ENTRY_S32("gFastChests", 1), - PRESET_ENTRY_S32("gMMBunnyHood", BUNNY_HOOD_FAST), - PRESET_ENTRY_S32("gAdultBunnyHood", 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_BOTH), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultBunnyHood"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE), diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 9d747c063..ba8aab9fb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -459,7 +459,7 @@ bool HasItemBeenCollected(RandomizerCheck rc) { case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER: // Gravedigger has a fix in place that means one of two save locations. Check both. return (gSaveContext.itemGetInf[1] & 0x1000) || // vanilla flag - ((IS_RANDO || CVarGetInteger("gGravediggingTourFix", 0)) && + ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("GravediggingTourFix"), 0)) && gSaveContext.sceneFlags[scene].collect & (1 << flag) || (gPlayState->actorCtx.flags.collect & (1 << flag))); // rando/fix flag default: return false; diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index bf1eaa8e1..d5a23b7ff 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -394,7 +394,7 @@ void Entrance_SetSavewarpEntrance(void) { gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0 } else if (scene == SCENE_LINKS_HOUSE) { gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); - } else if (CVarGetInteger("gRememberSaveLocation", 0) && scene != SCENE_FAIRYS_FOUNTAIN && scene != SCENE_GROTTOS && + } else if (CVarGetInteger(CVAR_ENHANCEMENT("RememberSaveLocation"), 0) && scene != SCENE_FAIRYS_FOUNTAIN && scene != SCENE_GROTTOS && gSaveContext.entranceIndex != ENTR_LOAD_OPENING) { // Use the saved entrance value with remember save location, except when in grottos/fairy fountains or if // the entrance index is -1 (new save) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index f5d504afa..5b0ef431d 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2597,7 +2597,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { - if (CVarGetInteger("gInjectItemCounts", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts"), 0) != 0) { // The freeze text cannot be manually dismissed and must be auto-dismissed. // This is fine and even wanted when skull tokens are not shuffled, but when // when they are shuffled we don't want to be able to manually dismiss the box. @@ -2605,7 +2605,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { // animation until the text box auto-dismisses. // RANDOTODO: Implement a way to determine if an item came from a skulltula and // inject the auto-dismiss control code if it did. - if (CVarGetInteger("gSkulltulaFreeze", 0) != 0 && + if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) { textId = TEXT_GS_NO_FREEZE; } else { @@ -2618,18 +2618,18 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry.Replace("{{gsCount}}", std::to_string(gsCount)); } } - if (textId == TEXT_HEART_CONTAINER && CVarGetInteger("gInjectItemCounts", 0)) { + if (textId == TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER); messageEntry.Replace("{{heartContainerCount}}", std::to_string(gSaveContext.sohStats.heartContainers + 1)); } - if (textId == TEXT_HEART_PIECE && CVarGetInteger("gInjectItemCounts", 0)) { + if (textId == TEXT_HEART_PIECE && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE); messageEntry.Replace("{{heartPieceCount}}", std::to_string(gSaveContext.sohStats.heartPieces + 1)); } - if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { + if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT); } - if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger("gQuitFishingAtDoor", 0)) { + if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE); } font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 2169e3d02..b577caee5 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -566,30 +566,30 @@ void DrawEnhancementsMenu() { ImGui::Text("Speed-ups:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true); - UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true); + UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", CVAR_ENHANCEMENT("TextSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementCheckbox("Skip Text", CVAR_ENHANCEMENT("SkipText"), false, true); UIWidgets::Tooltip("Holding down B skips text"); - UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true); - UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false); + UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", CVAR_ENHANCEMENT("MweepSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", CVAR_ENHANCEMENT("ClimbSpeed"), 0, 12, "", 0, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", CVAR_ENHANCEMENT("FasterBlockPush"), 0, 5, "", 0, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", CVAR_ENHANCEMENT("FasterHeavyBlockLift"), false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); - UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", CVAR_ENHANCEMENT("FastDrops"), true, false); UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); - UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", CVAR_ENHANCEMENT("FastOcarinaPlayback"), true, false); UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", CVAR_ENHANCEMENT("InstantScarecrow"), true, false, forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); - UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", CVAR_ENHANCEMENT("SkipArrowAnimation"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", CVAR_ENHANCEMENT("SkipSaveConfirmation"), true, false); UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); - UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false); + UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", CVAR_ENHANCEMENT("FastFarores"), true, false); UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); - UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), true, false); UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); ImGui::TableNextColumn(); @@ -597,27 +597,27 @@ void DrawEnhancementsMenu() { ImGui::Text("Changes:"); UIWidgets::PaddedSeparator(); - UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", CVAR_ENHANCEMENT("ForgeTime"), 0, 3, "", 3, true, false, true); UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); - UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); + UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", CVAR_ENHANCEMENT("RememberSaveLocation"), false, false); UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" "This doesn't work if the save was made in grottos/fairy fountains or dungeons."); - UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); + UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", CVAR_ENHANCEMENT("NoForcedNavi"), true, false); UIWidgets::Tooltip("Prevent forced Navi conversations"); - UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false); + UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", CVAR_ENHANCEMENT("ResetNaviTimer"), true, false); UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. "); - UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); + UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", CVAR_ENHANCEMENT("SkulltulaFreeze"), true, false); UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); - UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false); + UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), true, false); UIWidgets::Tooltip("Nighttime Skulltulas will spawn during both day and night."); - UIWidgets::PaddedEnhancementCheckbox("Dampe Appears All Night", "gDampeAllNight", true, false); + UIWidgets::PaddedEnhancementCheckbox("Dampe Appears All Night", CVAR_ENHANCEMENT("DampeAllNight"), true, false); UIWidgets::Tooltip("Makes Dampe appear anytime during the night, not just his usual working hours."); - UIWidgets::PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fast Chests", CVAR_ENHANCEMENT("FastChests"), true, false); UIWidgets::Tooltip("Kick open every chest"); UIWidgets::PaddedText("Chest size & texture matches contents", true, false); - if (UIWidgets::EnhancementCombobox("gChestSizeAndTextureMatchesContents", chestStyleMatchesContentsOptions, CSMC_DISABLED)) { - if (CVarGetInteger("gChestSizeAndTextureMatchesContents", CSMC_DISABLED) == CSMC_DISABLED) { - CVarSetInteger("gChestSizeDependsStoneOfAgony", 0); + if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), chestStyleMatchesContentsOptions, CSMC_DISABLED)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED) == CSMC_DISABLED) { + CVarSetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); } } UIWidgets::Tooltip( @@ -631,24 +631,24 @@ void DrawEnhancementsMenu() { "\n" "NOTE: Textures will not apply if you are using a mod pack with a custom chest model." ); - if (CVarGetInteger("gChestSizeAndTextureMatchesContents", CSMC_DISABLED) != CSMC_DISABLED) { - UIWidgets::PaddedEnhancementCheckbox("Chests of Agony", "gChestSizeDependsStoneOfAgony", true, false); + if (CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED) != CSMC_DISABLED) { + UIWidgets::PaddedEnhancementCheckbox("Chests of Agony", CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), true, false); UIWidgets::Tooltip("Only change the size/texture of chests if you have the Stone of Agony."); } - UIWidgets::PaddedEnhancementCheckbox("Ask to Equip New Items", "gAskToEquip", true, false); + UIWidgets::PaddedEnhancementCheckbox("Ask to Equip New Items", CVAR_ENHANCEMENT("AskToEquip"), true, false); UIWidgets::Tooltip("Adds a prompt to equip newly-obtained swords, shields and tunics"); - UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); + UIWidgets::PaddedEnhancementCheckbox("Better Owl", CVAR_ENHANCEMENT("BetterOwl"), true, false); UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); - UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", "gMarketSneak", true, false); + UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", CVAR_ENHANCEMENT("MarketSneak"), true, false); UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate."); - UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", "gEnhancements.OpenAllHours", true, false); + UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", CVAR_ENHANCEMENT("OpenAllHours"), true, false); UIWidgets::Tooltip("Shops and minigames are open both day and night. Requires scene reload to take effect."); - UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false); + UIWidgets::PaddedEnhancementCheckbox("Link as default file name", CVAR_ENHANCEMENT("LinkDefaultName"), true, false); UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name"); - UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", "gQuitFishingAtDoor", true, false); + UIWidgets::PaddedEnhancementCheckbox("Quit Fishing At Door", CVAR_ENHANCEMENT("QuitFishingAtDoor"), true, false); UIWidgets::Tooltip("Fisherman asks if you want to quit at the door when you still have the rod"); UIWidgets::PaddedText("Time Travel with the Song of Time", true, false); - UIWidgets::EnhancementCombobox("gTimeTravel", timeTravelOptions, 0); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("TimeTravel"), timeTravelOptions, 0); UIWidgets::Tooltip("Allows Link to freely change age by playing the Song of Time.\n" "Time Blocks can still be used properly.\n\n" "Requirements:\n" @@ -657,7 +657,7 @@ void DrawEnhancementsMenu() { "- Obtained the Master Sword\n" "- Not within range of Time Block\n" "- Not within range of Ocarina playing spots"); - UIWidgets::PaddedEnhancementCheckbox("Pause Warp", "gPauseWarp", true, false); + UIWidgets::PaddedEnhancementCheckbox("Pause Warp", CVAR_ENHANCEMENT("PauseWarp"), true, false); UIWidgets::Tooltip("Selection of warp song in pause menu initiates warp. Disables song playback."); ImGui::EndTable(); @@ -668,41 +668,41 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Items")) { - UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); + UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", CVAR_ENHANCEMENT("InstantPutaway"), true, false); UIWidgets::Tooltip("Allow Link to put items away without having to wait around"); - UIWidgets::PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); + UIWidgets::PaddedEnhancementCheckbox("Instant Boomerang Recall", CVAR_ENHANCEMENT("FastBoomerang"), true, false); UIWidgets::Tooltip("Instantly return the boomerang to Link by pressing its item button while it's in the air"); - UIWidgets::PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput", true, false); + UIWidgets::PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), true, false); UIWidgets::Tooltip("Prevent dropping inputs when playing the ocarina quickly"); UIWidgets::PaddedText("Bunny Hood Effect", true, false); - UIWidgets::EnhancementCombobox("gMMBunnyHood", bunnyHoodOptions, BUNNY_HOOD_VANILLA); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("MMBunnyHood"), bunnyHoodOptions, BUNNY_HOOD_VANILLA); UIWidgets::Tooltip( "Wearing the Bunny Hood grants a speed increase like in Majora's Mask. The longer jump option is not accounted for in randomizer logic.\n\n" "Also disables NPC's reactions to wearing the Bunny Hood." ); - UIWidgets::PaddedEnhancementCheckbox("Bunny Hood Equippable as Adult", "gAdultBunnyHood", true, false, (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_VANILLA), "Only available with increased bunny hood speed", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Bunny Hood Equippable as Adult", CVAR_ENHANCEMENT("AdultBunnyHood"), true, false, (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_VANILLA), "Only available with increased bunny hood speed", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("Allows the bunny hood to be equipped normally from the pause menu as adult."); - UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false); + UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", CVAR_ENHANCEMENT("MaskSelect"), true, false); UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); - UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false); + UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", CVAR_ENHANCEMENT("NutsExplodeBombs"), true, false); UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers."); - UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false); + UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", CVAR_ENHANCEMENT("SeparateArrows"), true, false); UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots. (Note this will disable the behaviour of the 'Equip Dupe' glitch)"); - UIWidgets::PaddedEnhancementCheckbox("Bow as Child/Slingshot as Adult", "gBowSlingShotAmmoFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Bow as Child/Slingshot as Adult", CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), true, false); UIWidgets::Tooltip("Allows child to use bow with arrows.\nAllows adult to use slingshot with seeds.\n\nRequires glitches or 'Timeless Equipment' cheat to equip."); - UIWidgets::PaddedEnhancementCheckbox("Better Farore's Wind", "gBetterFW", true, false); + UIWidgets::PaddedEnhancementCheckbox("Better Farore's Wind", CVAR_ENHANCEMENT("BetterFarore"), true, false); UIWidgets::Tooltip("Helps FW persist between ages, gives child and adult separate FW points, and can be used in more places."); - UIWidgets::PaddedEnhancementCheckbox("Remove Explosive Limit", "gRemoveExplosiveLimit", true, false); + UIWidgets::PaddedEnhancementCheckbox("Remove Explosive Limit", CVAR_ENHANCEMENT("RemoveExplosiveLimit"), true, false); UIWidgets::Tooltip("Removes the cap of 3 active explosives being deployed at once."); - UIWidgets::PaddedEnhancementCheckbox("Static Explosion Radius", "gStaticExplosionRadius", true, false); + UIWidgets::PaddedEnhancementCheckbox("Static Explosion Radius", CVAR_ENHANCEMENT("StaticExplosionRadius"), true, false); UIWidgets::Tooltip("Explosions are now a static size, like in Majora's Mask and OoT3D. Makes bombchu hovering much easier."); - UIWidgets::PaddedEnhancementCheckbox("Prevent Bombchus Forcing First-Person", "gDisableFirstPersonChus", true, false); + UIWidgets::PaddedEnhancementCheckbox("Prevent Bombchus Forcing First-Person", CVAR_ENHANCEMENT("DisableFirstPersonChus"), true, false); UIWidgets::Tooltip("Prevent bombchus from forcing the camera into first-person mode when released."); - UIWidgets::PaddedEnhancementCheckbox("Aiming reticle for the bow/slingshot", "gBowReticle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Aiming reticle for the bow/slingshot", CVAR_ENHANCEMENT("BowReticle"), true, false); UIWidgets::Tooltip("Aiming with a bow or slingshot will display a reticle as with the hookshot when the projectile is ready to fire."); - if (UIWidgets::PaddedEnhancementCheckbox("Allow strength equipment to be toggled", "gToggleStrength", true, false)) { - if (!CVarGetInteger("gToggleStrength", 0)) { - CVarSetInteger("gStrengthDisabled", 0); + if (UIWidgets::PaddedEnhancementCheckbox("Allow strength equipment to be toggled", CVAR_ENHANCEMENT("ToggleStrength"), true, false)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0)) { + CVarSetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0); } } UIWidgets::Tooltip("Allows strength to be toggled on and off by pressing A on the strength upgrade in the equipment subscreen of the pause menu (This allows performing some glitches that require the player to not have strength)."); @@ -715,86 +715,86 @@ void DrawEnhancementsMenu() { { if (ImGui::BeginMenu("Potion Values")) { - UIWidgets::EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); + UIWidgets::EnhancementCheckbox("Change Red Potion Effect", CVAR_ENHANCEMENT("RedPotionEffect")); UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Red Potions"); - bool disabledRedPotion = !CVarGetInteger("gRedPotionEffect", 0); + bool disabledRedPotion = !CVarGetInteger(CVAR_ENHANCEMENT("RedPotionEffect"), 0); static const char* disabledTooltipRedPotion = "This option is disabled because \"Change Red Potion Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true, disabledRedPotion, disabledTooltipRedPotion); + UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", CVAR_ENHANCEMENT("RedPotionHealth"), 1, 100, "", 0, true, disabledRedPotion, disabledTooltipRedPotion); UIWidgets::Tooltip("Changes the amount of health restored by Red Potions"); - UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore", disabledRedPotion, disabledTooltipRedPotion); + UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", CVAR_ENHANCEMENT("RedPercentRestore"), disabledRedPotion, disabledTooltipRedPotion); UIWidgets::Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); + UIWidgets::EnhancementCheckbox("Change Green Potion Effect", CVAR_ENHANCEMENT("GreenPotionEffect")); UIWidgets::Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); - bool disabledGreenPotion = !CVarGetInteger("gGreenPotionEffect", 0); + bool disabledGreenPotion = !CVarGetInteger(CVAR_ENHANCEMENT("GreenPotionEffect"), 0); static const char* disabledTooltipGreenPotion = "This option is disabled because \"Change Green Potion Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true, disabledGreenPotion, disabledTooltipGreenPotion); + UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", CVAR_ENHANCEMENT("GreenPotionMana"), 1, 100, "", 0, true, disabledGreenPotion, disabledTooltipGreenPotion); UIWidgets::Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); - UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore", disabledGreenPotion, disabledTooltipGreenPotion); + UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", CVAR_ENHANCEMENT("GreenPercentRestore"), disabledGreenPotion, disabledTooltipGreenPotion); UIWidgets::Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); + UIWidgets::EnhancementCheckbox("Change Blue Potion Effects", CVAR_ENHANCEMENT("BluePotionEffects")); UIWidgets::Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); - bool disabledBluePotion = !CVarGetInteger("gBluePotionEffects", 0); + bool disabledBluePotion = !CVarGetInteger(CVAR_ENHANCEMENT("BluePotionEffects"), 0); static const char* disabledTooltipBluePotion = "This option is disabled because \"Change Blue Potion Effects\" is turned off"; - UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion); + UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", CVAR_ENHANCEMENT("BluePotionHealth"), 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion); UIWidgets::Tooltip("Changes the amount of health restored by Blue Potions"); - UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore", disabledBluePotion, disabledTooltipBluePotion); + UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", CVAR_ENHANCEMENT("BlueHealthPercentRestore"), disabledBluePotion, disabledTooltipBluePotion); UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); ImGui::Separator(); - UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion); + UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", CVAR_ENHANCEMENT("BluePotionMana"), 1, 100, "", 0, true, disabledBluePotion, disabledTooltipBluePotion); UIWidgets::Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); - UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore", disabledBluePotion, disabledTooltipBluePotion); + UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", CVAR_ENHANCEMENT("BlueManaPercentRestore"), disabledBluePotion, disabledTooltipBluePotion); UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); + UIWidgets::EnhancementCheckbox("Change Milk Effect", CVAR_ENHANCEMENT("MilkEffect")); UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Milk"); - bool disabledMilk = !CVarGetInteger("gMilkEffect", 0); + bool disabledMilk = !CVarGetInteger(CVAR_ENHANCEMENT("MilkEffect"), 0); static const char* disabledTooltipMilk = "This option is disabled because \"Change Milk Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true, disabledMilk, disabledTooltipMilk); + UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", CVAR_ENHANCEMENT("MilkHealth"), 1, 100, "", 0, true, disabledMilk, disabledTooltipMilk); UIWidgets::Tooltip("Changes the amount of health restored by Milk"); - UIWidgets::EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore", disabledMilk, disabledTooltipMilk); + UIWidgets::EnhancementCheckbox("Milk Percent Restore", CVAR_ENHANCEMENT("MilkPercentRestore"), disabledMilk, disabledTooltipMilk); UIWidgets::Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect", disabledMilk, disabledTooltipMilk); + UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", CVAR_ENHANCEMENT("SeparateHalfMilkEffect"), disabledMilk, disabledTooltipMilk); UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); - bool disabledHalfMilk = disabledMilk || !CVarGetInteger("gSeparateHalfMilkEffect", 0); + bool disabledHalfMilk = disabledMilk || !CVarGetInteger(CVAR_ENHANCEMENT("SeparateHalfMilkEffect"), 0); static const char* disabledTooltipHalfMilk = "This option is disabled because \"Separate Half Milk Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true, disabledHalfMilk, disabledTooltipHalfMilk); + UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", CVAR_ENHANCEMENT("HalfMilkHealth"), 1, 100, "", 0, true, disabledHalfMilk, disabledTooltipHalfMilk); UIWidgets::Tooltip("Changes the amount of health restored by Half Milk"); - UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore", disabledHalfMilk, disabledTooltipHalfMilk); + UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", CVAR_ENHANCEMENT("HalfMilkPercentRestore"), disabledHalfMilk, disabledTooltipHalfMilk); UIWidgets::Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); + UIWidgets::EnhancementCheckbox("Change Fairy Effect", CVAR_ENHANCEMENT("FairyEffect")); UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairies"); - bool disabledFairy = !CVarGetInteger("gFairyEffect", 0); + bool disabledFairy = !CVarGetInteger(CVAR_ENHANCEMENT("FairyEffect"), 0); static const char* disabledTooltipFairy = "This option is disabled because \"Change Fairy Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true, disabledFairy, disabledTooltipFairy); + UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", CVAR_ENHANCEMENT("FairyHealth"), 1, 100, "", 0, true, disabledFairy, disabledTooltipFairy); UIWidgets::Tooltip("Changes the amount of health restored by Fairies"); - UIWidgets::EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore", disabledFairy, disabledTooltipFairy); + UIWidgets::EnhancementCheckbox("Fairy Percent Restore", CVAR_ENHANCEMENT("FairyPercentRestore"), disabledFairy, disabledTooltipFairy); UIWidgets::Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); ImGui::Separator(); - UIWidgets::EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); + UIWidgets::EnhancementCheckbox("Change Fairy Revive Effect", CVAR_ENHANCEMENT("FairyReviveEffect")); UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); - bool disabledFairyRevive = !CVarGetInteger("gFairyReviveEffect", 0); + bool disabledFairyRevive = !CVarGetInteger(CVAR_ENHANCEMENT("FairyReviveEffect"), 0); static const char* disabledTooltipFairyRevive = "This option is disabled because \"Change Fairy Revive Effect\" is turned off"; - UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true, disabledFairyRevive, disabledTooltipFairyRevive); + UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", CVAR_ENHANCEMENT("FairyReviveHealth"), 1, 100, "", 0, true, disabledFairyRevive, disabledTooltipFairyRevive); UIWidgets::Tooltip("Changes the amount of health restored by Fairy Revivals"); - UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore", disabledFairyRevive, disabledTooltipFairyRevive); + UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", CVAR_ENHANCEMENT("FairyRevivePercentRestore"), disabledFairyRevive, disabledTooltipFairyRevive); UIWidgets::Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); ImGui::EndMenu(); @@ -803,17 +803,17 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); if (ImGui::BeginMenu("Shooting Gallery")) { - UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeShootingGallery"); + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeShootingGallery")); UIWidgets::Tooltip("Turn on/off changes to the shooting gallery behavior"); - bool disabled = !CVarGetInteger("gCustomizeShootingGallery", 0); + bool disabled = !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0); static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off"; - UIWidgets::PaddedEnhancementCheckbox("Instant Win", "gInstantShootingGalleryWin", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Instant Win", CVAR_ENHANCEMENT("InstantShootingGalleryWin"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Skips the shooting gallery minigame"); - UIWidgets::PaddedEnhancementCheckbox("No Rupee Randomization", "gConstantAdultGallery", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("No Rupee Randomization", CVAR_ENHANCEMENT("ConstantAdultGallery"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Forces the rupee order to not be randomized as adult, making it the same as chlid"); - UIWidgets::PaddedEnhancementSliderInt("Child Starting Ammunition: %d", "##cShootingGalleryAmmunition", "gChildShootingGalleryAmmunition", 10, 30, "", 15, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Child Starting Ammunition: %d", "##cShootingGalleryAmmunition", CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 10, 30, "", 15, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The ammunition at the start of the shooting gallery minigame as a child"); - UIWidgets::PaddedEnhancementSliderInt("Adult Starting Ammunition: %d", "##aShootingGalleryAmmunition", "gAdultShootingGalleryAmmunition", 10, 30, "", 15, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Adult Starting Ammunition: %d", "##aShootingGalleryAmmunition", CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), 10, 30, "", 15, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The ammunition at the start of the shooting gallery minigame as an adult"); ImGui::EndMenu(); } @@ -821,15 +821,15 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); if (ImGui::BeginMenu("Bombchu Bowling")) { - UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeBombchuBowling"); + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeBombchuBowling")); UIWidgets::Tooltip("Turn on/off changes to the bombchu bowling behavior"); - bool disabled = CVarGetInteger("gCustomizeBombchuBowling", 0) == 0; + bool disabled = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) == 0; static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off"; - UIWidgets::PaddedEnhancementCheckbox("Remove Small Cucco", "gBombchuBowlingNoSmallCucco", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Remove Small Cucco", CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Prevents the small cucco from appearing in the bombchu bowling minigame"); - UIWidgets::PaddedEnhancementCheckbox("Remove Big Cucco", "gBombchuBowlingNoBigCucco", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Remove Big Cucco", CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Prevents the big cucco from appearing in the bombchu bowling minigame"); - UIWidgets::PaddedEnhancementSliderInt("Bombchu Count: %d", "##cBombchuBowlingAmmunition", "gBombchuBowlingAmmunition", 3, 20, "", 10, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Bombchu Count: %d", "##cBombchuBowlingAmmunition", CVAR_ENHANCEMENT("BombchuBowlingAmmo"), 3, 20, "", 10, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The number of bombchus available at the start of the bombchu bowling minigame"); ImGui::EndMenu(); } @@ -837,51 +837,51 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); if (ImGui::BeginMenu("Fishing")) { - UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeFishing"); + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeFishing")); UIWidgets::Tooltip("Turn on/off changes to the fishing behavior"); - bool disabled = !CVarGetInteger("gCustomizeFishing", 0); + bool disabled = !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0); static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off"; - UIWidgets::PaddedEnhancementCheckbox("Instant Fishing", "gInstantFishing", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Instant Fishing", CVAR_ENHANCEMENT("InstantFishing"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("All fish will be caught instantly"); - UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", CVAR_ENHANCEMENT("GuaranteeFishingBite"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); - UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", CVAR_ENHANCEMENT("FishNeverEscape"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Once a hook has been set, fish will never let go while being reeled in."); - UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3, 10, "", 10, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child"); - UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6, 13, "", 13, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); ImGui::EndMenu(); } UIWidgets::Spacer(0); if (ImGui::BeginMenu("Lost Woods Ocarina Game")) { - UIWidgets::EnhancementCheckbox("Customize Behavior", "gCustomizeOcarinaGame"); + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeOcarinaGame")); UIWidgets::Tooltip("Turn on/off changes to the lost woods ocarina game behavior"); - bool disabled = !CVarGetInteger("gCustomizeOcarinaGame", 0); + bool disabled = !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0); static const char* disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off"; - UIWidgets::PaddedEnhancementCheckbox("Instant Win", "gInstantOcarinaGameWin", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Instant Win", CVAR_ENHANCEMENT("InstantOcarinaGameWin"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Skips the lost woods ocarina game"); - UIWidgets::PaddedEnhancementSliderInt("Note Play Speed: %dx", "##OcarinaGameNoteSpeed", "gOcarinaGameNoteSpeed", 1, 5, "", 1, true, true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementSliderInt("Note Play Speed: %dx", "##OcarinaGameNoteSpeed", CVAR_ENHANCEMENT("OcarinaGame.NoteSpeed"), 1, 5, "", 1, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Adjust the speed that the skull kids play notes"); - UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", "gOcarinaUnlimitedFailTime", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", CVAR_ENHANCEMENT("OcarinaUnlimitedFailTime"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Removes the timer to play back the song"); - UIWidgets::PaddedEnhancementSliderInt("Number of Starting Notes: %d", "##OcarinaGameStartingNotes", "gOcarinaGameStartingNotes", 1, 8, "", 3, true, true, false, + UIWidgets::PaddedEnhancementSliderInt("Number of Starting Notes: %d", "##OcarinaGameStartingNotes", CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 1, 8, "", 3, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Adjust the number of notes the skull kids play to start the first round"); - int roundMin = CVarGetInteger("gOcarinaGameStartingNotes", 3); + int roundMin = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 3); UIWidgets::PaddedEnhancementSliderInt("Round One Notes: %d", "##OcarinaGameRoundOne", - "gOcarinaGameRoundOneNotes", roundMin, 8, "", 5, true, true, + CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), roundMin, 8, "", 5, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Adjust the number of notes you need to play to end the first round"); UIWidgets::PaddedEnhancementSliderInt("Round Two Notes: %d", "##OcarinaGameRoundTwoNotes", - "gOcarinaGameRoundTwoNotes", roundMin, 8, "", 6, true, true, + CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), roundMin, 8, "", 6, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Adjust the number of notes you need to play to end the second round"); UIWidgets::PaddedEnhancementSliderInt("Round Three Notes: %d", "##OcarinaGameRoundThreeNotes", - "gOcarinaGameRoundThreeNotes", roundMin, 8, "", 8, true, true, + CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), roundMin, 8, "", 8, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Adjust the number of notes you need to play to end the third round"); @@ -890,16 +890,16 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", "gDeleteFileOnDeath", true, false); + UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", CVAR_ENHANCEMENT("DeleteFileOnDeath"), true, false); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); UIWidgets::Tooltip("Dying will delete your file\n\n " ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSABLE\nUSE AT YOUR OWN RISK!"); ImGui::PopStyleColor(); - if (UIWidgets::PaddedEnhancementCheckbox("Permanent heart loss", "gPermanentHeartLoss", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Permanent heart loss", CVAR_ENHANCEMENT("PermanentHeartLoss"), true, false)) { UpdatePermanentHeartLossState(); } UIWidgets::Tooltip("When you lose 4 quarters of a heart you will permanently lose that heart container.\n\nDisabling this after the fact will restore your heart containers."); ImGui::Text("Damage Multiplier"); - UIWidgets::EnhancementCombobox("gDamageMul", allPowers, 0); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("DamageMult"), allPowers, 0); UIWidgets::Tooltip( "Modifies all sources of damage not affected by other sliders\n" "2x: Can survive all common attacks from the start of the game\n" @@ -912,7 +912,7 @@ void DrawEnhancementsMenu() { "256x: Cannot survive damage" ); UIWidgets::PaddedText("Fall Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gFallDamageMul", subPowers, 0); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("FallDamageMult"), subPowers, 0); UIWidgets::Tooltip( "Modifies all fall damage\n" "2x: Can survive all fall damage from the start of the game\n" @@ -924,7 +924,7 @@ void DrawEnhancementsMenu() { "128x: Cannot survive fall damage" ); UIWidgets::PaddedText("Void Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gVoidDamageMul", subSubPowers, 0); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("VoidDamageMult"), subSubPowers, 0); UIWidgets::Tooltip( "Modifies damage taken after falling into a void\n" "2x: Can survive void damage from the start of the game\n" @@ -935,41 +935,41 @@ void DrawEnhancementsMenu() { "64x: Cannot survive void damage" ); UIWidgets::PaddedText("Bonk Damage Multiplier", true, false); - UIWidgets::EnhancementCombobox("gBonkDamageMul", bonkDamageValues, BONK_DAMAGE_NONE); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("BonkDamageMult"), bonkDamageValues, BONK_DAMAGE_NONE); UIWidgets::Tooltip("Modifies damage taken after bonking."); - UIWidgets::PaddedEnhancementCheckbox("Spawn with full health", "gFullHealthSpawn", true, false); + UIWidgets::PaddedEnhancementCheckbox("Spawn with full health", CVAR_ENHANCEMENT("FullHealthSpawn"), true, false); UIWidgets::Tooltip("Respawn with full health instead of 3 Hearts"); - UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); + UIWidgets::PaddedEnhancementCheckbox("No Random Drops", CVAR_ENHANCEMENT("NoRandomDrops"), true, false); UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); bool forceEnableBombchuDrops = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1; static const char* forceEnableBombchuDropsText = "This setting is forcefully enabled because a savefile\nwith \"Enable Bombchu Drops\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false, + UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", CVAR_ENHANCEMENT("BombchuDrops"), true, false, forceEnableBombchuDrops, forceEnableBombchuDropsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); - UIWidgets::PaddedEnhancementCheckbox("Trees Drop Sticks", "gTreeStickDrops", true, false); + UIWidgets::PaddedEnhancementCheckbox("Trees Drop Sticks", CVAR_ENHANCEMENT("TreesDropSticks"), true, false); UIWidgets::Tooltip("Bonking into trees will have a chance to drop up to 3 sticks. Must already have obtained sticks."); - UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); + UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", CVAR_ENHANCEMENT("NoHeartDrops"), true, false); UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); - if (UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", "gHyperBosses", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Hyper Bosses", CVAR_ENHANCEMENT("HyperBosses"), true, false)) { UpdateHyperBossesState(); } UIWidgets::Tooltip("All major bosses move and act twice as fast."); - if (UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", "gHyperEnemies", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Hyper Enemies", CVAR_ENHANCEMENT("HyperEnemies"), true, false)) { UpdateHyperEnemiesState(); } UIWidgets::Tooltip("All regular enemies and mini-bosses move and act twice as fast."); - UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); + UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", CVAR_ENHANCEMENT("GoronPot"), true, false); UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); - UIWidgets::PaddedEnhancementCheckbox("Always Win Dampe Digging Game", "gDampeWin", true, false, SaveManager::Instance->IsRandoFile(), + UIWidgets::PaddedEnhancementCheckbox("Always Win Dampe Digging Game", CVAR_ENHANCEMENT("DampeWin"), true, false, SaveManager::Instance->IsRandoFile(), "This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Always win the heart piece/purple rupee on the first dig in Dampe's grave digging game, just like in rando\nIn a rando file, this is unconditionally enabled"); - UIWidgets::PaddedEnhancementCheckbox("All Dogs are Richard", "gAllDogsRichard", true, false); + UIWidgets::PaddedEnhancementCheckbox("All Dogs are Richard", CVAR_ENHANCEMENT("AllDogsRichard"), true, false); UIWidgets::Tooltip("All dogs can be traded in and will count as Richard."); - UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", "gCuccoStayDurationMultiplier", 1, 5, "", 1, true, true, false); + UIWidgets::PaddedEnhancementSliderInt("Cuccos Stay Put Multiplier: %dx", "##CuccoStayDurationMultiplier", CVAR_ENHANCEMENT("CuccoStayDurationMult"), 1, 5, "", 1, true, true, false); UIWidgets::Tooltip("Cuccos will stay in place longer after putting them down, by a multiple of the value of the slider."); - UIWidgets::PaddedEnhancementSliderInt("Leever Spawn Rate: %d seconds", "##LeeverSpawnRate", "gEnhancements.LeeverSpawnRate", 0, 10, "", 0, true, true, false); + UIWidgets::PaddedEnhancementSliderInt("Leever Spawn Rate: %d seconds", "##LeeverSpawnRate", CVAR_ENHANCEMENT("LeeverSpawnRate"), 0, 10, "", 0, true, true, false); UIWidgets::Tooltip("The time between leever groups spawning."); ImGui::EndMenu(); @@ -979,15 +979,15 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Reduced Clutter")) { - UIWidgets::EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); + UIWidgets::EnhancementCheckbox("Mute Low HP Alarm", CVAR_ENHANCEMENT("LowHpAlarm")); UIWidgets::Tooltip("Disable the low HP beeping sound"); - UIWidgets::PaddedEnhancementCheckbox("Minimal UI", "gMinimalUI", true, false); + UIWidgets::PaddedEnhancementCheckbox("Minimal UI", CVAR_ENHANCEMENT("MinimalUI"), true, false); UIWidgets::Tooltip("Hides most of the UI when not needed\nNote: Doesn't activate until after loading a new scene"); - UIWidgets::PaddedEnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Navi Call Audio", CVAR_ENHANCEMENT("DisableNaviCallAudio"), true, false); UIWidgets::Tooltip("Disables the voice audio when Navi calls you"); - UIWidgets::PaddedEnhancementCheckbox("Disable Hot/Underwater Warning Text", "gDisableTunicWarningText", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Hot/Underwater Warning Text", CVAR_ENHANCEMENT("DisableTunicWarningText"), true, false); UIWidgets::Tooltip("Disables warning text when you don't have on the Goron/Zora Tunic in Hot/Underwater conditions."); - UIWidgets::PaddedEnhancementCheckbox("Remember Minimap State Between Areas", "gEnhancements.RememberMapToggleState"); + UIWidgets::PaddedEnhancementCheckbox("Remember Minimap State Between Areas", CVAR_ENHANCEMENT("RememberMapToggleState")); UIWidgets::Tooltip("Preserves the minimap visibility state when going between areas rather than defaulting it to \"on\" when going through loading zones."); ImGui::EndMenu(); @@ -995,15 +995,15 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); - UIWidgets::EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); + UIWidgets::EnhancementCheckbox("Visual Stone of Agony", CVAR_ENHANCEMENT("VisualAgony")); UIWidgets::Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); - UIWidgets::PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); + UIWidgets::PaddedEnhancementCheckbox("Assignable Tunics and Boots", CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), true, false); UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons"); - UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); + UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), true, false); UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); - if (CVarGetInteger("gEquipmentCanBeRemoved", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 0)) { UIWidgets::PaddedText("Sword Toggle Options", true, false); - UIWidgets::EnhancementCombobox("gEnhancements.SwordToggle", swordToggleModes, SWORD_TOGGLE_NONE); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("SwordToggle"), swordToggleModes, SWORD_TOGGLE_NONE); UIWidgets::Tooltip( "Introduces Options for unequipping Link's sword\n\n" "None: Only Biggoron's Sword/Giant's Knife can be toggled. Doing so will equip the Master Sword.\n\n" @@ -1012,17 +1012,17 @@ void DrawEnhancementsMenu() { ); } - UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); + UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", CVAR_ENHANCEMENT("CowOfTime"), true, false); UIWidgets::Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); - UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); - UIWidgets::PaddedEnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect", true, false); - UIWidgets::PaddedEnhancementCheckbox("Item counts in messages", "gInjectItemCounts", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", CVAR_ENHANCEMENT("GuardVision"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable passage of time on file select", CVAR_ENHANCEMENT("TimeFlowFileSelect"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Item counts in messages", CVAR_ENHANCEMENT("InjectItemCounts"), true, false); UIWidgets::Tooltip("Injects item counts in pickup messages, like golden skulltula tokens and heart pieces"); - UIWidgets::PaddedEnhancementCheckbox("Pull grave during the day", "gDayGravePull", true, false); + UIWidgets::PaddedEnhancementCheckbox("Pull grave during the day", CVAR_ENHANCEMENT("DayGravePull"), true, false); UIWidgets::Tooltip("Allows graves to be pulled when child during the day"); - UIWidgets::PaddedEnhancementCheckbox("Dogs follow you everywhere", "gDogFollowsEverywhere", true, false); + UIWidgets::PaddedEnhancementCheckbox("Dogs follow you everywhere", CVAR_ENHANCEMENT("DogFollowsEverywhere"), true, false); UIWidgets::Tooltip("Allows dogs to follow you anywhere you go, even if you leave the market"); - UIWidgets::PaddedEnhancementCheckbox("Don't require input for Credits sequence", "gNoInputForCredits", true, false); + UIWidgets::PaddedEnhancementCheckbox("Don't require input for Credits sequence", CVAR_ENHANCEMENT("NoInputForCredits"), true, false); UIWidgets::Tooltip("Removes the input requirement on textboxes after defeating Ganon, allowing Credits sequence to continue to progress"); // Blue Fire Arrows @@ -1030,7 +1030,7 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BLUE_FIRE_ARROWS); static const char* forceEnableBlueFireArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Blue Fire Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", CVAR_ENHANCEMENT("BlueFireArrows"), true, false, forceEnableBlueFireArrows, forceEnableBlueFireArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Ice Arrows to melt red ice.\nMay require a room reload if toggled during gameplay."); @@ -1039,16 +1039,16 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SUNLIGHT_ARROWS); static const char* forceEnableSunLightArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Sunlight Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", CVAR_ENHANCEMENT("SunlightArrows"), true, false, forceEnableSunLightArrows, forceEnableSunLightArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Light Arrows to activate sun switches.\nMay require a room reload if toggled during gameplay."); - UIWidgets::PaddedEnhancementCheckbox("Disable Crit wiggle", "gDisableCritWiggle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Crit wiggle", CVAR_ENHANCEMENT("DisableCritWiggle"), true, false); UIWidgets::Tooltip("Disable random camera wiggle at low health"); - UIWidgets::PaddedEnhancementCheckbox("Enemy Health Bars", "gEnemyHealthBar", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enemy Health Bars", CVAR_ENHANCEMENT("EnemyHealthBar"), true, false); UIWidgets::Tooltip("Renders a health bar for enemies when Z-Targeted"); - UIWidgets::PaddedEnhancementCheckbox("Targetable Hookshot Reticle", "gHookshotableReticle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Targetable Hookshot Reticle", CVAR_ENHANCEMENT("HookshotableReticle"), true, false); UIWidgets::Tooltip("Use a different color when aiming at hookshotable collision"); ImGui::EndMenu(); @@ -1066,13 +1066,13 @@ void DrawEnhancementsMenu() { ToggleAltAssetsAtEndOfFrame = true; } UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not."); - UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", "gDisableBombBillboarding", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", CVAR_ENHANCEMENT("DisableBombBillboarding"), true, false); UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects."); - UIWidgets::PaddedEnhancementCheckbox("Disable Grotto Fixed Rotation", "gDisableGrottoRotation", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Grotto Fixed Rotation", CVAR_ENHANCEMENT("DisableGrottoRotation"), true, false); UIWidgets::Tooltip("Disables grottos rotating with the camera. To be used in conjunction with mods that want to replace grottos with 3D objects."); - UIWidgets::PaddedEnhancementCheckbox("Invisible Bunny Hood", "gHideBunnyHood", true, false); + UIWidgets::PaddedEnhancementCheckbox("Invisible Bunny Hood", CVAR_ENHANCEMENT("HideBunnyHood"), true, false); UIWidgets::Tooltip("Turns Bunny Hood invisible while still maintaining its effects."); - UIWidgets::PaddedEnhancementCheckbox("Disable HUD Heart animations", "gNoHUDHeartAnimation", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable HUD Heart animations", CVAR_ENHANCEMENT("NoHUDHeartAnimation"), true, false); UIWidgets::Tooltip("Disables the beating animation of the hearts on the HUD."); ImGui::EndMenu(); @@ -1082,43 +1082,43 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Animated Link in Pause Menu")) { ImGui::Text("Rotation"); - UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); - UIWidgets::EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 1); + UIWidgets::EnhancementRadioButton("Disabled", CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 0); + UIWidgets::EnhancementRadioButton("Rotate Link with D-pad", CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 1); UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); - UIWidgets::EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 2); + UIWidgets::EnhancementRadioButton("Rotate Link with C-buttons", CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 2); UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); - UIWidgets::EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); + UIWidgets::EnhancementRadioButton("Rotate Link with Right Stick", CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 3); UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the Right Stick\nYou can zoom in by pointing up and reset Link's rotation by pointing down"); - if (CVarGetInteger("gPauseLiveLinkRotation", 0) != 0) { - UIWidgets::EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, "", 1); + if (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 0) != 0) { + UIWidgets::EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", CVAR_ENHANCEMENT("PauseLiveLinkRotationSpeed"), 1, 20, "", 1); } UIWidgets::PaddedSeparator(); ImGui::Text("Static loop"); - UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); - UIWidgets::EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); - UIWidgets::EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); - UIWidgets::EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); - UIWidgets::EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); - UIWidgets::EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); - UIWidgets::EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); - UIWidgets::EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); - UIWidgets::EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); - UIWidgets::EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); - UIWidgets::EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); - UIWidgets::EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); - UIWidgets::EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); - UIWidgets::EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); - UIWidgets::EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); + UIWidgets::EnhancementRadioButton("Disabled", CVAR_ENHANCEMENT("PauseLiveLink"), 0); + UIWidgets::EnhancementRadioButton("Idle (standing)", CVAR_ENHANCEMENT("PauseLiveLink"), 1); + UIWidgets::EnhancementRadioButton("Idle (look around)", CVAR_ENHANCEMENT("PauseLiveLink"), 2); + UIWidgets::EnhancementRadioButton("Idle (belt)", CVAR_ENHANCEMENT("PauseLiveLink"), 3); + UIWidgets::EnhancementRadioButton("Idle (shield)", CVAR_ENHANCEMENT("PauseLiveLink"), 4); + UIWidgets::EnhancementRadioButton("Idle (test sword)", CVAR_ENHANCEMENT("PauseLiveLink"), 5); + UIWidgets::EnhancementRadioButton("Idle (yawn)", CVAR_ENHANCEMENT("PauseLiveLink"), 6); + UIWidgets::EnhancementRadioButton("Battle Stance", CVAR_ENHANCEMENT("PauseLiveLink"), 7); + UIWidgets::EnhancementRadioButton("Walking (no shield)", CVAR_ENHANCEMENT("PauseLiveLink"), 8); + UIWidgets::EnhancementRadioButton("Walking (holding shield)", CVAR_ENHANCEMENT("PauseLiveLink"), 9); + UIWidgets::EnhancementRadioButton("Running (no shield)", CVAR_ENHANCEMENT("PauseLiveLink"), 10); + UIWidgets::EnhancementRadioButton("Running (holding shield)", CVAR_ENHANCEMENT("PauseLiveLink"), 11); + UIWidgets::EnhancementRadioButton("Hand on hip", CVAR_ENHANCEMENT("PauseLiveLink"), 12); + UIWidgets::EnhancementRadioButton("Spin attack charge", CVAR_ENHANCEMENT("PauseLiveLink"), 13); + UIWidgets::EnhancementRadioButton("Look at hand", CVAR_ENHANCEMENT("PauseLiveLink"), 14); UIWidgets::PaddedSeparator(); ImGui::Text("Randomize"); - UIWidgets::EnhancementRadioButton("Random", "gPauseLiveLink", 15); + UIWidgets::EnhancementRadioButton("Random", CVAR_ENHANCEMENT("PauseLiveLink"), 15); UIWidgets::Tooltip("Randomize the animation played each time you open the menu"); - UIWidgets::EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); + UIWidgets::EnhancementRadioButton("Random cycle", CVAR_ENHANCEMENT("PauseLiveLink"), 16); UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time"); - UIWidgets::EnhancementRadioButton("Random cycle (Idle)", "gPauseLiveLink", 17); + UIWidgets::EnhancementRadioButton("Random cycle (Idle)", CVAR_ENHANCEMENT("PauseLiveLink"), 17); UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time (Idle animations only)"); - if (CVarGetInteger("gPauseLiveLink", 0) >= 16) { - UIWidgets::EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0); + if (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) >= 16) { + UIWidgets::EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", CVAR_ENHANCEMENT("MinFrameCount"), 1, 1000, "", 0); } ImGui::EndMenu(); @@ -1126,59 +1126,59 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable LOD", CVAR_ENHANCEMENT("DisableLOD"), true, false); UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) { - if (CVarGetInteger("gDisableDrawDistance", 0) == 0) { - CVarSetInteger("gDisableKokiriDrawDistance", 0); + if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", CVAR_ENHANCEMENT("DisableDrawDistance"), true, false)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) == 0) { + CVarSetInteger(CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), 0); } } UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVarGetInteger("gDisableDrawDistance", 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), true, false); UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); } - if (UIWidgets::PaddedEnhancementCheckbox("Show Age-Dependent Equipment", "gEnhancements.EquimentAlwaysVisible", true, + if (UIWidgets::PaddedEnhancementCheckbox("Show Age-Dependent Equipment", CVAR_ENHANCEMENT("EquimentAlwaysVisible"), true, false)) { UpdatePatchHand(); } UIWidgets::Tooltip("Makes all equipment visible, regardless of Age."); - if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", "gEnhancements.ScaleAdultEquimentAsChild", true, false); + if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", CVAR_ENHANCEMENT("ScaleAdultEquimentAsChild"), true, false); UIWidgets::Tooltip("Scales all of the Adult Equipment, as well and moving some a bit, to fit on Child Link Better. May not work properly with some mods."); } UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); - UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); + UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", CVAR_ENHANCEMENT("DrawLineupTick"), true, false); UIWidgets::Tooltip("Displays a tick in the top center of the screen to help with glitch line-ups in SoH, as traditional UI based line-ups do not work outside of 4:3"); - UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", CVAR_ENHANCEMENT("NewDrops"), true, false); UIWidgets::Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); - UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); + UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", CVAR_ENHANCEMENT("DisableBlackBars"), true, false); UIWidgets::Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); - UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); + UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", CVAR_ENHANCEMENT("DynamicWalletIcon"), true, false); UIWidgets::Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); - UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); + UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), true, false); UIWidgets::Tooltip("Always shows dungeon entrance icons on the minimap"); - UIWidgets::PaddedEnhancementCheckbox("Show Gauntlets in First Person", "gFPSGauntlets", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show Gauntlets in First Person", CVAR_ENHANCEMENT("FirstPersonGauntlets"), true, false); UIWidgets::Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OOT3D"); - if (UIWidgets::PaddedEnhancementCheckbox("Color Temple of Time's Medallions", "gToTMedallionsColors", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Color Temple of Time's Medallions", CVAR_ENHANCEMENT("ToTMedallionsColors"), true, false)) { PatchToTMedallions(); } UIWidgets::Tooltip("When medallions are collected, the medallion imprints around the Master Sword pedestal in the Temple of Time will become colored"); - UIWidgets::PaddedEnhancementCheckbox("Show locked door chains on both sides of locked doors", "gShowDoorLocksOnBothSides", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show locked door chains on both sides of locked doors", CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), true, false); UIWidgets::PaddedText("Fix Vanishing Paths", true, false); - if (UIWidgets::EnhancementCombobox("gSceneSpecificDirtPathFix", zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) { + if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), zFightingOptions, ZFIGHT_FIX_DISABLED) && gPlayState != NULL) { UpdateDirtPathFixState(gPlayState->sceneNum); } UIWidgets::Tooltip("Disabled: Paths vanish more the higher the resolution (Z-fighting is based on resolution)\n" "Consistent: Certain paths vanish the same way in all resolutions\n" "No Vanish: Paths do not vanish, Link seems to sink in to some paths\n" "This might affect other decal effects\n"); - UIWidgets::PaddedEnhancementSliderInt("Text Spacing: %d", "##TEXTSPACING", "gTextSpacing", 4, 6, "", 6, true, true, true); + UIWidgets::PaddedEnhancementSliderInt("Text Spacing: %d", "##TEXTSPACING", CVAR_ENHANCEMENT("TextSpacing"), 4, 6, "", 6, true, true, true); UIWidgets::Tooltip("Space between text characters (useful for HD font textures)"); - UIWidgets::PaddedEnhancementCheckbox("More info in file select", "gFileSelectMoreInfo", true, false); + UIWidgets::PaddedEnhancementCheckbox("More info in file select", CVAR_ENHANCEMENT("FileSelectMoreInfo"), true, false); UIWidgets::Tooltip("Shows what items you have collected in the file select screen, like in N64 randomizer"); - UIWidgets::PaddedEnhancementCheckbox("Better ammo rendering in pause menu", "gEnhancements.BetterAmmoRendering", true, false); + UIWidgets::PaddedEnhancementCheckbox("Better ammo rendering in pause menu", CVAR_ENHANCEMENT("BetterAmmoRendering"), true, false); UIWidgets::Tooltip("Ammo counts in the pause menu will work correctly regardless of the position of items in the inventory"); ImGui::EndMenu(); } @@ -1187,69 +1187,69 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Fixes")) { - UIWidgets::EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + UIWidgets::EnhancementCheckbox("Fix L&R Pause menu", CVAR_ENHANCEMENT("FixMenuLR")); UIWidgets::Tooltip("Makes the L and R buttons in the pause menu the same color"); - UIWidgets::PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", CVAR_ENHANCEMENT("NGCKaleidoSwitcher"), true, false); UIWidgets::Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); - UIWidgets::PaddedEnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Dungeon entrances", CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), true, false); UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); - UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", CVAR_ENHANCEMENT("TwoHandedIdle"), true, false); UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); - UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", CVAR_ENHANCEMENT("GravediggingTourFix"), true, false); UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); - UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", CVAR_ENHANCEMENT("DekuNutUpgradeFix"), true, false); UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); - UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", CVAR_ENHANCEMENT("NaviTextFix"), true, false); UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubixFix"), true, false); UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); - if (UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix", true, false)) { - if (!CVarGetInteger("gCrouchStabHammerFix", 0)) { - CVarClear("gCrouchStabFix"); + if (UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", CVAR_ENHANCEMENT("CrouchStabHammerFix"), true, false)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { + CVarClear(CVAR_ENHANCEMENT("CrouchStabFix")); } } UIWidgets::Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); - if (CVarGetInteger("gCrouchStabHammerFix", 0)) { - UIWidgets::PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false); + if (CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { + UIWidgets::PaddedEnhancementCheckbox("Remove power crouch stab", CVAR_ENHANCEMENT("CrouchStabFix"), true, false); UIWidgets::Tooltip("Make crouch stabbing always do the same damage as a regular slash"); } - UIWidgets::PaddedEnhancementCheckbox("Fix credits timing", "gCreditsFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix credits timing", CVAR_ENHANCEMENT("CreditsFix"), true, false); UIWidgets::Tooltip("Extend certain credits scenes so the music lines up properly with the visuals"); - UIWidgets::PaddedEnhancementCheckbox("Fix Gerudo Warrior's clothing colors", "gGerudoWarriorClothingFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Gerudo Warrior's clothing colors", CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), true, false); UIWidgets::Tooltip("Prevent the Gerudo Warrior's clothes changing color when changing Link's tunic or using bombs in front of her"); - UIWidgets::PaddedEnhancementCheckbox("Fix Camera Drift", "gFixCameraDrift", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Camera Drift", CVAR_ENHANCEMENT("FixCameraDrift"), true, false); UIWidgets::Tooltip("Fixes camera slightly drifting to the left when standing still due to a math error"); - UIWidgets::PaddedEnhancementCheckbox("Fix Camera Swing", "gFixCameraSwing", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Camera Swing", CVAR_ENHANCEMENT("FixCameraSwing"), true, false); UIWidgets::Tooltip("Fixes camera getting stuck on collision when standing still, also fixes slight shift back in camera when stop moving"); - UIWidgets::PaddedEnhancementCheckbox("Fix Hanging Ledge Swing Rate", "gFixHangingLedgeSwingRate", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Hanging Ledge Swing Rate", CVAR_ENHANCEMENT("FixHangingLedgeSwingRate"), true, false); UIWidgets::Tooltip("Fixes camera swing rate when player falls off a ledge and camera swings around"); - UIWidgets::PaddedEnhancementCheckbox("Fix Missing Jingle after 5 Silver Rupees", "gSilverRupeeJingleExtend", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Missing Jingle after 5 Silver Rupees", CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), true, false); UIWidgets::Tooltip( "Adds 5 higher pitches for the Silver Rupee Jingle for the rooms with more than 5 Silver Rupees. " "Currently only relevant in Master Quest."); - if (UIWidgets::PaddedEnhancementCheckbox("Fix out of bounds textures", "gFixTexturesOOB", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Fix out of bounds textures", CVAR_ENHANCEMENT("FixTexturesOOB"), true, false)) { ApplyAuthenticGfxPatches(); } UIWidgets::Tooltip("Fixes authentic out of bounds texture reads, instead loading textures with the correct size"); - UIWidgets::PaddedEnhancementCheckbox("Fix Poacher's Saw Softlock", "gFixSawSoftlock", true, false, CVarGetInteger("gSkipText", 0), + UIWidgets::PaddedEnhancementCheckbox("Fix Poacher's Saw Softlock", CVAR_ENHANCEMENT("FixSawSoftlock"), true, false, CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0), "This is disabled because it is forced on when Skip Text is enabled.", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Prevents the Poacher's Saw softlock from mashing through the text, or with Skip Text enabled."); - UIWidgets::PaddedEnhancementCheckbox("Fix enemies not spawning near water", "gEnemySpawnsOverWaterboxes", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix enemies not spawning near water", CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), true, false); UIWidgets::Tooltip("Causes respawning enemies, like stalchildren, to appear on land near bodies of water. " "Fixes an incorrect calculation that acted like water underneath ground was above it."); - UIWidgets::PaddedEnhancementCheckbox("Fix Bush Item Drops", "gBushDropFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Bush Item Drops", CVAR_ENHANCEMENT("BushDropFix"), true, false); UIWidgets::Tooltip("Fixes the bushes to drop items correctly rather than spawning undefined items."); - UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", CVAR_ENHANCEMENT("FixVineFall"), true, false); UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges."); - UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), true, false); UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping."); - UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed", + UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Fixes Darunia's dancing speed so he dances to the beat of Saria's Song, like in vanilla."); - UIWidgets::PaddedEnhancementCheckbox("Fix raised Floor Switches", "gEnhancements.FixFloorSwitches", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix raised Floor Switches", CVAR_ENHANCEMENT("FixFloorSwitches"), true, false); UIWidgets::Tooltip("Fixes the two raised floor switches, the one in Forest Temple Basement and the one at the top of Fire Temple. \n" "This will lower them, making activating them easier"); - UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", "gFixZoraHintDialogue", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", CVAR_ENHANCEMENT("FixZoraHintDialogue"), true, false); UIWidgets::Tooltip("Fixes one Zora's dialogue giving a hint about bringing Ruto's Letter to King Zora to properly occur before moving King Zora rather than after"); ImGui::EndMenu(); @@ -1259,23 +1259,23 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Restoration")) { - UIWidgets::EnhancementCheckbox("Authentic Logo Screen", "gAuthenticLogo"); + UIWidgets::EnhancementCheckbox("Authentic Logo Screen", CVAR_ENHANCEMENT("AuthenticLogo")); UIWidgets::Tooltip("Hide the game version and build details and display the authentic model and texture on the boot logo start screen"); - UIWidgets::PaddedEnhancementCheckbox("Red Ganon blood", "gRedGanonBlood", true, false); + UIWidgets::PaddedEnhancementCheckbox("Red Ganon blood", CVAR_ENHANCEMENT("RedGanonBlood"), true, false); UIWidgets::Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); - UIWidgets::PaddedEnhancementCheckbox("Fish while hovering", "gHoverFishing", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fish while hovering", CVAR_ENHANCEMENT("HoverFishing"), true, false); UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); - UIWidgets::PaddedEnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames", true, false); + UIWidgets::PaddedEnhancementCheckbox("N64 Weird Frames", CVAR_ENHANCEMENT("N64WeirdFrames"), true, false); UIWidgets::Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); - UIWidgets::PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); + UIWidgets::PaddedEnhancementCheckbox("Bombchus out of bounds", CVAR_ENHANCEMENT("BombchusOOB"), true, false); UIWidgets::Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); - UIWidgets::PaddedEnhancementCheckbox("Quick Putaway", "gQuickPutaway", true, false); + UIWidgets::PaddedEnhancementCheckbox("Quick Putaway", CVAR_ENHANCEMENT("QuickPutaway"), true, false); UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows putting away an item without an animation and performing Putaway Ocarina Items"); - UIWidgets::PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); + UIWidgets::PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", CVAR_ENHANCEMENT("GSCutscene"), true, false); UIWidgets::Tooltip("Restore pre-release behavior where defeating a Gold Skulltula will play a cutscene showing it die."); - UIWidgets::PaddedEnhancementCheckbox("Quick Bongo Kill", "gQuickBongoKill", true, false); + UIWidgets::PaddedEnhancementCheckbox("Quick Bongo Kill", CVAR_ENHANCEMENT("QuickBongoKill"), true, false); UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows bypassing Bongo Bongo's intro cutscene to quickly kill him"); - UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", "gRestoreRBAValues", true, false); + UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", CVAR_ENHANCEMENT("RestoreRBAValues"), true, false); UIWidgets::Tooltip("Restores the original outcomes when performing Reverse Bottle Adventure."); ImGui::EndMenu(); @@ -1285,7 +1285,7 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Extra Modes")) { UIWidgets::PaddedText("Mirrored World", true, false); - if (UIWidgets::EnhancementCombobox("gMirroredWorldMode", mirroredWorldModes, MIRRORED_WORLD_OFF) && gPlayState != NULL) { + if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("MirroredWorldMode"), mirroredWorldModes, MIRRORED_WORLD_OFF) && gPlayState != NULL) { UpdateMirrorModeState(gPlayState->sceneNum); } UIWidgets::Tooltip( @@ -1301,7 +1301,7 @@ void DrawEnhancementsMenu() { ); UIWidgets::PaddedText("Enemy Randomizer", true, false); - UIWidgets::EnhancementCombobox("gRandomizedEnemies", enemyRandomizerModes, ENEMY_RANDOMIZER_OFF); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("RandomizedEnemies"), enemyRandomizerModes, ENEMY_RANDOMIZER_OFF); UIWidgets::Tooltip( "Replaces fixed enemies throughout the game with a random enemy. Bosses, mini-bosses and a few specific regular enemies are excluded.\n" "Enemies that need more than Deku Nuts + either Deku Sticks or a sword to kill are excluded from spawning in \"clear enemy\" rooms.\n\n" @@ -1309,66 +1309,66 @@ void DrawEnhancementsMenu() { "- Random (Seeded): Enemies are randomized based on the current randomizer seed/file\n" ); - UIWidgets::PaddedEnhancementCheckbox("Randomized Enemy Sizes", "gRandomizedEnemySizes", true, false); + UIWidgets::PaddedEnhancementCheckbox("Randomized Enemy Sizes", CVAR_ENHANCEMENT("RandomizedEnemySizes"), true, false); UIWidgets::Tooltip("Enemies and Bosses spawn with random sizes."); - if (CVarGetInteger("gRandomizedEnemySizes", 0)) { - UIWidgets::EnhancementCheckbox("Scale Health with Size", "gEnemySizeScalesHealth"); + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0)) { + UIWidgets::EnhancementCheckbox("Scale Health with Size", CVAR_ENHANCEMENT("EnemySizeScalesHealth")); UIWidgets::Tooltip("Scales normal enemies health with their randomized size. *This will NOT affect bosses*"); } - UIWidgets::PaddedEnhancementCheckbox("Ivan the Fairy (Coop Mode)", "gIvanCoopModeEnabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("Ivan the Fairy (Coop Mode)", CVAR_ENHANCEMENT("IvanCoopModeEnabled"), true, false); UIWidgets::Tooltip("Enables Ivan the Fairy upon the next map change. Player 2 can control Ivan and " "press the C-Buttons to use items and mess with Player 1!"); - UIWidgets::PaddedEnhancementCheckbox("Rupee Dash Mode", "gRupeeDash", true, false); + UIWidgets::PaddedEnhancementCheckbox("Rupee Dash Mode", CVAR_ENHANCEMENT("RupeeDash"), true, false); UIWidgets::Tooltip("Rupees reduced over time, Link suffers damage when the count hits 0."); - if (CVarGetInteger("gRupeeDash", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) { UIWidgets::PaddedEnhancementSliderInt( - "Rupee Dash Interval: %d", "##DashInterval", "gDashInterval", 1, 10, "", 5, true, true, false, - !CVarGetInteger("gRupeeDash", 0), + "Rupee Dash Interval: %d", "##DashInterval", CVAR_ENHANCEMENT("RupeeDashInterval"), 1, 10, "", 5, true, true, false, + !CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0), "This option is disabled because \"Rupee Dash Mode\" is turned off"); UIWidgets::Tooltip("Interval between Rupee reduction in Rupee Dash Mode"); } - UIWidgets::PaddedEnhancementCheckbox("Shadow Tag Mode", "gShadowTag", true, false); + UIWidgets::PaddedEnhancementCheckbox("Shadow Tag Mode", CVAR_ENHANCEMENT("ShadowTag"), true, false); UIWidgets::Tooltip("A wallmaster follows Link everywhere, don't get caught!"); - UIWidgets::PaddedEnhancementCheckbox("Additional Traps", "gAddTraps.enabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("Additional Traps", CVAR_ENHANCEMENT("ExtraTraps.Enabled"), true, false); UIWidgets::Tooltip("Enables additional Trap variants."); - if (CVarGetInteger("gAddTraps.enabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0)) { UIWidgets::PaddedSeparator(); if (ImGui::BeginMenu("Trap Options")) { ImGui::Text("Tier 1 Traps:"); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Freeze Traps", "gAddTraps.Ice", true, false); - UIWidgets::PaddedEnhancementCheckbox("Burn Traps", "gAddTraps.Burn", true, false); - UIWidgets::PaddedEnhancementCheckbox("Shock Traps", "gAddTraps.Shock", true, false); + UIWidgets::PaddedEnhancementCheckbox("Freeze Traps", CVAR_ENHANCEMENT("ExtraTraps.Ice"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Burn Traps", CVAR_ENHANCEMENT("ExtraTraps.Burn"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Shock Traps", CVAR_ENHANCEMENT("ExtraTraps.Shock"), true, false); UIWidgets::PaddedSeparator(); ImGui::Text("Tier 2 Traps:"); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Knockback Traps", "gAddTraps.Knock", true, false); - UIWidgets::PaddedEnhancementCheckbox("Speed Traps", "gAddTraps.Speed", true, false); - UIWidgets::PaddedEnhancementCheckbox("Bomb Traps", "gAddTraps.Bomb", true, false); + UIWidgets::PaddedEnhancementCheckbox("Knockback Traps", CVAR_ENHANCEMENT("ExtraTraps.Knockback"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Speed Traps", CVAR_ENHANCEMENT("ExtraTraps.Speed"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Bomb Traps", CVAR_ENHANCEMENT("ExtraTraps.Bomb"), true, false); UIWidgets::PaddedSeparator(); ImGui::Text("Tier 3 Traps:"); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Void Traps", "gAddTraps.Void", true, false); - UIWidgets::PaddedEnhancementCheckbox("Ammo Traps", "gAddTraps.Ammo", true, false); - UIWidgets::PaddedEnhancementCheckbox("Death Traps", "gAddTraps.Kill", true, false); - UIWidgets::PaddedEnhancementCheckbox("Teleport Traps", "gAddTraps.Tele", true, false); + UIWidgets::PaddedEnhancementCheckbox("Void Traps", CVAR_ENHANCEMENT("ExtraTraps.Void"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Ammo Traps", CVAR_ENHANCEMENT("ExtraTraps.Ammo"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Death Traps", CVAR_ENHANCEMENT("ExtraTraps.Kill"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Teleport Traps", CVAR_ENHANCEMENT("ExtraTraps.Teleport"), true, false); ImGui::EndMenu(); } } UIWidgets::Spacer(0); - if (UIWidgets::PaddedEnhancementCheckbox("Hurt Container Mode", "gHurtContainer", true, false)) { - UpdateHurtContainerModeState(CVarGetInteger("gHurtContainer", 0)); + if (UIWidgets::PaddedEnhancementCheckbox("Hurt Container Mode", CVAR_ENHANCEMENT("HurtContainer"), true, false)) { + UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); } UIWidgets::Tooltip("Changes Heart Piece and Heart Container functionality.\n\n" "- Each Heart Container or full Heart Piece reduces Links hearts by 1.\n" @@ -1381,7 +1381,7 @@ void DrawEnhancementsMenu() { // Autosave enum value of 1 is the default in presets and the old checkbox "on" state for backwards compatibility UIWidgets::PaddedText("Autosave", false, true); - UIWidgets::EnhancementCombobox("gAutosave", autosaveLabels, AUTOSAVE_OFF); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("Autosave"), autosaveLabels, AUTOSAVE_OFF); UIWidgets::Tooltip("Automatically save the game when changing locations and/or obtaining items\n" "Major items exclude rupees and health/magic/ammo refills (but include bombchus unless bombchu drops are enabled)"); @@ -1417,8 +1417,8 @@ void DrawEnhancementsMenu() { #ifdef __SWITCH__ UIWidgets::Spacer(0); ImGui::Text("Switch performance mode"); - if (UIWidgets::EnhancementCombobox("gSwitchPerfMode", SWITCH_CPU_PROFILES, (int)LUS::SwitchProfiles::STOCK)) { - SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[CVarGetInteger("gSwitchPerfMode", (int)LUS::SwitchProfiles::STOCK)]); + if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("SwitchPerfMode"), SWITCH_CPU_PROFILES, (int)LUS::SwitchProfiles::STOCK)) { + SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[CVarGetInteger(CVAR_ENHANCEMENT("SwitchPerfMode"), (int)LUS::SwitchProfiles::STOCK)]); LUS::Switch::ApplyOverclock(); } #endif diff --git a/soh/src/code/code_80097A00.c b/soh/src/code/code_80097A00.c index eb83738e3..32110d8d2 100644 --- a/soh/src/code/code_80097A00.c +++ b/soh/src/code/code_80097A00.c @@ -205,7 +205,7 @@ u8 Inventory_DeleteEquipment(PlayState* play, s16 equipment) { if (equipment == EQUIP_TYPE_TUNIC) { gSaveContext.equips.equipment |= EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4); // non-vanilla: remove goron and zora tunics from item buttons if assignable tunics is on - if (CVarGetInteger("gAssignableTunicsAndBoots", 0) && equipValue != EQUIP_VALUE_TUNIC_KOKIRI) { + if (CVarGetInteger(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 0) && equipValue != EQUIP_VALUE_TUNIC_KOKIRI) { ItemID item = (equipValue == EQUIP_VALUE_TUNIC_GORON ? ITEM_TUNIC_GORON : ITEM_TUNIC_ZORA); for (int i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (gSaveContext.equips.buttonItems[i] == item) { diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index c7238cb39..95387b448 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -1608,7 +1608,7 @@ void func_800ED458(s32 arg0) { if (D_80130F3C != 0 && sOcarinaDropInputTimer != 0) { sOcarinaDropInputTimer--; - if (!CVarGetInteger("gDpadNoDropOcarinaInput", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 0)) { return; } } @@ -2067,15 +2067,15 @@ void Audio_OcaMemoryGameStart(u8 minigameRound) { u8 i; // #region SOH [Enhancement] - if (CVarGetInteger("gCustomizeOcarinaGame", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) { u8 startingNotes = 3; - u8 roundOneCount = CVarGetInteger("gOcarinaGameRoundOneNotes", 5); - u8 roundTwoCount = CVarGetInteger("gOcarinaGameRoundTwoNotes", 6); - u8 roundThreeCount = CVarGetInteger("gOcarinaGameRoundThreeNotes", 8); + u8 roundOneCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), 5); + u8 roundTwoCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), 6); + u8 roundThreeCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), 8); u8 modMinigameNoteCnts[] = { roundOneCount, roundTwoCount, roundThreeCount }; - startingNotes = CVarGetInteger("gOcarinaGameStartingNotes", 3); + startingNotes = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 3); if (minigameRound > 2) { minigameRound = 2; @@ -2118,9 +2118,9 @@ s32 Audio_OcaMemoryGameGenNote(void) { } // #region SOH [Enhancement] - if (CVarGetInteger("gCustomizeOcarinaGame", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) { int noteSpeed = 0x2D; - noteSpeed = noteSpeed / CVarGetInteger("gOcarinaGameNoteSpeed", 1); + noteSpeed = noteSpeed / CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.NoteSpeed"), 1); sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].noteIdx = rndNote; sOcarinaSongs[OCARINA_SONG_MEMORY_GAME][sOcaMinigameAppendPos].unk_02 = noteSpeed; diff --git a/soh/src/code/shrink_window.c b/soh/src/code/shrink_window.c index 015820421..ee4d2e967 100644 --- a/soh/src/code/shrink_window.c +++ b/soh/src/code/shrink_window.c @@ -6,7 +6,7 @@ s32 sShrinkWindowVal = 0; s32 sShrinkWindowCurrentVal = 0; void ShrinkWindow_SetVal(s32 value) { - if (CVarGetInteger("gDisableBlackBars", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableBlackBars"), 0)) { sShrinkWindowVal = 0; return; } @@ -21,7 +21,7 @@ u32 ShrinkWindow_GetVal(void) { } void ShrinkWindow_SetCurrentVal(s32 currentVal) { - if (CVarGetInteger("gDisableBlackBars", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableBlackBars"), 0)) { sShrinkWindowCurrentVal = 0; return; } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index ec14f13b5..87c4f9b46 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1228,7 +1228,7 @@ void Actor_Init(Actor* actor, PlayState* play) { actor->uncullZoneForward = 1000.0f; actor->uncullZoneScale = 350.0f; actor->uncullZoneDownward = 700.0f; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room @@ -2350,7 +2350,7 @@ void Actor_DrawFaroresWindPointer(PlayState* play) { D_8015BC14 = 60; D_8015BC18 = 1.0f; } else if (D_8015BC14) { - D_8015BC14-= CVarGetInteger("gFastFarores", 0) ? 5 : 1; + D_8015BC14-= CVarGetInteger(CVAR_ENHANCEMENT("FastFarores"), 0) ? 5 : 1; } else if (D_8015BC18 > 0.0f) { static Vec3f effectVel = { 0.0f, -0.05f, 0.0f }; static Vec3f effectAccel = { 0.0f, -0.025f, 0.0f }; @@ -2898,7 +2898,7 @@ s32 func_800314B0(PlayState* play, Actor* actor) { s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { f32 var; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room @@ -3192,7 +3192,7 @@ int gMapLoading = 0; Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ, s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize) { - uint8_t tryRandomizeEnemy = CVarGetInteger("gRandomizedEnemies", 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2 && canRandomize; + uint8_t tryRandomizeEnemy = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2 && canRandomize; if (tryRandomizeEnemy) { if (!GetRandomizedEnemy(play, &actorId, &posX, &posY, &posZ, &rotX, &rotY, &rotZ, ¶ms)) { @@ -3221,7 +3221,7 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId); - if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger("gRandomizedEnemies", 0))) { + if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0))) { objBankIndex = 0; } @@ -3299,7 +3299,7 @@ Actor* Actor_SpawnAsChild(ActorContext* actorCtx, Actor* parent, PlayState* play // Gohma (z_boss_goma.c), the Stalchildren spawner (z_en_encount1.c) and the falling platform spawning Stalfos in // Forest Temple (z_bg_mori_bigst.c) that normally rely on this behaviour are changed when // Enemy Rando is on so they still work properly even without assigning a parent. - if (CVarGetInteger("gRandomizedEnemies", 0) && (spawnedActor->id == ACTOR_EN_FLOORMAS || spawnedActor->id == ACTOR_EN_PEEHAT)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && (spawnedActor->id == ACTOR_EN_FLOORMAS || spawnedActor->id == ACTOR_EN_PEEHAT)) { return spawnedActor; } diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 3f3c55f65..03f8b4b7a 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1239,7 +1239,7 @@ f32 Camera_LERPClampDist(Camera* camera, f32 dist, f32 min, f32 max) { camera->rUpdateRateInv = Camera_LERPCeilF(rUpdateRateInvTarget, camera->rUpdateRateInv, PCT(OREG(25)), 0.1f); return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, - CVarGetInteger("gFixCameraDrift", 0) ? 0.0f : 0.2f); + CVarGetInteger(CVAR_ENHANCEMENT("FixCameraDrift"), 0) ? 0.0f : 0.2f); } f32 Camera_ClampDist(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 timer) { @@ -1262,7 +1262,7 @@ f32 Camera_ClampDist(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 tim camera->rUpdateRateInv = Camera_LERPCeilF(rUpdateRateInvTarget, camera->rUpdateRateInv, PCT(OREG(25)), 0.1f); return Camera_LERPCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, - CVarGetInteger("gFixCameraDrift", 0) ? 0.0f : 0.2f); + CVarGetInteger(CVAR_ENHANCEMENT("FixCameraDrift"), 0) ? 0.0f : 0.2f); } s16 Camera_CalcDefaultPitch(Camera* camera, s16 arg1, s16 arg2, s16 arg3) { @@ -1710,7 +1710,7 @@ s32 Camera_Normal1(Camera* camera) { Camera_Vec3fVecSphGeoAdd(eyeNext, at, &eyeAdjustment); if ((camera->status == CAM_STAT_ACTIVE) && (!(norm1->interfaceFlags & 0x10))) { anim->swingYawTarget = BINANG_ROT180(camera->playerPosRot.rot.y); - if (!CVarGetInteger("gFixCameraSwing", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FixCameraSwing"), 0)) { if (anim->startSwingTimer > 0) { func_80046E20(camera, &eyeAdjustment, norm1->distMin, norm1->unk_0C, &sp98, &anim->swing); } else { @@ -1749,7 +1749,7 @@ s32 Camera_Normal1(Camera* camera) { } // crit wiggle - if(!CVarGetInteger("gDisableCritWiggle",0)) { + if(!CVarGetInteger(CVAR_ENHANCEMENT("DisableCritWiggle"),0)) { if (gSaveContext.health <= 16 && ((camera->play->state.frames % 256) == 0)) { wiggleAdj = Rand_ZeroOne() * 10000.0f; camera->inputDir.y = wiggleAdj + camera->inputDir.y; @@ -4726,7 +4726,7 @@ s32 Camera_Unique1(Camera* camera) { anim->timer--; } - sp8C.yaw = Camera_LERPFloorS(anim->yawTarget, eyeNextAtOffset.yaw, 0.5f, CVarGetInteger("gFixHangingLedgeSwingRate", 0) ? 0xA : 0x2710); + sp8C.yaw = Camera_LERPFloorS(anim->yawTarget, eyeNextAtOffset.yaw, 0.5f, CVarGetInteger(CVAR_ENHANCEMENT("FixHangingLedgeSwingRate"), 0) ? 0xA : 0x2710); Camera_Vec3fVecSphGeoAdd(eyeNext, at, &sp8C); *eye = *eyeNext; Camera_BGCheck(camera, at, eye); diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index c4716c947..5376ae41c 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -3047,7 +3047,7 @@ void CollisionCheck_ApplyDamage(PlayState* play, CollisionCheckContext* colChkCt collider->actor->colChkInfo.damage += damage; } - if (CVarGetInteger("gIvanCoopModeEnabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) { collider->actor->colChkInfo.damage *= GET_PLAYER(play)->ivanDamageMultiplier; } } @@ -3667,7 +3667,7 @@ u8 CollisionCheck_GetSwordDamage(s32 dmgFlags, PlayState* play) { damage = 8; } - if (CVarGetInteger("gIvanCoopModeEnabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) { damage *= GET_PLAYER(play)->ivanDamageMultiplier; } diff --git a/soh/src/code/z_construct.c b/soh/src/code/z_construct.c index c8a340492..960088cba 100644 --- a/soh/src/code/z_construct.c +++ b/soh/src/code/z_construct.c @@ -430,8 +430,8 @@ void Regs_InitDataImpl(void) { WREG(28) = 0; R_OW_MINIMAP_X = 238; R_OW_MINIMAP_Y = 164; - if (!CVarGetInteger("gEnhancements.RememberMapToggleState", 0)) { - R_MINIMAP_DISABLED = CVarGetInteger("gMinimalUI", 0); + if (!CVarGetInteger(CVAR_ENHANCEMENT("RememberMapToggleState"), 0)) { + R_MINIMAP_DISABLED = CVarGetInteger(CVAR_ENHANCEMENT("MinimalUI"), 0); } WREG(32) = 122; WREG(33) = 60; diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 21ac5eae7..55f62c1e0 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -512,9 +512,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB } bool playCutscene = false; - if (!CVarGetInteger("gCreditsFix", 1) && (cmd->startFrame == csCtx->frames)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("CreditsFix"), 1) && (cmd->startFrame == csCtx->frames)) { playCutscene = true; - } else if (CVarGetInteger("gCreditsFix", 1)) { + } else if (CVarGetInteger(CVAR_ENHANCEMENT("CreditsFix"), 1)) { u16 delay = 0; // HACK: Align visual timing with audio during credits sequence @@ -616,7 +616,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_INSTANT; break; case 8: - if (CVarGetInteger("gBetterFW", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) { FaroresWindData tempFW = gSaveContext.backupFW; gSaveContext.backupFW = gSaveContext.fw; gSaveContext.fw = tempFW; diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 136df2ef0..4f59e29df 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -333,7 +333,7 @@ void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc) { void EnItem00_SetObjectDependency(EnItem00* this, PlayState* play, s16 objectIndex) { // Remove object dependency for Enemy Randomizer and Crowd Control to allow Like-likes to // drop equipment correctly in rooms where Like-likes normally don't spawn. - if (CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { this->actor.objBankIndex = 0; } else { this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, objectIndex); @@ -781,7 +781,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { (this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) || this->actor.params == ITEM00_BOMBS_A || this->actor.params == ITEM00_ARROWS_SINGLE || this->actor.params == ITEM00_BOMBS_SPECIAL || this->actor.params == ITEM00_BOMBCHU) { - if (CVarGetInteger("gNewDrops", 0) || + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) || // Keys in randomizer need to always rotate for their GID replacement (IS_RANDO && this->actor.params == ITEM00_SMALL_KEY)) { this->actor.shape.rot.y += 960; @@ -1008,35 +1008,35 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { if (!(this->unk_156 & this->unk_158)) { switch (this->actor.params) { case ITEM00_RUPEE_GREEN: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 25.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_RUPEE_GREEN); break; } case ITEM00_RUPEE_BLUE: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 25.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_RUPEE_BLUE); break; } case ITEM00_RUPEE_RED: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 25.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_RUPEE_RED); break; } case ITEM00_RUPEE_ORANGE: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 17.5f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_RUPEE_GOLD); break; } case ITEM00_RUPEE_PURPLE: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 17.5f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_RUPEE_PURPLE); @@ -1046,7 +1046,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { } break; case ITEM00_HEART_PIECE: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) && !IS_RANDO) { mtxScale = 21.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_HEART_PIECE); @@ -1059,7 +1059,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { break; case ITEM00_HEART: // Only change despawn-able recovery hearts - if (CVarGetInteger("gNewDrops", 0) && this->unk_15A >= 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) && this->unk_15A >= 0) { mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_HEART); @@ -1085,7 +1085,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { case ITEM00_BOMBS_A: case ITEM00_BOMBS_B: case ITEM00_BOMBS_SPECIAL: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_BOMB); @@ -1093,70 +1093,70 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { } case ITEM00_ARROWS_SINGLE: case ITEM00_ARROWS_SMALL: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 7.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_ARROWS_SMALL); break; } case ITEM00_ARROWS_MEDIUM: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 7.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_ARROWS_MEDIUM); break; } case ITEM00_ARROWS_LARGE: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 7.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_ARROWS_LARGE); break; } case ITEM00_NUTS: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 9.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_NUTS); break; } case ITEM00_STICK: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 7.5f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_STICK); break; } case ITEM00_MAGIC_LARGE: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_MAGIC_LARGE); break; } case ITEM00_MAGIC_SMALL: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_MAGIC_SMALL); break; } case ITEM00_SEEDS: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 7.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_SEEDS); break; } case ITEM00_BOMBCHU: - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { mtxScale = 9.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_BOMBCHU); break; } case ITEM00_SMALL_KEY: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) && !IS_RANDO) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_KEY_SMALL); @@ -1523,7 +1523,7 @@ s16 func_8001F404(s16 dropId) { if (LINK_IS_ADULT) { if (dropId == ITEM00_SEEDS) { dropId = ITEM00_ARROWS_SMALL; - } else if ((dropId == ITEM00_STICK) && !(CVarGetInteger("gTreeStickDrops", 0))) { + } else if ((dropId == ITEM00_STICK) && !(CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0))) { dropId = ITEM00_RUPEE_GREEN; } } else { @@ -1532,7 +1532,7 @@ s16 func_8001F404(s16 dropId) { } } - if ((CVarGetInteger("gBombchuDrops", 0) || + if ((CVarGetInteger(CVAR_ENHANCEMENT("BombchuDrops"), 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) && (dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) { dropId = EnItem00_ConvertBombDropToBombchu(dropId); @@ -1566,7 +1566,7 @@ EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params) { params &= 0x3FFF; - if ((params & 0x00FF) == ITEM00_HEART && CVarGetInteger("gNoHeartDrops", 0)) { return NULL; } + if ((params & 0x00FF) == ITEM00_HEART && CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { return NULL; } if (((params & 0x00FF) == ITEM00_FLEXIBLE) && !param4000) { // TODO: Prevent the cast to EnItem00 here since this is a different actor (En_Elf) @@ -1611,7 +1611,7 @@ EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params) { params &= 0x3FFF; - if ((params & 0x00FF) == ITEM00_HEART && CVarGetInteger("gNoHeartDrops", 0)) { return NULL; } + if ((params & 0x00FF) == ITEM00_HEART && CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { return NULL; } if (((params & 0x00FF) == ITEM00_FLEXIBLE) && !param4000) { // TODO: Prevent the cast to EnItem00 here since this is a different actor (En_Elf) @@ -1648,7 +1648,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP param8000 = params & 0x8000; params &= 0x7FFF; - if (CVarGetInteger("gNoRandomDrops", 0)) { return; } + if (CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) { return; } if (fromActor != NULL) { if (fromActor->dropFlag) { @@ -1691,11 +1691,11 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP EffectSsDeadSound_SpawnStationary(play, spawnPos, NA_SE_EV_BUTTERFRY_TO_FAIRY, true, DEADSOUND_REPEAT_MODE_OFF, 40); return; - } else if (gSaveContext.health <= 0x30 && !CVarGetInteger("gNoHeartDrops", 0)) { // 3 hearts or less + } else if (gSaveContext.health <= 0x30 && !CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { // 3 hearts or less params = 0xB * 0x10; dropTableIndex = 0x0; dropId = ITEM00_HEART; - } else if (gSaveContext.health <= 0x50 && !CVarGetInteger("gNoHeartDrops", 0)) { // 5 hearts or less + } else if (gSaveContext.health <= 0x50 && !CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { // 5 hearts or less params = 0xA * 0x10; dropTableIndex = 0x0; dropId = ITEM00_HEART; @@ -1728,7 +1728,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP } } - if (dropId != 0xFF && (!CVarGetInteger("gNoHeartDrops", 0) || dropId != ITEM00_HEART)) { + if (dropId != 0xFF && (!CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0) || dropId != ITEM00_HEART)) { dropQuantity = sDropQuantities[params + dropTableIndex]; while (dropQuantity > 0) { if (!param8000) { @@ -1753,7 +1753,7 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP } } } else { - if (CVarGetInteger("gBushDropFix", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BushDropFix"), 0)) { Item_DropCollectible(play, spawnPos, dropId | 0x8000); } else { Item_DropCollectible(play, spawnPos, params | 0x8000); diff --git a/soh/src/code/z_face_reaction.c b/soh/src/code/z_face_reaction.c index 899c6afc6..278af706e 100644 --- a/soh/src/code/z_face_reaction.c +++ b/soh/src/code/z_face_reaction.c @@ -67,7 +67,7 @@ u16 sReactionTextIds[][PLAYER_MASK_MAX] = { u16 Text_GetFaceReaction(PlayState* play, u32 reactionSet) { u8 currentMask = Player_GetMask(play); - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && currentMask == PLAYER_MASK_BUNNY) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && currentMask == PLAYER_MASK_BUNNY) { return 0; } else { return sReactionTextIds[reactionSet][currentMask]; diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index b75c34a61..91b6dc90c 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -131,7 +131,7 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv Matrix_TranslateRotateZYX(&pos, &rot); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); - if (CVarGetInteger("gDisableLOD", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { lod = 0; } diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index 69cba24b4..bc337df4c 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -602,7 +602,7 @@ void HealthMeter_Draw(PlayState* play) { { Mtx* matrix = Graph_Alloc(gfxCtx, sizeof(Mtx)); - if (CVarGetInteger("gNoHUDHeartAnimation", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NoHUDHeartAnimation"), 0)) { Matrix_SetTranslateScaleMtx2(matrix, HeartsScale, // Scale X HeartsScale, // Scale Y @@ -646,7 +646,7 @@ void HealthMeter_HandleCriticalAlarm(PlayState* play) { if (interfaceCtx->unk_22A <= 0) { interfaceCtx->unk_22A = 0; interfaceCtx->unk_22C = 0; - if (CVarGetInteger("gLowHpAlarm", 0) == 0 && !Player_InCsMode(play) && (play->pauseCtx.state == 0) && + if (CVarGetInteger(CVAR_ENHANCEMENT("LowHpAlarm"), 0) == 0 && !Player_InCsMode(play) && (play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Play_InCsMode(play)) { func_80078884(NA_SE_SY_HITPOINT_ALARM); } diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 60ac73cda..2370f3a58 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -918,14 +918,14 @@ void Minimap_Draw(PlayState* play) { // or hide them entirely if the fix is applied if (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] == 0) { entranceY = 0; - entranceX = CVarGetInteger("gFixDungeonMinimapIcon", 0) ? -9999 : OTRGetRectDimensionFromLeftEdge(0); + entranceX = CVarGetInteger(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 0) ? -9999 : OTRGetRectDimensionFromLeftEdge(0); } //! @bug UB: sEntranceIconMapIndex can be up to 23 and is accessing owEntranceFlag which is size 20 if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) || ((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) && ((gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]) || - CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0)))) { + CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0)))) { gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, iconSize, iconSize, 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); @@ -952,7 +952,7 @@ void Minimap_Draw(PlayState* play) { // Ice Cavern entrance icon if ((play->sceneNum == SCENE_ZORAS_FOUNTAIN) && ((gSaveContext.infTable[26] & gBitFlags[9]) || - CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0))) { + CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0))) { gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, iconSize, iconSize, 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); diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index fa4c6c01b..149ca72df 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -150,7 +150,7 @@ void Message_UpdateOcarinaGame(PlayState* play) { u8 Message_ShouldAdvance(PlayState* play) { Input* input = &play->state.input[0]; - bool isB_Held = CVarGetInteger("gSkipText", 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) + bool isB_Held = CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) : CHECK_BTN_ALL(input->press.button, BTN_B); if (CHECK_BTN_ALL(input->press.button, BTN_A) || isB_Held || CHECK_BTN_ALL(input->press.button, BTN_CUP)) { @@ -162,7 +162,7 @@ u8 Message_ShouldAdvance(PlayState* play) { u8 Message_ShouldAdvanceSilent(PlayState* play) { Input* input = &play->state.input[0]; - bool isB_Held = CVarGetInteger("gSkipText", 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) + bool isB_Held = CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) : CHECK_BTN_ALL(input->press.button, BTN_B); return CHECK_BTN_ALL(input->press.button, BTN_A) || isB_Held || CHECK_BTN_ALL(input->press.button, BTN_CUP); @@ -291,7 +291,7 @@ void Message_FindMessage(PlayState* play, u16 textId) { const char* seg; u16 bufferId = textId; // Use the better owl message if better owl is enabled - if (CVarGetInteger("gBetterOwl", 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B || + if (CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B || bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A)) { bufferId = 0x71B3; @@ -873,7 +873,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { Message_SetTextColor(msgCtx, msgCtx->msgBufDecoded[++i] & 0xF); break; case ' ': - msgCtx->textPosX += CVarGetInteger("gTextSpacing", 6); + msgCtx->textPosX += CVarGetInteger(CVAR_ENHANCEMENT("TextSpacing"), 6); break; case MESSAGE_BOX_BREAK: if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { @@ -1032,7 +1032,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { msgCtx->textDelay = msgCtx->msgBufDecoded[++i]; break; case MESSAGE_UNSKIPPABLE: - msgCtx->textUnskippable = CVarGetInteger("gSkipText", 0) != 1; + msgCtx->textUnskippable = CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 1; break; case MESSAGE_TWO_CHOICE: msgCtx->textboxEndType = TEXTBOX_ENDTYPE_2_CHOICE; @@ -1116,7 +1116,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { } } if (msgCtx->textDelayTimer == 0) { - msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 2); + msgCtx->textDrawPos = i + CVarGetInteger(CVAR_ENHANCEMENT("TextSpeed"), 2); msgCtx->textDelayTimer = msgCtx->textDelay; } else { msgCtx->textDelayTimer--; @@ -1189,7 +1189,7 @@ void Message_Decode(PlayState* play) { phi_s1 = temp_s2 = msgCtx->msgBufDecoded[decodedBufPos] = font->msgBuf[msgCtx->msgBufPos]; // Don't require input for credits textboxes in randomizer - if (CVarGetInteger("gNoInputForCredits", 0) && ( + if (CVarGetInteger(CVAR_ENHANCEMENT("NoInputForCredits"), 0) && ( msgCtx->textId == 0x706F || msgCtx->textId == 0x7091 || msgCtx->textId == 0x7092 || @@ -1654,7 +1654,7 @@ void Message_OpenText(PlayState* play, u16 textId) { //DmaMgr_SendRequest1(font->msgBuf, (uintptr_t)(_staff_message_data_staticSegmentRomStart + 4 + font->msgOffset), //font->msgLength, __FILE__, __LINE__); - } else if (CVarGetInteger("gAskToEquip", 0) && + } else if (CVarGetInteger(CVAR_ENHANCEMENT("AskToEquip"), 0) && (((LINK_IS_ADULT || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) && // 0C = Biggoron, 4B = Giant's, 4E = Mirror Shield, 50-51 = Tunics (textId == 0x0C || textId == 0x4B || textId == 0x4E || @@ -2155,7 +2155,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { gDPSetCombineLERP(gfx++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0); - bool isB_Held = CVarGetInteger("gSkipText", 0) != 0 ? CHECK_BTN_ALL(play->state.input[0].cur.button, BTN_B) + bool isB_Held = CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0 ? CHECK_BTN_ALL(play->state.input[0].cur.button, BTN_B) : CHECK_BTN_ALL(play->state.input[0].press.button, BTN_B); switch (msgCtx->msgMode) { @@ -2436,7 +2436,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { } break; case MSGMODE_SETUP_DISPLAY_SONG_PLAYED: - if (CVarGetInteger("gFastOcarinaPlayback", 0) == 0 || + if (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) == 0 || play->msgCtx.lastPlayedSong == OCARINA_SONG_TIME || play->msgCtx.lastPlayedSong == OCARINA_SONG_STORMS || play->msgCtx.lastPlayedSong == OCARINA_SONG_SUNS) { @@ -2491,7 +2491,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { Message_Decode(play); msgCtx->msgMode = MSGMODE_DISPLAY_SONG_PLAYED_TEXT; - if (CVarGetInteger("gFastOcarinaPlayback", 0) == 0 || play->msgCtx.lastPlayedSong == OCARINA_SONG_TIME + if (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) == 0 || play->msgCtx.lastPlayedSong == OCARINA_SONG_TIME || play->msgCtx.lastPlayedSong == OCARINA_SONG_STORMS || play->msgCtx.lastPlayedSong == OCARINA_SONG_SUNS) { msgCtx->stateTimer = 20; @@ -3148,7 +3148,7 @@ void Message_Update(PlayState* play) { GameInteractor_ExecuteOnDialogMessage(); - bool isB_Held = CVarGetInteger("gSkipText", 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) && !sTextboxSkipped + bool isB_Held = CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) && !sTextboxSkipped : CHECK_BTN_ALL(input->press.button, BTN_B); switch (msgCtx->msgMode) { @@ -3367,7 +3367,7 @@ void Message_Update(PlayState* play) { } if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) { gSaveContext.inventory.questItems ^= 0x40000000; - if (!CVarGetInteger("gHurtContainer", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)) { gSaveContext.healthCapacity += 0x10; gSaveContext.health += 0x10; } else { diff --git a/soh/src/code/z_olib.c b/soh/src/code/z_olib.c index 2b72f3014..da4959726 100644 --- a/soh/src/code/z_olib.c +++ b/soh/src/code/z_olib.c @@ -80,7 +80,7 @@ Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph) { f32 sinYaw; f32 cosYaw; - if (CVarGetInteger("gFixCameraDrift", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixCameraDrift"), 0)) { cosPitch = Math_AccurateCosS(sph->pitch); cosYaw = Math_AccurateCosS(sph->yaw); sinPitch = Math_AccurateSinS(sph->pitch); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 2ece7c2f1..caf6da8d6 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -72,7 +72,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor // #region SOH [Enhancement] //the default is 90, lower values necessary to prevent camera swing as animation speeds up - s16 camCrawlTemp = CVarGetInteger("gCrawlSpeed", 1); + s16 camCrawlTemp = CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1); s16 camCrawlTimer = D_8012042C / camCrawlTemp; // #endregion @@ -336,7 +336,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 9601: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); - if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) > 1) { OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120398); } else { OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398); @@ -344,7 +344,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor break; case 9602: // #region SOH [Enhancement] - if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) > 1) { Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, MAIN_CAM, mainCam->prevSetting); OnePointCutscene_SetCsCamPoints(csCam, D_80120430 | 0x1000, camCrawlTimer, D_80120308, D_80120434); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index e9788f7f8..dd6949e8e 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1170,7 +1170,7 @@ void func_80083108(PlayState* play) { if (interfaceCtx->restrictions.tradeItems != 0) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) + if ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && (gSaveContext.equips.buttonItems[i] >= ITEM_MASK_KEATON) && (gSaveContext.equips.buttonItems[i] <= ITEM_MASK_TRUTH)) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_ENABLED; @@ -1401,7 +1401,7 @@ void Interface_SetSceneRestrictions(PlayState* play) { interfaceCtx->restrictions.farores, interfaceCtx->restrictions.dinsNayrus, interfaceCtx->restrictions.all); osSyncPrintf(VT_RST); - if (CVarGetInteger("gBetterFW", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) { if (currentScene == SCENE_GERUDO_TRAINING_GROUND || currentScene == SCENE_INSIDE_GANONS_CASTLE) { interfaceCtx->restrictions.farores = 0; } @@ -2278,7 +2278,7 @@ u8 Item_Give(PlayState* play, u8 item) { gSaveContext.sohStats.heartPieces++; return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_HEART_CONTAINER) { - if (!CVarGetInteger("gHurtContainer", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)) { gSaveContext.healthCapacity += 0x10; gSaveContext.health += 0x10; } else { @@ -2379,7 +2379,7 @@ u8 Item_Give(PlayState* play, u8 item) { } return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_WEIRD_EGG) && (item <= ITEM_CLAIM_CHECK)) { - if ((item == ITEM_SAW) && CVarGetInteger("gDekuNutUpgradeFix", 0) == 0) { + if ((item == ITEM_SAW) && CVarGetInteger(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 0) == 0) { Flags_SetItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE); } @@ -2905,7 +2905,7 @@ void Inventory_UpdateBottleItem(PlayState* play, u8 item, u8 button) { item = ITEM_MILK_HALF; } - if (CVarGetInteger("gRestoreRBAValues",0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RestoreRBAValues"),0)) { byteSwapInventory(); gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[button - 1]] = item; byteSwapInventory(); @@ -3016,7 +3016,7 @@ void Interface_SetNaviCall(PlayState* play, u16 naviCallState) { if (((naviCallState == 0x1D) || (naviCallState == 0x1E)) && !interfaceCtx->naviCalling && (play->csCtx.state == CS_STATE_IDLE)) { - if (!CVarGetInteger("gDisableNaviCallAudio", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 0)) { // clang-format off if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } @@ -4132,7 +4132,7 @@ void Interface_DrawItemButtons(PlayState* play) { const s16 C_Right_BTN_Pos_ori[] = { C_RIGHT_BUTTON_X+X_Margins_CR, C_RIGHT_BUTTON_Y+Y_Margins_CR }; const s16 C_Up_BTN_Pos_ori[] = { C_UP_BUTTON_X+X_Margins_CU, C_UP_BUTTON_Y+Y_Margins_CU }; const s16 C_Down_BTN_Pos_ori[] = { C_DOWN_BUTTON_X+X_Margins_CD, C_DOWN_BUTTON_Y+Y_Margins_CD }; - s16 LabelX_Navi=7 + !!CVarGetInteger("gNaviTextFix", 0); + s16 LabelX_Navi=7 + !!CVarGetInteger(CVAR_ENHANCEMENT("NaviTextFix"), 0); s16 LabelY_Navi=4; s16 C_Left_BTN_Pos[2]; //(X,Y) s16 C_Right_BTN_Pos[2]; @@ -5119,7 +5119,7 @@ void Interface_Draw(PlayState* play) { s16 svar4; s16 svar5; s16 svar6; - bool fullUi = !CVarGetInteger("gMinimalUI", 0) || !R_MINIMAP_DISABLED || play->pauseCtx.state != 0; + bool fullUi = !CVarGetInteger(CVAR_ENHANCEMENT("MinimalUI"), 0) || !R_MINIMAP_DISABLED || play->pauseCtx.state != 0; if (GameInteractor_NoUIActive()) { return; @@ -5143,7 +5143,7 @@ void Interface_Draw(PlayState* play) { if (fullUi) { // Rupee Icon - if (CVarGetInteger("gDynamicWalletIcon", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { switch (CUR_UPG_VALUE(UPG_WALLET)) { case 0: if (CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0)) { @@ -5346,7 +5346,7 @@ void Interface_Draw(PlayState* play) { gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0); } - if (CVarGetInteger("gDrawLineupTick", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DrawLineupTick"), 0)) { Interface_DrawLineupTick(play); } @@ -5366,7 +5366,7 @@ void Interface_Draw(PlayState* play) { } // Render enemy health bar after Z-target to leverage set variables - if (CVarGetInteger("gEnemyHealthBar", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EnemyHealthBar"), 0)) { Interface_DrawEnemyHealthBar(&play->actorCtx.targetCtx, play); } } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 9bc72380e..6e745ea7f 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -675,7 +675,7 @@ void Play_Init(GameState* thisx) { Fault_AddClient(&D_801614B8, ZeldaArena_Display, NULL, NULL); // In order to keep bunny hood equipped on first load, we need to pre-set the age reqs for the item and slot - if ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) { gItemAgeReqs[ITEM_MASK_BUNNY] = AGE_REQ_NONE; if(INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY) gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_NONE; @@ -762,7 +762,7 @@ void Play_Init(GameState* thisx) { } #endif - if (CVarGetInteger("gIvanCoopModeEnabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) { Actor_Spawn(&play->actorCtx, play, gEnPartnerId, GET_PLAYER(play)->actor.world.pos.x, GET_PLAYER(play)->actor.world.pos.y + Player_GetHeight(GET_PLAYER(play)) + 5.0f, GET_PLAYER(play)->actor.world.pos.z, 0, 0, 0, 1, true); @@ -1216,7 +1216,7 @@ void Play_Update(PlayState* play) { gSaveContext.sohStats.sceneTimer++; gSaveContext.sohStats.roomTimer++; - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && Player_GetMask(play) == PLAYER_MASK_BUNNY) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && Player_GetMask(play) == PLAYER_MASK_BUNNY) { gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD]++; } } @@ -2364,7 +2364,7 @@ void Play_PerformSave(PlayState* play) { IS_RANDO && gSaveContext.triforcePiecesCollected == Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) && Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT); - if (CVarGetInteger("gAutosave", AUTOSAVE_OFF) != AUTOSAVE_OFF || triforceHuntCompleted) { + if (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF || triforceHuntCompleted) { Overlay_DisplayText(3.0f, "Game Saved"); } } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 90b721f3c..8bcb6ec7c 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -600,9 +600,9 @@ void Player_SetModelsForHoldingShield(Player* this) { if ((CVarGetInteger(CVAR_CHEAT("ShieldTwoHanded"), 0) && (this->heldItemAction != PLAYER_IA_DEKU_STICK) || !Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) { this->rightHandType = PLAYER_MODELTYPE_RH_SHIELD; - if (LINK_IS_CHILD && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) { + if (LINK_IS_CHILD && (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && (this->currentShield == PLAYER_SHIELD_MIRROR)) { this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][0]; - } else if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && (this->currentShield == PLAYER_SHIELD_DEKU)) { + } else if (LINK_IS_ADULT && (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && (this->currentShield == PLAYER_SHIELD_DEKU)) { this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][1]; } else { this->rightHandDLists = &sPlayerDListGroups[PLAYER_MODELTYPE_RH_SHIELD][gSaveContext.linkAge]; @@ -613,7 +613,7 @@ void Player_SetModelsForHoldingShield(Player* this) { this->sheathType = PLAYER_MODELTYPE_SHEATH_17; } this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; - if ((CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_CHILD && + if ((CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_CHILD && gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI) { this->sheathDLists = &sPlayerDListGroups[this->sheathType][0]; } @@ -628,7 +628,7 @@ void Player_SetModels(Player* this, s32 modelGroup) { this->leftHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND]; this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][gSaveContext.linkAge]; - if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { if (LINK_IS_CHILD && (this->leftHandType == PLAYER_MODELTYPE_LH_HAMMER || ((this->leftHandType == PLAYER_MODELTYPE_LH_SWORD || this->leftHandType == PLAYER_MODELTYPE_LH_BGS) && @@ -649,7 +649,7 @@ void Player_SetModels(Player* this, s32 modelGroup) { this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND]; this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge]; - if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { if (LINK_IS_CHILD && (this->rightHandType == PLAYER_MODELTYPE_RH_HOOKSHOT || (this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD && this->currentShield == PLAYER_SHIELD_MIRROR))) { @@ -660,7 +660,7 @@ void Player_SetModels(Player* this, s32 modelGroup) { this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][1]; } } - if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && this->rightHandType == 11) { // If holding Bow/Slingshot + if ((CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && this->rightHandType == 11) { // If holding Bow/Slingshot this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][Player_HoldsSlingshot(this)]; } @@ -668,7 +668,7 @@ void Player_SetModels(Player* this, s32 modelGroup) { this->sheathType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_SHEATH]; this->sheathDLists = &sPlayerDListGroups[this->sheathType][gSaveContext.linkAge]; - if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { if (LINK_IS_CHILD && (this->currentShield == PLAYER_SHIELD_HYLIAN || this->currentShield == PLAYER_SHIELD_MIRROR) && ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_MASTER) || @@ -789,7 +789,7 @@ s32 Player_IsBurningStickInRange(PlayState* play, Vec3f* pos, f32 xzRange, f32 y s32 Player_GetStrength(void) { s32 strengthUpgrade = CUR_UPG_VALUE(UPG_STRENGTH); - if (CVarGetInteger("gToggleStrength", 0) && CVarGetInteger("gStrengthDisabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0)) { return PLAYER_STR_NONE; } @@ -953,9 +953,9 @@ s32 Player_GetEnvironmentalHazard(PlayState* play) { triggerEntry = &sTextTriggers[var]; if ((triggerEntry->flag != 0) && !(gSaveContext.textTriggerFlags & triggerEntry->flag) && - (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)) || + (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger(CVAR_ENHANCEMENT("DisableTunicWarningText"), 0) == 0)) || (((var == 1) || (var == 3)) && (this->currentBoots == PLAYER_BOOTS_IRON) && - (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger("gDisableTunicWarningText", 0) == 0)))) { + (this->currentTunic != PLAYER_TUNIC_ZORA && CVarGetInteger(CVAR_CHEAT("SuperTunic"), 0) == 0 && CVarGetInteger(CVAR_ENHANCEMENT("DisableTunicWarningText"), 0) == 0)))) { Message_StartTextbox(play, triggerEntry->textId, NULL); gSaveContext.textTriggerFlags |= triggerEntry->flag; } @@ -1090,7 +1090,7 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL SkelAnime_DrawFlexLod(play, skeleton, jointTable, dListCount, overrideLimbDraw, postLimbDraw, data, lod); - if (((CVarGetInteger("gFPSGauntlets", 0) && LINK_IS_ADULT) || (overrideLimbDraw != Player_OverrideLimbDrawGameplayFirstPerson)) && + if (((CVarGetInteger(CVAR_ENHANCEMENT("FirstPersonGauntlets"), 0) && LINK_IS_ADULT) || (overrideLimbDraw != Player_OverrideLimbDrawGameplayFirstPerson)) && (overrideLimbDraw != Player_OverrideLimbDrawGameplayCrawling) && (gSaveContext.gameMode != 3)) { if (LINK_IS_ADULT) { @@ -1243,7 +1243,7 @@ void func_8008F87C(PlayState* play, Player* this, SkelAnime* skelAnime, Vec3f* p s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { Player* this = (Player*)thisx; - if (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0) && CVarGetInteger("gEnhancements.ScaleAdultEquimentAsChild", 0) && LINK_IS_CHILD) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("ScaleAdultEquimentAsChild"), 0) && LINK_IS_CHILD) { if (limbIndex == PLAYER_LIMB_L_HAND) { if ((gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && sLeftHandType == PLAYER_MODELTYPE_LH_SWORD) || (sLeftHandType == PLAYER_MODELTYPE_LH_BGS) || (sLeftHandType == PLAYER_MODELTYPE_LH_HAMMER)) { @@ -1396,7 +1396,7 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { dLists += PLAYER_SHIELD_MAX * 4; } - } else if (!CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + } else if (!CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { if (!LINK_IS_ADULT && ((this->sheathType == PLAYER_MODELTYPE_SHEATH_16) || (this->sheathType == PLAYER_MODELTYPE_SHEATH_17)) && (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI)) { dLists = &sSheathWithSwordDLs[PLAYER_SHIELD_MAX * 4]; @@ -1438,7 +1438,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G *dList = sFirstPersonLeftForearmDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_L_HAND) { s32 handOutDlIndex = gSaveContext.linkAge; - if ((CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) && LINK_IS_ADULT && Player_HoldsSlingshot(this)) { handOutDlIndex = 1; } *dList = sFirstPersonLeftHandDLs[handOutDlIndex]; @@ -1448,7 +1448,7 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G *dList = sFirstPersonForearmDLs[gSaveContext.linkAge]; } else if (limbIndex == PLAYER_LIMB_R_HAND) { s32 firstPersonWeaponIndex = gSaveContext.linkAge; - if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { if (Player_HoldsBow(this)) { firstPersonWeaponIndex = 0; } else if (Player_HoldsSlingshot(this)) { @@ -1682,7 +1682,7 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange gSPTexture(WORLD_OVERLAY_DISP++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); gDPLoadTextureBlock(WORLD_OVERLAY_DISP++, gLinkAdultHookshotReticleTex, G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); - if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && CVarGetInteger("gHookshotableReticle", false)) { + if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && CVarGetInteger(CVAR_ENHANCEMENT("HookshotableReticle"), false)) { const Color_RGBA8 defaultColor = { .r = 0, .g = 255, .b = 0, .a = 255 }; const Color_RGBA8 color = CVarGetColor("gCosmetics.HookshotReticle_Target.Value", defaultColor); gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a); @@ -1848,7 +1848,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve Matrix_Get(&this->shieldMf); } else if ((this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT) || (this->rightHandType == PLAYER_MODELTYPE_RH_BOW_SLINGSHOT_2)) { s32 stringModelToUse = gSaveContext.linkAge; - if (CVarGetInteger("gBowSlingShotAmmoFix", 0) || CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0)) { stringModelToUse = Player_HoldsSlingshot(this); } BowStringData* stringData = &sBowStringData[stringModelToUse]; @@ -1917,7 +1917,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f)); } } - } else if (CVarGetInteger("gBowReticle", 0) && ( + } else if (CVarGetInteger(CVAR_ENHANCEMENT("BowReticle"), 0) && ( (this->heldItemAction == PLAYER_IA_BOW_FIRE) || (this->heldItemAction == PLAYER_IA_BOW_ICE) || (this->heldItemAction == PLAYER_IA_BOW_LIGHT) || @@ -2038,7 +2038,7 @@ s32 Player_OverrideLimbDrawPause(PlayState* play, s32 limbIndex, Gfx** dList, Ve type = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_SHEATH]; if ((type == PLAYER_MODELTYPE_SHEATH_18) || (type == PLAYER_MODELTYPE_SHEATH_19)) { dListOffset = playerSwordAndShield[1] * ptrSize; - } else if (type == PLAYER_MODELTYPE_SHEATH_16 && CVarGetInteger("gPauseLiveLink", 0)) { + } else if (type == PLAYER_MODELTYPE_SHEATH_16 && CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0)) { //if (playerSwordAndShield[0] == 1) //dListOffset = 4; } @@ -2122,7 +2122,7 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* playerSwordAndShield[0] = sword; playerSwordAndShield[1] = shield; - Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger("gPauseLiveLink", 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0), + Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0), pos->y - (CVarGetInteger("gPauseTriforce", 0) ? 16 : 0), pos->z, rot); Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), scale, scale, MTXMODE_APPLY); @@ -2176,8 +2176,8 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* Vec3s* srcTable; s32 i; bool canswitchrnd = false; - s16 SelectedMode = CVarGetInteger("gPauseLiveLink", 0); - MinFrameCount = CVarGetInteger("gMinFrameCount", 200); + s16 SelectedMode = CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0); + MinFrameCount = CVarGetInteger(CVAR_ENHANCEMENT("MinFrameCount"), 200); gSegments[4] = VIRTUAL_TO_PHYSICAL(segment + 0x3800); gSegments[6] = VIRTUAL_TO_PHYSICAL(segment + 0x8800); @@ -2202,7 +2202,7 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* }; s16 AnimArraySize = ARRAY_COUNT(PauseMenuAnimSet); - if (CVarGetInteger("gPauseLiveLink", 0) || CVarGetInteger("gPauseTriforce", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) || CVarGetInteger("gPauseTriforce", 0)) { uintptr_t anim = 0; // Initialise anim if (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) >= EQUIP_VALUE_SWORD_BIGGORON) { diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 2123c2d3b..3df8a26a5 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -78,7 +78,7 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3f pos; Vec3s rot; - if (CVarGetInteger("gDisableLOD", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { lod = 0; } @@ -195,7 +195,7 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3s rot; Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx)); - if (CVarGetInteger("gDisableLOD", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { lod = 0; } @@ -870,7 +870,7 @@ AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, Animat */ void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, Vec3s* frameTable) { - if (CVarGetInteger("gN64WeirdFrames", 0) && frame < 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("N64WeirdFrames"), 0) && frame < 0) { Vec3s* src = (Vec3s*)getN64WeirdFrame((sizeof(Vec3s) * limbCount + 2) * frame); memcpy(frameTable, src, sizeof(Vec3s) * limbCount + 2); return; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 5b67eba1d..60285a8bf 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -125,7 +125,7 @@ void Sram_OpenSave() { default: // Use the saved entrance value with remember save location, except when in grottos/fairy fountains - if (CVarGetInteger("gRememberSaveLocation", 0) && gSaveContext.savedSceneNum != SCENE_FAIRYS_FOUNTAIN && + if (CVarGetInteger(CVAR_ENHANCEMENT("RememberSaveLocation"), 0) && gSaveContext.savedSceneNum != SCENE_FAIRYS_FOUNTAIN && gSaveContext.savedSceneNum != SCENE_GROTTOS) { break; } @@ -142,7 +142,7 @@ void Sram_OpenSave() { osSyncPrintf(VT_RST); if (gSaveContext.health < 0x30) { - gSaveContext.health = CVarGetInteger("gFullHealthSpawn", 0) ? gSaveContext.healthCapacity : 0x30; + gSaveContext.health = CVarGetInteger(CVAR_ENHANCEMENT("FullHealthSpawn"), 0) ? gSaveContext.healthCapacity : 0x30; } if (gSaveContext.scarecrowLongSongSet) { diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 58f11a7f3..1ada94a29 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -106,7 +106,7 @@ void BgBreakwall_Init(Actor* thisx, PlayState* play) { s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF; // Initialize this with the mud wall, so it can't be affected by toggling while the actor is loaded - blueFireArrowsEnabledOnMudwallLoad = CVarGetInteger("gBlueFireArrows", 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS)); + blueFireArrowsEnabledOnMudwallLoad = CVarGetInteger(CVAR_ENHANCEMENT("BlueFireArrows"), 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS)); Actor_ProcessInitChain(&this->dyna.actor, sInitChain); DynaPolyActor_Init(&this->dyna, DPM_UNK); diff --git a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c index 2379b0a58..d1f0e6d30 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka/z_bg_haka.c @@ -69,7 +69,7 @@ void func_8087B7E8(BgHaka* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->dyna.unk_150 != 0.0f) { - if (play->sceneNum == SCENE_GRAVEYARD && !LINK_IS_ADULT && IS_DAY && !CVarGetInteger("gDayGravePull", 0)) { + if (play->sceneNum == SCENE_GRAVEYARD && !LINK_IS_ADULT && IS_DAY && !CVarGetInteger(CVAR_ENHANCEMENT("DayGravePull"), 0)) { this->dyna.unk_150 = 0.0f; player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; if (!Play_InCsMode(play)) { diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c b/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c index c61c93a46..98c5138c3 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Gate/z_bg_haka_gate.c @@ -211,9 +211,9 @@ void BgHakaGate_StatueTurn(BgHakaGate* this, PlayState* play) { if (turnFinished) { player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; this->vRotYDeg10 = (this->vRotYDeg10 + turnAngle) % 3600; - this->vTurnRateDeg10 = CVarGetInteger("gFasterBlockPush", 0) * 2; + this->vTurnRateDeg10 = CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 2; this->vTurnAngleDeg10 = 0; - this->vTimer = 5 - ((CVarGetInteger("gFasterBlockPush", 0) * 3) / 5); + this->vTimer = 5 - ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 3) / 5); this->actionFunc = BgHakaGate_StatueIdle; this->dyna.unk_150 = 0.0f; } diff --git a/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c b/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c index 4f9b4a216..e031c07cc 100644 --- a/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c +++ b/soh/src/overlays/actors/ovl_Bg_Haka_Tubo/z_bg_haka_tubo.c @@ -181,7 +181,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) { func_80078884(NA_SE_SY_ERROR); } else { // Random rewards - if (CVarGetInteger("gNoRandomDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) { collectibleParams = -1; } else if(rnd < 0.4f) { collectibleParams = ITEM00_BOMBS_A; @@ -196,7 +196,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) { } } else if (Flags_GetCollectible(play, this->dyna.actor.params) != 0) { // If small key already collected, drop recovery heart instead - if (CVarGetInteger("gNoHeartDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { collectibleParams = -1; } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c index 3b2524e79..c020c07ed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c @@ -320,7 +320,7 @@ void BgHeavyBlock_Wait(BgHeavyBlock* this, PlayState* play) { if (Actor_HasParent(&this->dyna.actor, play)) { this->timer = 0; - if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { switch (this->dyna.actor.params & 0xFF) { case HEAVYBLOCK_BREAKABLE: OnePointCutscene_Init(play, 4020, 270, &this->dyna.actor, MAIN_CAM); @@ -369,7 +369,7 @@ void BgHeavyBlock_LiftedUp(BgHeavyBlock* this, PlayState* play) { this->timer++; - if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { func_8002DF54(play, &player->actor, 8); } @@ -409,7 +409,7 @@ void BgHeavyBlock_Fly(BgHeavyBlock* this, PlayState* play) { Quake_SetCountdown(quakeIndex, 30); // We don't want this arbitrarily long quake with the enhancement enabled - if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), 2); Quake_SetSpeed(quakeIndex, 12000); Quake_SetQuakeValues(quakeIndex, 5, 0, 0, 0); diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c index 36cfb0a27..c5b90a4c9 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Rock/z_bg_hidan_rock.c @@ -137,9 +137,9 @@ void func_8088B268(BgHidanRock* this, PlayState* play) { } } - this->dyna.actor.speedXZ = this->dyna.actor.speedXZ + (CVarGetInteger("gFasterBlockPush", 0) * 0.3) + 0.5f; + this->dyna.actor.speedXZ = this->dyna.actor.speedXZ + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.3) + 0.5f; this->dyna.actor.speedXZ = - CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f + (CVarGetInteger("gFasterBlockPush", 0) * 0.5)); + CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.5)); if (D_8088BFC0 > 0.0f) { temp_v1 = Math_StepToF(&D_8088BFC0, 20.0f, this->dyna.actor.speedXZ); @@ -157,7 +157,7 @@ void func_8088B268(BgHidanRock* this, PlayState* play) { this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z; D_8088BFC0 = 0.0f; this->dyna.actor.speedXZ = 0.0f; - this->timer = 5 - ((CVarGetInteger("gFasterBlockPush", 0) * 3) / 5); + this->timer = 5 - ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 3) / 5); } func_8002F974(&this->dyna.actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG); diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c index 36666ed15..2b2e1c0f7 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c @@ -105,7 +105,7 @@ void func_80890740(BgIceShelter* this, PlayState* play) { s32 type = (this->dyna.actor.params >> 8) & 7; // Initialize this with the red ice, so it can't be affected by toggling while the actor is loaded - blueFireArrowsEnabledOnRedIceLoad = CVarGetInteger("gBlueFireArrows", 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS)); + blueFireArrowsEnabledOnRedIceLoad = CVarGetInteger(CVAR_ENHANCEMENT("BlueFireArrows"), 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS)); Collider_InitCylinder(play, &this->cylinder1); // If "Blue Fire Arrows" is enabled, set up a collider on the red ice that responds to them diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Cobra/z_bg_jya_cobra.c b/soh/src/overlays/actors/ovl_Bg_Jya_Cobra/z_bg_jya_cobra.c index 564f6f322..f2c821929 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Cobra/z_bg_jya_cobra.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Cobra/z_bg_jya_cobra.c @@ -443,7 +443,7 @@ void func_80896950(BgJyaCobra* this, PlayState* play) { if (this->dyna.unk_150 > 0.001f) { this->unk_168++; - if (this->unk_168 >= (15 - CVarGetInteger("gFasterBlockPush", 0) * 2)) { + if (this->unk_168 >= (15 - CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 2)) { func_808969F8(this, play); } } else { @@ -478,7 +478,7 @@ void func_808969F8(BgJyaCobra* this, PlayState* play) { this->unk_174.z = player->actor.world.pos.z - this->dyna.actor.world.pos.z; this->unk_170 = 0; this->unk_172 = true; - this->unk_16E = CVarGetInteger("gFasterBlockPush", 0) * 20; + this->unk_16E = CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 20; } void func_80896ABC(BgJyaCobra* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_Bg_Jya_Lift/z_bg_jya_lift.c b/soh/src/overlays/actors/ovl_Bg_Jya_Lift/z_bg_jya_lift.c index 7ec5c2a77..19bef1b67 100644 --- a/soh/src/overlays/actors/ovl_Bg_Jya_Lift/z_bg_jya_lift.c +++ b/soh/src/overlays/actors/ovl_Bg_Jya_Lift/z_bg_jya_lift.c @@ -99,7 +99,7 @@ void BgJyaLift_DelayMove(BgJyaLift* this, PlayState* play) { // The cutscene of the platform lowering will show the central room in an unloaded state if // Link is not standing on the platform as it lowers. Therefore check for the Sunlight arrows // enhancement and if it's enabled, check that Link is on the platform. Otherwise skip it. - if (!(CVarGetInteger("gSunlightArrows", 0) || Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS)) || + if (!(CVarGetInteger(CVAR_ENHANCEMENT("SunlightArrows"), 0) || Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS)) || (GET_PLAYER(play)->actor.world.pos.x > -19.0f && GET_PLAYER(play)->actor.world.pos.x < 139.0f && GET_PLAYER(play)->actor.world.pos.z > -1172.0f && diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index eeecfabcb..6e1c36f78 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -216,7 +216,7 @@ void BgMoriBigst_SetupStalfosPairFight(BgMoriBigst* this, PlayState* play) { void BgMoriBigst_StalfosPairFight(BgMoriBigst* this, PlayState* play) { if ((this->dyna.actor.home.rot.z == 0 || // Check if all enemies are defeated instead of the regular stalfos when enemy randomizer or crowd control is on. - (Flags_GetTempClear(play, this->dyna.actor.room) && (CVarGetInteger("gRandomizedEnemies", 0) || (CVarGetInteger("gCrowdControl", 0))))) && + (Flags_GetTempClear(play, this->dyna.actor.room) && (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger("gCrowdControl", 0))))) && !Player_InCsMode(play)) { Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); BgMoriBigst_SetupDone(this, play); diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c index 8392e7224..4944c8455 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c @@ -94,7 +94,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) { if (this->dyna.unk_150 > 0.001f) { this->timer++; - if ((this->timer > (28 - CVarGetInteger("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(play)) { + if ((this->timer > (28 - CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 4)) && !Player_InCsMode(play)) { BgMoriKaitenkabe_SetupRotate(this); func_8002DF54(play, &this->dyna.actor, 8); Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos); @@ -118,7 +118,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) { void BgMoriKaitenkabe_SetupRotate(BgMoriKaitenkabe* this) { this->actionFunc = BgMoriKaitenkabe_Rotate; - this->rotSpeed = CVarGetInteger("gFasterBlockPush", 0) * 0.1f; + this->rotSpeed = CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.1f; this->rotYdeg = 0.0f; } diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c index a2fca0db7..5f53bb878 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c @@ -387,8 +387,8 @@ void BgPoEvent_BlockPush(BgPoEvent* this, PlayState* play) { s32 blockStop; Player* player = GET_PLAYER(play); - this->dyna.actor.speedXZ = this->dyna.actor.speedXZ + (CVarGetInteger("gFasterBlockPush", 0) * 0.3) + 0.5f; - this->dyna.actor.speedXZ = CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f + (CVarGetInteger("gFasterBlockPush", 0) * 0.5)); + this->dyna.actor.speedXZ = this->dyna.actor.speedXZ + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.3) + 0.5f; + this->dyna.actor.speedXZ = CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.5)); blockStop = Math_StepToF(&sBgPoEventblockPushDist, 20.0f, this->dyna.actor.speedXZ); displacement = this->direction * sBgPoEventblockPushDist; this->dyna.actor.world.pos.x = (Math_SinS(this->dyna.unk_158) * displacement) + this->dyna.actor.home.pos.x; @@ -403,7 +403,7 @@ void BgPoEvent_BlockPush(BgPoEvent* this, PlayState* play) { this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z; sBgPoEventblockPushDist = 0.0f; this->dyna.actor.speedXZ = 0.0f; - this->direction = 5 - ((CVarGetInteger("gFasterBlockPush", 0) * 3) / 5); + this->direction = 5 - ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 3) / 5); sBgPoEventBlocksAtRest++; this->actionFunc = BgPoEvent_BlockIdle; if (this->type == 1) { diff --git a/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c b/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c index 4385c4341..d1fdca048 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot15_Rrbox/z_bg_spot15_rrbox.c @@ -260,9 +260,9 @@ void func_808B4194(BgSpot15Rrbox* this, PlayState* play) { s32 approxFResult; Actor* actor = &this->dyna.actor; - this->unk_174 = this->unk_174 + ((CVarGetInteger("gFasterBlockPush", 0) / 2) * 0.5) + 0.5f; + this->unk_174 = this->unk_174 + ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) / 2) * 0.5) + 0.5f; - this->unk_174 = CLAMP_MAX(this->unk_174, 2.0f + (CVarGetInteger("gFasterBlockPush", 0) * 0.5)); + this->unk_174 = CLAMP_MAX(this->unk_174, 2.0f + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.5)); approxFResult = Math_StepToF(&this->unk_178, 20.0f, this->unk_174); @@ -294,7 +294,7 @@ void func_808B4194(BgSpot15Rrbox* this, PlayState* play) { this->dyna.unk_150 = 0.0f; this->unk_178 = 0.0f; this->unk_174 = 0.0f; - this->unk_168 = 10 - ((CVarGetInteger("gFasterBlockPush", 0) * 3) / 2); + this->unk_168 = 10 - ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 3) / 2); func_808B4084(this, play); } Audio_PlayActorSound2(actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot18_Basket/z_bg_spot18_basket.c b/soh/src/overlays/actors/ovl_Bg_Spot18_Basket/z_bg_spot18_basket.c index 8233ffeac..2d81c8610 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot18_Basket/z_bg_spot18_basket.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot18_Basket/z_bg_spot18_basket.c @@ -297,7 +297,7 @@ void func_808B7F74(BgSpot18Basket* this) { shapeRotY = this->dyna.actor.shape.rot.y; this->actionFunc = func_808B7FC0; - if ((shapeRotY < -0x2E93) || (shapeRotY >= 0x7C19) || CVarGetInteger("gGoronPot", 0)) { + if ((shapeRotY < -0x2E93) || (shapeRotY >= 0x7C19) || CVarGetInteger(CVAR_ENHANCEMENT("GoronPot"), 0)) { this->unk_218 = 2; } else if (shapeRotY < 0x26C2) { this->unk_218 = 1; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 97551ca46..65420de32 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -1240,7 +1240,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { static Color_RGBA8 bloodPrimColor = { 0, 120, 0, 255 }; static Color_RGBA8 bloodEnvColor = { 0, 120, 0, 255 }; - if(CVarGetInteger("gRedGanonBlood", 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("RedGanonBlood"), 0)) { bloodPrimColor.r = 120; bloodPrimColor.g = 0; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index ba4a4fbc6..4de5ab068 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -1486,7 +1486,7 @@ void func_8090109C(BossGanon2* this, PlayState* play) { static Color_RGBA8 sPrimColor = { 0, 120, 0, 255 }; static Color_RGBA8 sEnvColor = { 0, 120, 0, 255 }; - if(CVarGetInteger("gRedGanonBlood", 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("RedGanonBlood"), 0)) { sPrimColor.r = 120; sPrimColor.g = 0; diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 6de72fd2d..049cb3da5 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -445,7 +445,7 @@ void BossGoma_SetupCeilingIdle(BossGoma* this) { void BossGoma_SetupFallJump(BossGoma* this) { // When in Enemy Randomizer, reset the state of the spawned Gohma Larva because it's not done // by the (non-existent) Larva themselves. - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { this->childrenGohmaState[0] = this->childrenGohmaState[1] = this->childrenGohmaState[2] = 0; } Animation_Change(&this->skelanime, &gGohmaLandAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -5.0f); @@ -1559,14 +1559,14 @@ void BossGoma_CeilingIdle(BossGoma* this, PlayState* play) { if (this->framesUntilNextAction == 0) { Actor* nearbyEnTest = NULL; - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { nearbyEnTest = Actor_FindNearby(play, &this->actor, -1, ACTORCAT_ENEMY, 8000.0f); } if (this->childrenGohmaState[0] == 0 && this->childrenGohmaState[1] == 0 && this->childrenGohmaState[2] == 0) { // if no child gohma has been spawned BossGoma_SetupCeilingPrepareSpawnGohmas(this); } else if ((this->childrenGohmaState[0] < 0 && this->childrenGohmaState[1] < 0 && this->childrenGohmaState[2] < 0) || - (nearbyEnTest == NULL && CVarGetInteger("gRandomizedEnemies", 0))) { + (nearbyEnTest == NULL && CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0))) { // In authentic gameplay, check if all baby Ghomas are dead. In Enemy Randomizer, check if there's no enemies alive. BossGoma_SetupFallJump(this); } else { diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index b9f5c6f2c..d7be78fab 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -360,7 +360,7 @@ void BossSst_HeadSetupLurk(BossSst* this) { } void BossSst_HeadLurk(BossSst* this, PlayState* play) { - if (CVarGetInteger("gQuickBongoKill", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) { this->colliderCyl.base.acFlags |= AC_ON; } @@ -371,7 +371,7 @@ void BossSst_HeadLurk(BossSst* this, PlayState* play) { void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { //Make sure to restore original behavior if the quick kill didn't happen - if (CVarGetInteger("gQuickBongoKill", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) { this->colliderCyl.base.acFlags &= ~AC_ON; } @@ -2665,7 +2665,7 @@ void BossSst_UpdateHead(Actor* thisx, PlayState* play) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderJntSph.base); } - if ((this->actionFunc != BossSst_HeadLurk || CVarGetInteger("gQuickBongoKill", 0)) && (this->actionFunc != BossSst_HeadIntro)) { + if ((this->actionFunc != BossSst_HeadLurk || CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) && (this->actionFunc != BossSst_HeadIntro)) { if (this->colliderCyl.base.acFlags & AC_ON) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->colliderCyl.base); } diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index 22c850111..27155289b 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -182,7 +182,7 @@ void DoorAna_Update(Actor* thisx, PlayState* play) { this->actionFunc(this, play); // Changes the grottos facing angle based on camera angle - if (!CVarGetInteger("gDisableGrottoRotation", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableGrottoRotation"), 0)) { this->actor.shape.rot.y = Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000; } } diff --git a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c index 3fe7fc689..13b960f55 100644 --- a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c +++ b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c @@ -110,7 +110,7 @@ void ElfMsg_Destroy(Actor* thisx, PlayState* play) { s32 ElfMsg_GetMessageId(ElfMsg* this) { // Negative message ID forces link to talk to Navi - if (this->actor.params & 0x8000 || CVarGetInteger("gNoForcedNavi", 0) != 0) { + if (this->actor.params & 0x8000 || CVarGetInteger(CVAR_ENHANCEMENT("NoForcedNavi"), 0) != 0) { return (this->actor.params & 0xFF) + 0x100; } else { return -((this->actor.params & 0xFF) + 0x100); diff --git a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c index 8347c631a..c62e3a8fa 100644 --- a/soh/src/overlays/actors/ovl_En_Am/z_en_am.c +++ b/soh/src/overlays/actors/ovl_En_Am/z_en_am.c @@ -670,7 +670,7 @@ void EnAm_Statue(EnAm* this, PlayState* play) { Player* player = GET_PLAYER(play); f32 temp158f = this->dyna.unk_158; s16 moveDir = 0; - s32 blockSpeed = CVarGetInteger("gFasterBlockPush", 0); + s32 blockSpeed = CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0); if (this->unk_258 == 0) { if (this->dyna.unk_150 != 0.0f) { diff --git a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c index 740aea6c4..0b1a2b0b7 100644 --- a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c +++ b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c @@ -116,7 +116,7 @@ void func_809B27D8(EnAnubiceFire* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); this->cylinder.base.atFlags &= 0xFFE9; this->cylinder.base.atFlags |= 8; - this->cylinder.info.toucher.dmgFlags = CVarGetInteger("gAnubisFix", 0) ? 0x800 : 2; + this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubixFix"), 0) ? 0x800 : 2; this->unk_15A = 30; this->actor.params = 1; this->actor.velocity.x *= -1.0f; diff --git a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c index 816dcf091..d612475d4 100644 --- a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c +++ b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c @@ -104,8 +104,8 @@ void EnBlkobj_DarkLinkFight(EnBlkobj* this, PlayState* play) { // Check for if Dark Link is defeated in authentic gameplay. // Check for if all enemies are defeated with enemy randomizer or crowd control on. uint8_t roomCleared = - (!CVarGetInteger("gRandomizedEnemies", 0) && !CVarGetInteger("gCrowdControl", 0) && Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) || - ((CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0)) && Flags_GetTempClear(play, this->dyna.actor.room)); + (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && !CVarGetInteger("gCrowdControl", 0) && Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) || + ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) && Flags_GetTempClear(play, this->dyna.actor.room)); if (roomCleared) { Flags_SetClear(play, this->dyna.actor.room); this->timer++; diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index baa1db8f5..434556a51 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -125,7 +125,7 @@ void EnBom_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->bombCollider, thisx, &sCylinderInit); Collider_SetJntSph(play, &this->explosionCollider, thisx, &sJntSphInit, &this->explosionColliderItems[0]); this->explosionColliderItems[0].info.toucher.damage += (thisx->shape.rot.z & 0xFF00) >> 8; - if (CVarGetInteger("gNutsExplodeBombs", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NutsExplodeBombs"), 0)) { this->bombCollider.info.bumper.dmgFlags |= 1; } @@ -199,7 +199,7 @@ void EnBom_Explode(EnBom* this, PlayState* play) { func_800AA000(this->actor.xzDistToPlayer, 0xFF, 0x14, 0x96); } - if (CVarGetInteger("gStaticExplosionRadius", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("StaticExplosionRadius"), 0)) { //72 is the maximum radius of an OoT bomb explosion this->explosionCollider.elements[0].dim.worldSphere.radius = 72; } else { @@ -397,7 +397,7 @@ void EnBom_Draw(Actor* thisx, PlayState* play) { if (thisx->params == BOMB_BODY) { Gfx_SetupDL_25Opa(play->state.gfxCtx); - if (!CVarGetInteger("gDisableBombBillboarding", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableBombBillboarding"), 0)) { Matrix_ReplaceRotation(&play->billboardMtxF); } func_8002EBCC(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 76c0feac3..eccfe98b0 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -69,7 +69,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { Actor_SetScale(&this->actor, 0.013f); for (i = 0; i < 2; i++) { - if(CVarGetInteger("gCustomizeBombchuBowling", 0) && CVarGetInteger(i == 0 ? "gBombchuBowlingNoSmallCucco" : "gBombchuBowlingNoBigCucco", 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco") : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), 0)) { continue; } @@ -327,8 +327,8 @@ void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) { Rupees_ChangeBy(-30); this->minigamePlayStatus = 1; this->wallStatus[0] = this->wallStatus[1] = 0; - if(CVarGetInteger("gCustomizeBombchuBowling", 0)) { - play->bombchuBowlingStatus = CVarGetInteger("gBombchuBowlingAmmunition", 10); + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0)) { + play->bombchuBowlingStatus = CVarGetInteger(CVAR_ENHANCEMENT("BombchuBowlingAmmo"), 10); } else { play->bombchuBowlingStatus = 10; diff --git a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index 02ff9140d..4fcaa88e2 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -139,7 +139,7 @@ void EnBomChu_UpdateFloorPoly(EnBomChu* this, CollisionPoly* floorPoly, PlayStat f32 normDotUp; MtxF mf; - if (CVarGetInteger("gBombchusOOB", 0) && floorPoly == NULL) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BombchusOOB"), 0) && floorPoly == NULL) { EnBomChu_Explode(this, play); return; } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index dfd8fae27..7ec29b818 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -629,7 +629,7 @@ void EnBox_Update(Actor* thisx, PlayState* play) { if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) || (IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) && this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { - if (!CVarGetInteger("gAddTraps.enabled", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0)) { EnBox_SpawnIceSmoke(this, play); } } @@ -637,8 +637,8 @@ void EnBox_Update(Actor* thisx, PlayState* play) { void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { EnBox_CreateExtraChestTextures(); - int csmc = CVarGetInteger("gChestSizeAndTextureMatchesContents", CSMC_DISABLED); - int requiresStoneAgony = CVarGetInteger("gChestSizeDependsStoneOfAgony", 0); + int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); + int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); GetItemCategory getItemCategory; int isVanilla = csmc == CSMC_DISABLED || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)) || diff --git a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c index 6be3a219f..c4ed47bf6 100644 --- a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c +++ b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c @@ -262,7 +262,7 @@ void EnClearTag_Init(Actor* thisx, PlayState* play) { // Change Arwing to regular enemy instead of boss with enemy randomizer and crowd control. // This way Arwings will be considered for "clear enemy" rooms properly. - if (CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); } @@ -478,7 +478,7 @@ void EnClearTag_Update(Actor* thisx, PlayState* play2) { // Introduce a range requirement in Enemy Rando so Arwings don't shoot the player from // across the map. Especially noticeable in big maps like Lake Hylia and Hyrule Field. - uint8_t enemyRandoShootLaser = !CVarGetInteger("gRandomizedEnemies", 0) || this->actor.xzDistToPlayer < 1000.0f; + uint8_t enemyRandoShootLaser = !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || this->actor.xzDistToPlayer < 1000.0f; // Check if the Arwing should fire its laser. if ((this->frameCounter % 4) == 0 && (Rand_ZeroOne() < 0.75f) && diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 04123c7b3..1a799763a 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -123,7 +123,7 @@ void EnCow_Init(Actor* thisx, PlayState* play) { func_809DEE9C(this); this->actionFunc = func_809DF96C; if (play->sceneNum == SCENE_LINKS_HOUSE) { - if (!LINK_IS_ADULT && !CVarGetInteger("gCowOfTime", 0)) { + if (!LINK_IS_ADULT && !CVarGetInteger(CVAR_ENHANCEMENT("CowOfTime"), 0)) { Actor_Kill(&this->actor); return; } diff --git a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c index b1b967220..bb7236e04 100644 --- a/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/soh/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -364,7 +364,7 @@ void EnCrow_Die(EnCrow* this, PlayState* play) { } else { Item_DropCollectible(play, &this->actor.world.pos, ITEM00_RUPEE_RED); } - if (!CVarGetInteger("gRandomizedEnemies", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { EnCrow_SetupRespawn(this); } else { Actor_Kill(this); diff --git a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c index 38a1cf95b..2c49accfe 100644 --- a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c +++ b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c @@ -373,7 +373,7 @@ void EnDog_FollowPlayer(EnDog* this, PlayState* play) { return; } - if (CVarGetInteger("gDogFollowsEverywhere", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0)) { // If the dog is too far away it's usually because they are stuck in a hole or on a different floor, this gives them a push if (this->actor.xyzDistToPlayerSq > 250000.0f) { Player* player = GET_PLAYER(play); @@ -394,7 +394,7 @@ void EnDog_FollowPlayer(EnDog* this, PlayState* play) { } if (this->actor.xzDistToPlayer > 400.0f) { - if (CVarGetInteger("gDogFollowsEverywhere", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0)) { // Instead of stopping following when the dog gets too far, just speed them up. speed = this->actor.xzDistToPlayer / 25.0f; } else { @@ -419,7 +419,7 @@ void EnDog_FollowPlayer(EnDog* this, PlayState* play) { Math_ApproachF(&this->actor.speedXZ, speed, 0.6f, 1.0f); - if (!(this->actor.xzDistToPlayer > 400.0f) || CVarGetInteger("gDogFollowsEverywhere", 0)) { + if (!(this->actor.xzDistToPlayer > 400.0f) || CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0)) { Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 10, 1000, 1); this->actor.shape.rot = this->actor.world.rot; } diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c index 2a571e34e..cbfd5f018 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c @@ -349,11 +349,11 @@ void EnDoor_Draw(Actor* thisx, PlayState* play) { } } if (this->lockTimer != 0) { - if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 0)) { Matrix_Push(); } Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); - if (CVarGetInteger("gShowDoorLocksOnBothSides", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 0)) { Matrix_Pop(); Matrix_RotateZYX(0, 0x8000, 0, MTXMODE_APPLY); Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index 19af8a4c5..0327cb445 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -276,7 +276,7 @@ void func_809FE040(EnDu* this) { this->unk_1E6 = 0; } // #region SOH[Enhancement] - if (CVarGetInteger("gEnhancements.FixDaruniaDanceSpeed", 1)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfoFix, animationIndices[this->unk_1E6]); // #endregion } else { @@ -298,7 +298,7 @@ void func_809FE104(EnDu* this) { this->unk_1E6++; if (this->unk_1E6 < 4) { // #region SOH[Enhancement] - if (CVarGetInteger("gEnhancements.FixDaruniaDanceSpeed", 1) && this->unk_1E6 <= 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1) && this->unk_1E6 <= 1) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfoFix, animationIndices[this->unk_1E6]); // #endregion } else { @@ -498,7 +498,7 @@ void func_809FE890(EnDu* this, PlayState* play) { if (csAction->action == 7 || csAction->action == 8) { this->unk_1E6 = 0; // #region SOH[Enhancement] - if (CVarGetInteger("gEnhancements.FixDaruniaDanceSpeed", 1)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfoFix, ENDU_ANIM_7); // #endregion } else { diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index f996fe6c1..eba2799b7 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -631,15 +631,15 @@ void func_80A0329C(EnElf* this, PlayState* play) { if ((heightDiff > 0.0f) && (heightDiff < 60.0f)) { if (!func_80A01F90(&this->actor.world.pos, &refActor->actor.world.pos, 10.0f)) { - if (CVarGetInteger("gFairyEffect", 0) && !(this->fairyFlags & FAIRY_FLAG_BIG)) + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyEffect"), 0) && !(this->fairyFlags & FAIRY_FLAG_BIG)) { - if (CVarGetInteger("gFairyPercentRestore", 0)) + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyPercentRestore"), 0)) { - Health_ChangeBy(play, (gSaveContext.healthCapacity * CVarGetInteger("gFairyHealth", 100) / 100 + 15) / 16 * 16); + Health_ChangeBy(play, (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("FairyHealth"), 100) / 100 + 15) / 16 * 16); } else { - Health_ChangeBy(play, CVarGetInteger("gFairyHealth", 8) * 16); + Health_ChangeBy(play, CVarGetInteger(CVAR_ENHANCEMENT("FairyHealth"), 8) * 16); } } else diff --git a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c index 146f0deaa..74d5fcd06 100644 --- a/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c +++ b/soh/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c @@ -169,7 +169,7 @@ void EnEncount1_SpawnLeevers(EnEncount1* this, PlayState* play) { break; } } - int32_t modifiedSpawnRate = CVarGetInteger("gEnhancements.LeeverSpawnRate", 0); + int32_t modifiedSpawnRate = CVarGetInteger(CVAR_ENHANCEMENT("LeeverSpawnRate"), 0); if (modifiedSpawnRate) { this->timer = 20 * modifiedSpawnRate; } @@ -248,9 +248,9 @@ void EnEncount1_SpawnStalchildOrWolfos(EnEncount1* this, PlayState* play) { // been spawned and/or killed. int8_t enemyCount = play->actorCtx.actorLists[ACTORCAT_ENEMY].length; if ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || - (CVarGetInteger("gRandomizedEnemies", 0) && enemyCount < 15)) { + (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && enemyCount < 15)) { while ((this->curNumSpawn < this->maxCurSpawns && this->totalNumSpawn < this->maxTotalSpawns) || - (CVarGetInteger("gRandomizedEnemies", 0) && enemyCount < 15)) { + (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && enemyCount < 15)) { if (play->sceneNum == SCENE_HYRULE_FIELD) { if ((player->floorSfxOffset == 0) || (player->actor.floorBgId != BGCHECK_SCENE) || !(player->actor.bgCheckFlags & 1) || (player->stateFlags1 & PLAYER_STATE1_IN_WATER)) { @@ -282,7 +282,7 @@ void EnEncount1_SpawnStalchildOrWolfos(EnEncount1* this, PlayState* play) { break; } if ((player->actor.yDistToWater != BGCHECK_Y_MIN) && - (floorY < (player->actor.world.pos.y + player->actor.yDistToWater*(CVarGetInteger("gEnemySpawnsOverWaterboxes", 0) ? 1 : -1)))) { + (floorY < (player->actor.world.pos.y + player->actor.yDistToWater*(CVarGetInteger(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 0) ? 1 : -1)))) { break; } spawnPos.y = floorY; diff --git a/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c b/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c index 834096220..37ceedb87 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c @@ -388,7 +388,7 @@ void EnExRuppy_Draw(Actor* thisx, PlayState* play) { if (!this->invisible) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { // purple/gold rupees need less scaling f32 mtxScale = this->colorIdx >= 3 ? 17.5f : 25.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c index e6e096e47..ce0d39ded 100644 --- a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c +++ b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c @@ -212,7 +212,7 @@ void EnGSwitch_SilverRupeeTracker(EnGSwitch* this, PlayState* play) { static s8 majorScale[] = { 0, 2, 4, 5, 7, 9, 11, 13, 15, 17 }; if (this->noteIndex < sCollectedCount) { - if (sCollectedCount < (CVarGetInteger("gSilverRupeeJingleExtend", 0) ? 10 : 5)) { + if (sCollectedCount < (CVarGetInteger(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 0) ? 10 : 5)) { // "sound?" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex); Audio_PlaySoundTransposed(&D_801333D4, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]); @@ -480,7 +480,7 @@ void EnGSwitch_DrawRupee(Actor* thisx, PlayState* play) { if (!this->broken) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger("gNewDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0)) { // purple/gold/silver rupees need less scaling f32 mtxScale = this->colorIdx >= 3 ? 17.5f : 25.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index 90d2981f0..f19ce1bae 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -252,7 +252,7 @@ s32 EnGe3_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p rot->x += this->headRot.y; default: - if (CVarGetInteger("gGerudoWarriorClothingFix", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 0)) { // This is a hack to fix the color-changing clothes this Gerudo has on N64 versions OPEN_DISPS(play->state.gfxCtx); switch (limbIndex) { diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 6aa1b7d41..11c29227f 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -493,7 +493,7 @@ s32 EnGirlA_CanBuy_DekuNuts(PlayState* play, EnGirlA* this) { if (gSaveContext.rupees < this->basePrice) { return CANBUY_RESULT_NEED_RUPEES; } - if ((Item_CheckObtainability(ITEM_NUT) == ITEM_NONE) && !CVarGetInteger("gFastDrops", 0)) { + if ((Item_CheckObtainability(ITEM_NUT) == ITEM_NONE) && !CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { return CANBUY_RESULT_SUCCESS_FANFARE; } return CANBUY_RESULT_SUCCESS; @@ -506,7 +506,7 @@ s32 EnGirlA_CanBuy_DekuSticks(PlayState* play, EnGirlA* this) { if (gSaveContext.rupees < this->basePrice) { return CANBUY_RESULT_NEED_RUPEES; } - if ((Item_CheckObtainability(ITEM_STICK) == ITEM_NONE) && !CVarGetInteger("gFastDrops", 0)) { + if ((Item_CheckObtainability(ITEM_STICK) == ITEM_NONE) && !CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { return CANBUY_RESULT_SUCCESS_FANFARE; } return CANBUY_RESULT_SUCCESS; @@ -705,7 +705,7 @@ s32 EnGirlA_CanBuy_DekuSeeds(PlayState* play, EnGirlA* this) { if (gSaveContext.rupees < this->basePrice) { return CANBUY_RESULT_NEED_RUPEES; } - if ((Item_CheckObtainability(ITEM_SEEDS) == ITEM_NONE) && !CVarGetInteger("gFastDrops", 0)) { + if ((Item_CheckObtainability(ITEM_SEEDS) == ITEM_NONE) && !CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { return CANBUY_RESULT_SUCCESS_FANFARE; } return CANBUY_RESULT_SUCCESS; diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 3094f2171..777c1cff2 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -98,7 +98,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { if (!IS_RANDO && gSaveContext.bgsFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { - if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (Environment_GetBgsDayCount() >= CVarGetInteger(CVAR_ENHANCEMENT("ForgeTime"), 3)) { return 0x305E; } else { return 0x305D; diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index a4aede2e5..5f1c8fa03 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -1082,7 +1082,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { textId = 0x3003; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + } else if (Environment_GetBgsDayCount() >= CVarGetInteger(CVAR_ENHANCEMENT("ForgeTime"), 3)) { textId = 0x305E; } else { textId = 0x305D; @@ -1091,7 +1091,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { } else { if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { textId = 0x305E; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + } else if (Environment_GetBgsDayCount() >= CVarGetInteger(CVAR_ENHANCEMENT("ForgeTime"), 3)) { textId = 0x3002; } else { textId = 0x305D; diff --git a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c index 391d7dc5d..ccb14cdbd 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c +++ b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c @@ -337,9 +337,9 @@ void func_80A56B40(EnHeishi4* this, PlayState* play) { Player* player = GET_PLAYER(play); // Only allow sneaking when not wearing a mask as that triggers different dialogue. MM Bunny hood disables // these interactions, so bunny hood is fine in that case. - if (CVarGetInteger("gMarketSneak", 0) && + if (CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && (player->currentMask == PLAYER_MASK_NONE || - (player->currentMask == PLAYER_MASK_BUNNY && CVarGetInteger("gMMBunnyHood", 0)))) { + (player->currentMask == PLAYER_MASK_BUNNY && CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), 0)))) { this->actionFunc = EnHeishi4_MarketSneak; } else { this->actionFunc = func_80A56614; diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index e0ff7470d..f02609d00 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -438,7 +438,7 @@ u16 func_80A6F810(PlayState* play, Actor* thisx) { if (followingDog != 0) { this->unk_215 = false; - return ((followingDog == 1) || (CVarGetInteger("gAllDogsRichard", 0))) ? 0x709F : 0x709E; + return ((followingDog == 1) || (CVarGetInteger(CVAR_ENHANCEMENT("AllDogsRichard"), 0))) ? 0x709F : 0x709E; } else { return 0x709D; } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index aaf0e0342..ac8c0b7bd 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -233,7 +233,7 @@ void func_80A74398(Actor* thisx, PlayState* play) { Effect_Add(play, &this->blureIdx, EFFECT_BLURE1, 0, 0, &blureInit); func_80A74714(this); - uint8_t enemyRandoCCActive = CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0); + uint8_t enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); if (this->switchFlags != 0xFF) { // In vanilla gameplay, Iron Knuckles are despawned based on specific flags in specific scenarios. @@ -303,7 +303,7 @@ void func_80A747C0(EnIk* this, PlayState* play) { this->skelAnime.playSpeed = 1.0f; // Disable miniboss music with Enemy Randomizer because the music would keep // playing if the enemy was never defeated, which is common with Enemy Randomizer. - if (!CVarGetInteger("gRandomizedEnemies", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { func_800F5ACC(NA_BGM_MINI_BOSS); } } @@ -663,7 +663,7 @@ void func_80A75A38(EnIk* this, PlayState* play) { Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xB0); // Don't set flag when Enemy Rando or CrowdControl are on. // Instead Iron Knuckles rely on the "clear room" flag. - if (this->switchFlags != 0xFF && !CVarGetInteger("gRandomizedEnemies", 0) && !CVarGetInteger("gCrowdControl", 0)) { + if (this->switchFlags != 0xFF && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && !CVarGetInteger("gCrowdControl", 0)) { Flags_SetSwitch(play, this->switchFlags); } Actor_Kill(&this->actor); @@ -1484,7 +1484,7 @@ void EnIk_Init(Actor* thisx, PlayState* play) { } // Immediately trigger Iron Knuckle for Enemy Rando and Crowd Control - if ((CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0)) && (thisx->params == 2 || thisx->params == 3)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) && (thisx->params == 2 || thisx->params == 3)) { this->skelAnime.playSpeed = 1.0f; } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c index 0a118916b..4bec916e2 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c @@ -118,7 +118,7 @@ void func_80A90264(EnKakasi2* this, PlayState* play) { this->unk_194++; bool skipScarecrow = play->msgCtx.msgMode == MSGMODE_OCARINA_PLAYING && - ((CVarGetInteger("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet) || + ((CVarGetInteger(CVAR_ENHANCEMENT("InstantScarecrow"), 0) && gSaveContext.scarecrowSpawnSongSet) || (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG))); if ((BREG(1) != 0) || skipScarecrow && (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 25299f5b0..1f813c2d6 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1095,7 +1095,7 @@ void func_80A98DB4(EnKo* this, PlayState* play) { dist = this->actor.xzDistToPlayer; } - if (CVarGetInteger("gDisableKokiriDrawDistance", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), 0) != 0) { this->appearDist = 32767.0f; Math_SmoothStepToF(&this->modelAlpha, (this->appearDist < dist) ? 0.0f : 255.0f, 0.3f, 40.0f, 1.0f); f32 test = this->appearDist; diff --git a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c index 75e54c140..04b0ca1e3 100644 --- a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c +++ b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c @@ -137,9 +137,9 @@ void EnKusa_DropCollectible(EnKusa* this, PlayState* play) { Item_DropCollectibleRandom(play, NULL, &this->actor.world.pos, dropParams << 4); break; case ENKUSA_TYPE_1: - if (CVarGetInteger("gNoRandomDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) { } - else if (CVarGetInteger("gNoHeartDrops", 0)) { + else if (CVarGetInteger(CVAR_ENHANCEMENT("NoHeartDrops"), 0)) { Item_DropCollectible(play, &this->actor.world.pos, ITEM00_SEEDS); } else if (Rand_ZeroOne() < 0.5f) { diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index ad3bd0ab5..8e61e5517 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -301,7 +301,7 @@ s32 EnKz_FollowPath(EnKz* this, PlayState* play) { pathDiffZ = pointPos->z - this->actor.world.pos.z; Math_SmoothStepToS(&this->actor.world.rot.y, (Math_FAtan2F(pathDiffX, pathDiffZ) * (0x8000 / M_PI)), 0xA, 0x3E8, 1); - if ((SQ(pathDiffX) + SQ(pathDiffZ)) < 10.0f * CVarGetInteger("gMweepSpeed", 1)) { + if ((SQ(pathDiffX) + SQ(pathDiffZ)) < 10.0f * CVarGetInteger(CVAR_ENHANCEMENT("MweepSpeed"), 1)) { this->waypoint++; if (this->waypoint >= path->count) { this->waypoint = 0; @@ -415,7 +415,7 @@ void EnKz_SetupMweep(EnKz* this, PlayState* play) { initPos.z += 260.0f; Play_CameraSetAtEye(play, this->cutsceneCamera, &pos, &initPos); func_8002DF54(play, &this->actor, 8); - this->actor.speedXZ = 0.1f * CVarGetInteger("gMweepSpeed", 1); + this->actor.speedXZ = 0.1f * CVarGetInteger(CVAR_ENHANCEMENT("MweepSpeed"), 1); this->actionFunc = EnKz_Mweep; } diff --git a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c index 43f6a6665..b0aff3750 100644 --- a/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c +++ b/soh/src/overlays/actors/ovl_En_Mb/z_en_mb.c @@ -512,7 +512,7 @@ void EnMb_SetupClubAttack(EnMb* this) { // Rotate Club Moblin towards player in Enemy Randomizer because they're // borderline useless otherwise in most scenarios. - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); } @@ -717,7 +717,7 @@ void EnMb_ClubWaitAfterAttack(EnMb* this, PlayState* play) { // Rotate Club Moblin towards player in Enemy Randomizer because they're // borderline useless otherwise in most scenarios. - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); } @@ -844,7 +844,7 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) { // Rotate Club Moblin towards player in Enemy Randomizer because they're // borderline useless otherwise in most scenarios. - if (!CVarGetInteger("gRandomizedEnemies", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { Math_SmoothStepToS(&this->actor.shape.rot.y, relYawTarget[this->attack - 1] + this->actor.world.rot.y, 1, 0x2EE, 0); } else { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); @@ -891,7 +891,7 @@ void EnMb_ClubAttack(EnMb* this, PlayState* play) { // Disable camera shake when the Moblin attacks with Enemy Randomizer enabled. // This camera shake gets very annoying as these Moblins can spawn in many rooms, // and also often (initially) out of reach for the player. - if (!CVarGetInteger("gRandomizedEnemies", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { Camera_AddQuake(&play->mainCamera, 2, 0x19, 5); } func_800358DC(&this->actor, &effSpawnPos, &this->actor.world.rot, flamesParams, 20, flamesUnused, play, @@ -1267,7 +1267,7 @@ void EnMb_ClubWaitPlayerNear(EnMb* this, PlayState* play) { // Rotate Club Moblin towards player in Enemy Randomizer because they're // borderline useless otherwise in most scenarios. - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 100.0f, 0); } @@ -1278,7 +1278,7 @@ void EnMb_ClubWaitPlayerNear(EnMb* this, PlayState* play) { // Add a height check to the Moblin's Club attack when Enemy Randomizer is on. // Without the height check, the Moblin will attack (and play the sound effect) a lot even though // the Moblin is very far away from the player in vertical rooms (like the first room in Deku Tree). - s8 enemyRando = CVarGetInteger("gRandomizedEnemies", 0); + s8 enemyRando = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0); if (!enemyRando || (enemyRando && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) { EnMb_SetupClubAttack(this); } diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index 9181b452b..7cdce3852 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -638,7 +638,7 @@ void func_80AAB5A4(EnMd* this, PlayState* play) { f32 temp; if (play->sceneNum != SCENE_MIDOS_HOUSE) { - if (CVarGetInteger("gDisableKokiriDrawDistance", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), 0) != 0) { temp = (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && (play->sceneNum == SCENE_KOKIRI_FOREST)) ? 100.0f diff --git a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c index 91730e5bf..3f94ac8ea 100644 --- a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c +++ b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c @@ -666,7 +666,7 @@ void func_80AB6D08(EnNiw* this, PlayState* play) { } this->path = 1; - this->timer5 = 80 * CVarGetInteger("gCuccoStayDurationMultiplier", 1); + this->timer5 = 80 * CVarGetInteger(CVAR_ENHANCEMENT("CuccoStayDurationMult"), 1); this->actor.speedXZ = 0.0f; this->actor.velocity.y = 4.0f; } else { diff --git a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c index 2add8c4a9..63f4fe3a3 100644 --- a/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c +++ b/soh/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c @@ -75,7 +75,7 @@ void EnNutsball_Init(Actor* thisx, PlayState* play) { ActorShape_Init(&this->actor.shape, 400.0f, ActorShadow_DrawCircle, 13.0f); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { this->objBankIndex = 0; } else { this->objBankIndex = Object_GetIndex(&play->objectCtx, sObjectIDs[this->actor.params]); @@ -176,7 +176,7 @@ void EnNutsball_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger("gNewDrops", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 6), diff --git a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 9533e8309..5d75b7343 100644 --- a/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/soh/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -506,7 +506,7 @@ void EnOkuta_ProjectileFly(EnOkuta* this, PlayState* play) { pos.x = this->actor.world.pos.x; pos.y = this->actor.world.pos.y + 11.0f; pos.z = this->actor.world.pos.z; - if (CVarGetInteger("gNewDrops", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) { static s16 sEffectScales[] = { 145, 135, 115, 85, 75, 53, 45, 40, 35, }; @@ -763,7 +763,7 @@ void EnOkuta_Draw(Actor* thisx, PlayState* play) { } else { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger("gNewDrops", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NewDrops"), 0) != 0) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 6), diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 303c58819..93d51171c 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -373,7 +373,7 @@ void func_80ACA7E0(EnOwl* this, PlayState* play) { void EnOwl_ConfirmKokiriMessage(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x2065); @@ -402,7 +402,7 @@ void EnOwl_WaitOutsideKokiri(EnOwl* this, PlayState* play) { void func_80ACA998(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x2069); @@ -448,7 +448,7 @@ void EnOwl_WaitHyruleCastle(EnOwl* this, PlayState* play) { void func_80ACAB88(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: // obtained zelda's letter @@ -491,7 +491,7 @@ void EnOwl_WaitKakariko(EnOwl* this, PlayState* play) { void func_80ACAD34(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x206F); @@ -529,7 +529,7 @@ void EnOwl_WaitGerudo(EnOwl* this, PlayState* play) { void func_80ACAEB8(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x2071); @@ -651,7 +651,7 @@ void EnOwl_WaitDeathMountainShortcut(EnOwl* this, PlayState* play) { void func_80ACB344(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x607A); @@ -676,7 +676,7 @@ void func_80ACB3E0(EnOwl* this, PlayState* play) { void func_80ACB440(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x10C1); @@ -713,7 +713,7 @@ void EnOwl_WaitLWPreSaria(EnOwl* this, PlayState* play) { void func_80ACB5C4(EnOwl* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(play)) { // swap the order of the responses if better owl is enabled - uint8_t index = CVarGetInteger("gBetterOwl", 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); + uint8_t index = CVarGetInteger(CVAR_ENHANCEMENT("BetterOwl"), 0) == 0 ? play->msgCtx.choiceIndex : (1 - play->msgCtx.choiceIndex); switch (index) { case OWL_REPEAT: Message_ContinueTextbox(play, 0x10C5); diff --git a/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c b/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c index 7b444f241..5526ad49c 100644 --- a/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c +++ b/soh/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c @@ -328,7 +328,7 @@ void EnPeehat_Ground_SetStateGround(EnPeehat* this) { void EnPeehat_Ground_StateGround(EnPeehat* this, PlayState* play) { // Keep the peahat as the version that doesn't spawn extra enemies and can actually be killed // when Enemy Randomizer is on. - if (IS_DAY || CVarGetInteger("gRandomizedEnemies", 0)) { + if (IS_DAY || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { this->actor.flags |= ACTOR_FLAG_TARGETABLE; if (this->riseDelayTimer == 0) { if (this->actor.xzDistToPlayer < this->xzDistToRise) { diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 793c73865..0ffd1459e 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -254,7 +254,7 @@ void func_80AE2744(EnRd* this, PlayState* play) { // Add a height check to redeads/gibdos freeze when Enemy Randomizer is on. // Without the height check, redeads/gibdos can freeze the player from insane distances in // vertical rooms (like the first room in Deku Tree), making these rooms nearly unplayable. - s8 enemyRandoCCActive = CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0); + s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); if (!enemyRandoCCActive || (enemyRandoCCActive && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) { if ((this->actor.params != 2) && (this->unk_305 == 0)) { func_80AE37BC(this); @@ -668,7 +668,7 @@ void func_80AE3C98(EnRd* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { if (this->unk_30C == 0) { - s8 enemyRandoCCActive = CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0); + s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); // Don't set this flag in Enemy Rando as it can overlap with other objects using the same flag. if (!Flags_GetSwitch(play, this->unk_312 & 0x7F) && !enemyRandoCCActive) { Flags_SetSwitch(play, this->unk_312 & 0x7F); diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index 9e09a705c..708d5ddf2 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -750,7 +750,7 @@ void EnSa_Update(Actor* thisx, PlayState* play) { } if (this->actionFunc != func_80AF68E4) { - if (CVarGetInteger("gDisableKokiriDrawDistance", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), 0) != 0) { this->alpha = func_80034DD4(&this->actor, play, this->alpha, 32767); } else { diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 943a2fbb0..185a39c51 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -111,7 +111,7 @@ void func_80AFB768(EnSi* this, PlayState* play) { } else { Item_Give(play, giveItemId); } - if ((!CVarGetInteger("gSkulltulaFreeze", 0) || giveItemId != ITEM_SKULL_TOKEN) && + if ((!CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) || giveItemId != ITEM_SKULL_TOKEN) && getItemId != RG_ICE_TRAP) { player->actor.freezeTimer = 20; } @@ -181,7 +181,7 @@ void func_80AFB950(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && - (!CVarGetInteger("gSkulltulaFreeze", 0) || getItemId == RG_ICE_TRAP || giveItemId != ITEM_SKULL_TOKEN)) { + (!CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) || getItemId == RG_ICE_TRAP || giveItemId != ITEM_SKULL_TOKEN)) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); diff --git a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c index 6a5862747..e985fe862 100644 --- a/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c +++ b/soh/src/overlays/actors/ovl_En_Skb/z_en_skb.c @@ -192,7 +192,7 @@ void EnSkb_Destroy(Actor* thisx, PlayState* play) { void func_80AFCD60(EnSkb* this) { // Don't despawn stallchildren during daytime when enemy randomizer is enabled. - if (IS_DAY && !CVarGetInteger("gRandomizedEnemies", 0)) { + if (IS_DAY && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { func_80AFCF48(this); } else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) && (this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) { @@ -290,7 +290,7 @@ void EnSkb_Advance(EnSkb* this, PlayState* play) { } } // Don't despawn stallchildren during daytime or when a stalchildren walks too far away from his "home" when enemy randomizer is enabled. - if ((Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) && !CVarGetInteger("gRandomizedEnemies", 0)) { + if ((Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) > 800.0f || IS_DAY) && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { func_80AFCF48(this); } else if (Actor_IsFacingPlayer(&this->actor, 0x11C7) && (this->actor.xzDistToPlayer < (60.0f + (this->actor.params * 6.0f)))) { diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 67c695872..d4b26eb12 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1413,7 +1413,7 @@ void EnSkj_StartOcarinaMinigame(EnSkj* this, PlayState* play) { if (dialogState == TEXT_STATE_CLOSING) { // #region SOH [Enhancement] - if (CVarGetInteger("gInstantOcarinaGameWin", 0) && CVarGetInteger("gCustomizeOcarinaGame", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("InstantOcarinaGameWin"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) { play->msgCtx.ocarinaMode = OCARINA_MODE_0F; this->songFailTimer = 160; this->actionFunc = EnSkj_WaitForPlayback; @@ -1475,8 +1475,8 @@ void EnSkj_WaitForPlayback(EnSkj* this, PlayState* play) { case MSGMODE_MEMORY_GAME_PLAYER_PLAYING: if (this->songFailTimer != 0) { // #region SOH [Enhancement] - if (CVarGetInteger("gOcarinaUnlimitedFailTime", 0) == 1 && - CVarGetInteger("gCustomizeOcarinaGame", 0) == 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("OcarinaUnlimitedFailTime"), 0) == 1 && + CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0) == 1) { // don't decrement timer // #endregion } else { diff --git a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c index f62f8b998..00f859e70 100644 --- a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -354,7 +354,7 @@ s32 func_80B0C9F0(EnSw* this, PlayState* play) { } Enemy_StartFinishingBlow(play, &this->actor); if (((this->actor.params & 0xE000) >> 0xD) != 0) { - if (CVarGetInteger("gGsCutscene", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GSCutscene"), 0)) { OnePointCutscene_Init(play, 2200, 90, &this->actor, MAIN_CAM); } this->skelAnime.playSpeed = 8.0f; @@ -571,7 +571,7 @@ void func_80B0D590(EnSw* this, PlayState* play) { this->collider.elements[0].info.ocElemFlags = 1; } - Math_ApproachF(&this->actor.scale.x, !IS_DAY || CVarGetInteger("gNightGSAlwaysSpawn", 0) ? 0.02f : 0.0f, 0.2f, 0.01f); + Math_ApproachF(&this->actor.scale.x, !IS_DAY || CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0) ? 0.02f : 0.0f, 0.2f, 0.01f); Actor_SetScale(&this->actor, this->actor.scale.x); } diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c index f0d9d3897..dbd6007a2 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c @@ -111,8 +111,8 @@ void EnSyatekiItm_Idle(EnSyatekiItm* this, PlayState* play) { player->actor.world.rot.x = player->actor.shape.rot.x = player->actor.world.rot.z = player->actor.shape.rot.z = 0; s32 ammunition = 15; - if(CVarGetInteger("gCustomizeShootingGallery", 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? "gAdultShootingGalleryAmmunition" : "gChildShootingGalleryAmmunition", 15); + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->roundNum = this->hitCount = 0; @@ -132,7 +132,7 @@ void EnSyatekiItm_StartRound(EnSyatekiItm* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->unkTimer == 0) { - if (LINK_IS_ADULT && !(CVarGetInteger("gCustomizeShootingGallery", 0) && CVarGetInteger("gConstantAdultGallery", 0))) { + if (LINK_IS_ADULT && !(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("ConstantAdultGallery"), 0))) { for (i = 0, j = 0; i < SYATEKI_ROUND_MAX; i++) { if (this->roundFlags[i]) { j++; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 6ab91ddc0..252279e35 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -293,7 +293,7 @@ void EnSyatekiMan_StartGame(EnSyatekiMan* this, PlayState* play) { Message_CloseTextbox(play); gallery = ((EnSyatekiItm*)this->actor.parent); if (gallery->actor.update != NULL) { - if(CVarGetInteger("gCustomizeShootingGallery", 0) && CVarGetInteger("gInstantShootingGalleryWin", 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InstantShootingGalleryWin"), 0)) { gallery->hitCount = 10; gallery->signal = ENSYATEKI_END; } else { @@ -406,8 +406,8 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { case SYATEKI_RESULT_ALMOST: this->timer = 20; s32 ammunition = 15; - if(CVarGetInteger("gCustomizeShootingGallery", 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? "gAdultShootingGalleryAmmunition" : "gChildShootingGalleryAmmunition", 15); + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->actionFunc = EnSyatekiMan_RestartGame; diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index 55fbed824..d00ebbb18 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -408,7 +408,7 @@ s32 EnTk_ChooseReward(EnTk* this) { f32 luck; s32 reward; - if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { + if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { return 3; } @@ -502,7 +502,7 @@ void EnTk_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (CVarGetInteger("gDampeAllNight", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeAllNight"), 0)) { if (!!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) { Actor_Kill(&this->actor); return; @@ -610,7 +610,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->rewardTimer = 0; - if (this->validDigHere == 1 || IS_RANDO || CVarGetInteger("gDampeWin", 0)) { + if (this->validDigHere == 1 || IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { rewardOrigin.x = 0.0f; rewardOrigin.y = 0.0f; rewardOrigin.z = -40.0f; @@ -625,15 +625,15 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->currentReward = EnTk_ChooseReward(this); if (this->currentReward == 3) { - if (IS_RANDO || CVarGetInteger("gDampeWin", 0)) { + if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { /* * Upgrade the purple rupee reward to the heart piece if this * is the first grand prize dig. */ - if (!Flags_GetItemGetInf(ITEMGETINF_1C) && !(IS_RANDO || CVarGetInteger("gDampeWin", 0))) { + if (!Flags_GetItemGetInf(ITEMGETINF_1C) && !(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0))) { Flags_SetItemGetInf(ITEMGETINF_1C); this->currentReward = 4; - } else if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { + } else if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { this->currentReward = 4; } } @@ -646,7 +646,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { // If true, spawn the heart piece and set the vanilla itemGetInf flag and new temp clear flag. if (!heartPieceSpawned && (!(gSaveContext.itemGetInf[1] & ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE) || - CVarGetInteger("gGravediggingTourFix", 0) && + CVarGetInteger(CVAR_ENHANCEMENT("GravediggingTourFix"), 0) && !Flags_GetCollectible(play, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE))) { this->currentReward = 4; gSaveContext.itemGetInf[1] |= ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE; @@ -668,7 +668,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { if (this->skelAnime.curFrame >= 32.0f && this->rewardTimer == 10) { /* Play a reward sound shortly after digging */ - if (!(IS_RANDO || CVarGetInteger("gDampeWin", 0)) && this->validDigHere == 0) { + if (!(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) && this->validDigHere == 0) { /* Bad dig spot */ Audio_PlayActorSound2(&this->actor, NA_SE_SY_ERROR); } else if (this->currentReward == 4) { diff --git a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index f919bb39a..ef2b79cdb 100644 --- a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -128,7 +128,7 @@ void EnTorch2_Init(Actor* thisx, PlayState* play2) { // Change Dark Link to regular enemy instead of boss with enemy randomizer and crowd control. // This way Dark Link will be considered for "clear enemy" rooms properly. - if (CVarGetInteger("gRandomizedEnemies", 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); } @@ -279,7 +279,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { } // Disable miniboss music with Enemy Randomizer because the music would keep // playing if the enemy was never defeated, which is common with Enemy Randomizer. - if (!CVarGetInteger("gRandomizedEnemies", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { func_800F5ACC(NA_BGM_MINI_BOSS); } sActionState = ENTORCH2_ATTACK; diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index d52b82d8d..ae4ac753f 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -293,7 +293,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. - bool checkAnim = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? play->animationCtx.animationCount <= 1 : true; + bool checkAnim = (CVarGetInteger(CVAR_ENHANCEMENT("FixSawSoftlock"), 0) != 0 || CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0) ? play->animationCtx.animationCount <= 1 : true; if (this->unk_1E4 == 3 && checkAnim) { Actor_ProcessTalkRequest(&this->actor, play); Message_ContinueTextbox(play, this->actor.textId); diff --git a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c index d7a838d8a..9b6154a8b 100644 --- a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c +++ b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c @@ -246,7 +246,7 @@ void EnVali_SetupDivideAndDie(EnVali* this, PlayState* play) { // Offset small jellyfish with Enemy Randomizer, otherwise it gets // stuck in a loop spawning more big jellyfish with seeded spawns. - if (CVarGetInteger("gRandomizedEnemies", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { this->actor.world.rot.y += rand() % 50; } diff --git a/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c b/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c index 2f90ad1a0..1a711b644 100644 --- a/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c +++ b/soh/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c @@ -405,7 +405,7 @@ void EnWallmas_ReturnToCeiling(EnWallmas* this, PlayState* play) { } } if (this->actor.params == WMT_SHADOWTAG) { - if (!CVarGetInteger("gShadowTag", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) { Actor_Kill(&this->actor); } } @@ -439,7 +439,7 @@ void EnWallmas_Die(EnWallmas* this, PlayState* play) { Actor_Kill(&this->actor); } if (this->actor.params == WMT_SHADOWTAG) { - if (!CVarGetInteger("gShadowTag", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) { Actor_Kill(&this->actor); } else { EnWallmas_Init(this, play); diff --git a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c index 41a485bbc..2c243e254 100644 --- a/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c +++ b/soh/src/overlays/actors/ovl_En_Wf/z_en_wf.c @@ -390,7 +390,7 @@ void EnWf_WaitToAppear(EnWf* this, PlayState* play) { // Disable miniboss music with Enemy Randomizer because the music would keep // playing if the enemy was never defeated, which is common with Enemy Randomizer. - if ((this->actor.params != WOLFOS_NORMAL) && (this->switchFlag != 0xFF) && !CVarGetInteger("gRandomizedEnemies", 0)) { + if ((this->actor.params != WOLFOS_NORMAL) && (this->switchFlag != 0xFF) && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0)) { func_800F5ACC(NA_BGM_MINI_BOSS); } } diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 4adb7afe7..2b0d6c126 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -101,7 +101,7 @@ static f32 sSpawnSin; s32 EnWood02_SpawnZoneCheck(EnWood02* this, PlayState* play, Vec3f* pos) { f32 phi_f12; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { return true; } @@ -177,7 +177,7 @@ void EnWood02_Init(Actor* thisx, PlayState* play2) { // as the night scene, For the always spawn GS enhancement we apply the needed // params to have the GS drop when bonking if ((this->actor.params & 0xFF) == WOOD_TREE_CONICAL_MEDIUM && IS_DAY && - play->sceneNum == SCENE_KAKARIKO_VILLAGE && CVarGetInteger("gNightGSAlwaysSpawn", 0)) { + play->sceneNum == SCENE_KAKARIKO_VILLAGE && CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0)) { this->actor.params = 0x2001; this->actor.home.rot.z = 0x71; } @@ -352,7 +352,7 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { dropsSpawnPt = this->actor.world.pos; dropsSpawnPt.y += 200.0f; - if ((this->unk_14C >= 0) && (this->unk_14C < 0x64) && (CVarGetInteger("gTreeStickDrops", 0)) && !(INV_CONTENT(ITEM_STICK) == ITEM_NONE)) { + if ((this->unk_14C >= 0) && (this->unk_14C < 0x64) && (CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0)) && !(INV_CONTENT(ITEM_STICK) == ITEM_NONE)) { (numDrops = (Rand_ZeroOne() * 4)); for (i = 0; i < numDrops; ++i) { Item_DropCollectible(play, &dropsSpawnPt, ITEM00_STICK); diff --git a/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c b/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c index f5275618b..57ac15ecf 100644 --- a/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c +++ b/soh/src/overlays/actors/ovl_En_Zo/z_en_zo.c @@ -428,7 +428,7 @@ u16 EnZo_GetTextId(PlayState* play, Actor* thisx) { } if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) || - (CVarGetInteger("gFixZoraHintDialogue", 0) && + (CVarGetInteger(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 0) && Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER))) { return 0x4010; } diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 9a31ceb50..7bf1ac7d1 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -2901,24 +2901,24 @@ f32 Fishing_GetMinimumRequiredScore() { // RANDOTODO: update the enhancement sliders to not allow // values above rando fish weight values when rando'd if(sLinkAge == 1) { - weight = CVarGetInteger("gCustomizeFishing", 0) ? CVarGetInteger("gChildMinimumWeightFish", 10) : 10; + weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) ? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 10) : 10; } else { - weight = CVarGetInteger("gCustomizeFishing", 0) ? CVarGetInteger("gAdultMinimumWeightFish", 13) : 13; + weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) ? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 13) : 13; } return sqrt(((f32)weight - 0.5f) / 0.0036f); } bool getInstantFish() { - return CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gInstantFishing", 0); + return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InstantFishing"), 0); } bool getGuaranteeBite() { - return CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gGuaranteeFishingBite", 0); + return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 0); } bool getFishNeverEscape() { - return CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gFishNeverEscape", 0); + return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("FishNeverEscape"), 0); } void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { @@ -5513,7 +5513,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { player->actor.speedXZ = 0.0f; // #region SOH [Enhancement] - if (CVarGetInteger("gQuitFishingAtDoor", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { Fishing_QuitAtDoor(this, play); } // #endregion diff --git a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c index a9e5ca2a7..9d0cb7619 100644 --- a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c +++ b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c @@ -141,7 +141,7 @@ void ObjComb_ChooseItemDrop(ObjComb* this, PlayState* play) { } else if (Rand_ZeroOne() < 0.5f) { params = -1; } - if (params >= 0 && !CVarGetInteger("gNoRandomDrops", 0)) { + if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) { Item_DropCollectible(play, &this->actor.world.pos, params); } } diff --git a/soh/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.c b/soh/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.c index 217fc434f..18c898547 100644 --- a/soh/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.c +++ b/soh/src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.c @@ -123,7 +123,7 @@ void ObjLightswitch_InitCollider(ObjLightswitch* this, PlayState* play) { s32 pad; // Initialize this with the sun switch, so it can't be affected by toggling while the actor is loaded - sunLightArrowsEnabledOnSunSwitchLoad = CVarGetInteger("gSunlightArrows", 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS)); + sunLightArrowsEnabledOnSunSwitchLoad = CVarGetInteger(CVAR_ENHANCEMENT("SunlightArrows"), 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS)); Collider_InitJntSph(play, &this->collider); // If "Sunlight Arrows" is enabled, set up the collider to allow Light Arrow hits diff --git a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c index 2f5cf4ee3..a59dc5ab6 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c @@ -275,7 +275,7 @@ void ObjMure_InitialAction(ObjMure* this, PlayState* play) { } void ObjMure_CulledState(ObjMure* this, PlayState* play) { - if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] || CVarGetInteger("gDisableDrawDistance", 0) != 0) { + if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] || CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { this->actionFunc = ObjMure_ActiveState; this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_SpawnActors(this, play); @@ -399,7 +399,7 @@ static ObjMureActionFunc sTypeGroupBehaviorFunc[] = { void ObjMure_ActiveState(ObjMure* this, PlayState* play) { ObjMure_CheckChildren(this, play); if (sZClip[this->type] + 40.0f <= fabsf(this->actor.projectedPos.z) && - CVarGetInteger("gDisableDrawDistance", 1) != 0) { + CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) != 0) { this->actionFunc = ObjMure_CulledState; this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_KillActors(this, play); diff --git a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c index b883072b9..0aad27c04 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c @@ -191,7 +191,7 @@ void func_80B9A658(ObjMure2* this) { void func_80B9A668(ObjMure2* this, PlayState* play) { if (Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z) < (sDistSquared1[this->actor.params & 3] * this->unk_184) || - CVarGetInteger("gDisableDrawDistance", 0) != 0) { + CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure2_SpawnActors(this, play); func_80B9A6E8(this); @@ -205,7 +205,7 @@ void func_80B9A6E8(ObjMure2* this) { void func_80B9A6F8(ObjMure2* this, PlayState* play) { func_80B9A534(this); - if (CVarGetInteger("gDisableDrawDistance", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { return; } diff --git a/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c b/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c index 09ce9dff6..ae26db3ac 100644 --- a/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c +++ b/soh/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c @@ -568,9 +568,9 @@ void ObjOshihiki_Push(ObjOshihiki* this, PlayState* play) { f32 pushDistSigned; s32 stopFlag; - this->pushSpeed = this->pushSpeed + (CVarGetInteger("gFasterBlockPush", 0) * 0.25) + 0.5f; + this->pushSpeed = this->pushSpeed + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.25) + 0.5f; this->stateFlags |= PUSHBLOCK_PUSH; - this->pushSpeed = CLAMP_MAX(this->pushSpeed, 2.0f + (CVarGetInteger("gFasterBlockPush", 0) * 0.5)); + this->pushSpeed = CLAMP_MAX(this->pushSpeed, 2.0f + (CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 0.5)); stopFlag = Math_StepToF(&this->pushDist, 20.0f, this->pushSpeed); pushDistSigned = ((this->direction >= 0.0f) ? 1.0f : -1.0f) * this->pushDist; thisx->world.pos.x = thisx->home.pos.x + (pushDistSigned * this->yawSin); @@ -596,7 +596,7 @@ void ObjOshihiki_Push(ObjOshihiki* this, PlayState* play) { this->dyna.unk_150 = 0.0f; this->pushDist = 0.0f; this->pushSpeed = 0.0f; - this->timer = 10 - ((CVarGetInteger("gFasterBlockPush", 0) * 3) / 2); + this->timer = 10 - ((CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 3) / 2); if (this->floorBgIds[this->highestFloor] == BGCHECK_SCENE) { ObjOshihiki_SetupOnScene(this, play); } else { diff --git a/soh/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c b/soh/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c index 202bcc09f..4da1c3eba 100644 --- a/soh/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c +++ b/soh/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c @@ -34,7 +34,7 @@ void ObjRoomtimer_Init(Actor* thisx, PlayState* play) { // Shabom room in Jabu Jabu has a lengthened timer in Enemy Randomizer. Flag doesn't match what the game // expects. Instead set it back to the same flag as what it would be in vanilla. - if (CVarGetInteger("gRandomizedEnemies", 0) && play->sceneNum == SCENE_JABU_JABU && play->roomCtx.curRoom.num == 12) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && play->sceneNum == SCENE_JABU_JABU && play->roomCtx.curRoom.num == 12) { this->switchFlag = 30; } else { this->switchFlag = (params >> 10) & 0x3F; diff --git a/soh/src/overlays/actors/ovl_Oceff_Wipe/z_oceff_wipe.c b/soh/src/overlays/actors/ovl_Oceff_Wipe/z_oceff_wipe.c index 0076a6385..dfc236251 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Wipe/z_oceff_wipe.c +++ b/soh/src/overlays/actors/ovl_Oceff_Wipe/z_oceff_wipe.c @@ -80,7 +80,7 @@ void OceffWipe_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - int fastOcarinaPlayback = (CVarGetInteger("gFastOcarinaPlayback", 0) != 0); + int fastOcarinaPlayback = (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) != 0); if (this->timer < 32) { z = Math_SinS(this->timer << 9) * (fastOcarinaPlayback ? 1200.0f : 1400.0f); } else { diff --git a/soh/src/overlays/actors/ovl_Oceff_Wipe2/z_oceff_wipe2.c b/soh/src/overlays/actors/ovl_Oceff_Wipe2/z_oceff_wipe2.c index 38014b5e2..a6b422062 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Wipe2/z_oceff_wipe2.c +++ b/soh/src/overlays/actors/ovl_Oceff_Wipe2/z_oceff_wipe2.c @@ -72,7 +72,7 @@ void OceffWipe2_Draw(Actor* thisx, PlayState* play) { eye = GET_ACTIVE_CAM(play)->eye; Camera_GetSkyboxOffset(&vec, GET_ACTIVE_CAM(play)); - int fastOcarinaPlayback = (CVarGetInteger("gFastOcarinaPlayback", 0) != 0); + int fastOcarinaPlayback = (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) != 0); if (this->timer < 32) { z = Math_SinS(this->timer << 9) * (fastOcarinaPlayback ? 1200.0f : 1330.0f); } else { diff --git a/soh/src/overlays/actors/ovl_Oceff_Wipe3/z_oceff_wipe3.c b/soh/src/overlays/actors/ovl_Oceff_Wipe3/z_oceff_wipe3.c index df3fc1a87..28f02100d 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Wipe3/z_oceff_wipe3.c +++ b/soh/src/overlays/actors/ovl_Oceff_Wipe3/z_oceff_wipe3.c @@ -73,7 +73,7 @@ void OceffWipe3_Draw(Actor* thisx, PlayState* play) { eye = GET_ACTIVE_CAM(play)->eye; Camera_GetSkyboxOffset(&vec, GET_ACTIVE_CAM(play)); - int fastOcarinaPlayback = (CVarGetInteger("gFastOcarinaPlayback", 0) != 0); + int fastOcarinaPlayback = (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) != 0); if (this->counter < 32) { z = Math_SinS(this->counter << 9) * (fastOcarinaPlayback ? 1200.0f : 1330.0f); } else { diff --git a/soh/src/overlays/actors/ovl_Oceff_Wipe4/z_oceff_wipe4.c b/soh/src/overlays/actors/ovl_Oceff_Wipe4/z_oceff_wipe4.c index 5a66b2991..6c96e639f 100644 --- a/soh/src/overlays/actors/ovl_Oceff_Wipe4/z_oceff_wipe4.c +++ b/soh/src/overlays/actors/ovl_Oceff_Wipe4/z_oceff_wipe4.c @@ -68,7 +68,7 @@ void OceffWipe4_Draw(Actor* thisx, PlayState* play) { eye = GET_ACTIVE_CAM(play)->eye; Camera_GetSkyboxOffset(&vec, GET_ACTIVE_CAM(play)); - int fastOcarinaPlayback = (CVarGetInteger("gFastOcarinaPlayback", 0) != 0); + int fastOcarinaPlayback = (CVarGetInteger(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 0) != 0); if (this->timer < 16) { z = Math_SinS(this->timer * 1024) * (fastOcarinaPlayback ? 1200.0f : 1330.0f); } else { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 834d9fb96..b90681120 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2251,7 +2251,7 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { s32 i; if (this->currentMask != PLAYER_MASK_NONE) { - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) { s32 maskItem = this->currentMask - PLAYER_MASK_KEATON + ITEM_MASK_KEATON; bool hasOnDpad = false; if (CVarGetInteger("gDpadEquips", 0) != 0) { @@ -2377,7 +2377,7 @@ void Player_StartChangingHeldItem(Player* this, PlayState* play) { } void Player_UpdateItems(Player* this, PlayState* play) { - if ((this->actor.category == ACTORCAT_PLAYER) && (CVarGetInteger("gQuickPutaway", 0) || !(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY)) && + if ((this->actor.category == ACTORCAT_PLAYER) && (CVarGetInteger(CVAR_ENHANCEMENT("QuickPutaway"), 0) || !(this->stateFlags1 & PLAYER_STATE1_START_PUTAWAY)) && ((this->heldItemAction == this->itemAction) || (this->stateFlags1 & PLAYER_STATE1_SHIELDING)) && (gSaveContext.health != 0) && (play->csCtx.state == CS_STATE_IDLE) && (this->csAction == 0) && (play->shootingGalleryStatus == 0) && (play->activeCamera == MAIN_CAM) && @@ -2393,7 +2393,7 @@ void Player_UpdateItems(Player* this, PlayState* play) { // Determine projectile type for bow or slingshot s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { bool useBow = LINK_IS_ADULT; - if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ + if(CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0)){ useBow = this->heldItemAction != PLAYER_IA_SLINGSHOT; } if (useBow) { @@ -2937,7 +2937,7 @@ s32 Player_UpperAction_CarryActor(Player* this, PlayState* play) { } void func_808357E8(Player* this, Gfx** dLists) { - if (LINK_IS_ADULT && (CVarGetInteger("gEnhancements.EquimentAlwaysVisible", 0))) { + if (LINK_IS_ADULT && (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0))) { this->leftHandDLists = &dLists[1]; } else { this->leftHandDLists = &dLists[gSaveContext.linkAge]; @@ -3021,7 +3021,7 @@ s32 func_808359FC(Player* this, PlayState* play) { } s32 spawn_boomerang_ivan(EnPartner* this, PlayState* play) { - if (!CVarGetInteger("gIvanCoopModeEnabled", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0)) { return 0; } @@ -3055,7 +3055,7 @@ s32 func_80835B60(Player* this, PlayState* play) { return 1; } - if (sUseHeldItem && CVarGetInteger("gFastBoomerang", 0)) { + if (sUseHeldItem && CVarGetInteger(CVAR_ENHANCEMENT("FastBoomerang"), 0)) { this->boomerangQuickRecall = true; } @@ -3179,7 +3179,7 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { ((itemAction == PLAYER_IA_MAGIC_BEAN) && (AMMO(ITEM_BEAN) == 0)) || (temp = Player_ActionToExplosive(this, itemAction), ((temp >= 0) && ((AMMO(sExplosiveInfos[temp].itemId) == 0) || - (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3 && !CVarGetInteger("gRemoveExplosiveLimit", 0))))))) { + (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length >= 3 && !CVarGetInteger(CVAR_ENHANCEMENT("RemoveExplosiveLimit"), 0))))))) { // Prevent some items from being used if player is out of ammo. // Also prevent explosives from being used if there are 3 or more active (outside of bombchu bowling) func_80078884(NA_SE_SY_ERROR); @@ -3241,7 +3241,7 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) { (item != this->heldItemId) && (sItemChangeTypes[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType] != PLAYER_ITEM_CHG_0) && - (!CVarGetInteger("gSeparateArrows", 0) || + (!CVarGetInteger(CVAR_ENHANCEMENT("SeparateArrows"), 0) || itemAction < PLAYER_IA_BOW || itemAction > PLAYER_IA_BOW_0E || this->heldItemAction < PLAYER_IA_BOW || this->heldItemAction > PLAYER_IA_BOW_0E)) { // Start the held item change process @@ -4038,7 +4038,7 @@ s32 func_80837B18_modified(PlayState* play, Player* this, s32 damage, u8 modifie s32 modifiedDamage = damage; if (modified) { - modifiedDamage *= (1 << CVarGetInteger("gDamageMul", 0)); + modifiedDamage *= (1 << CVarGetInteger(CVAR_ENHANCEMENT("DamageMult"), 0)); } return Health_ChangeBy(play, modifiedDamage); @@ -4263,7 +4263,7 @@ s32 func_808382DC(Player* this, PlayState* play) { if (this->unk_A86 != 0) { if (!Player_InBlockingCsMode(play, this)) { - Player_InflictDamageModified(play, -16 * (1 << CVarGetInteger("gVoidDamageMul", 0)), false); + Player_InflictDamageModified(play, -16 * (1 << CVarGetInteger(CVAR_ENHANCEMENT("VoidDamageMult"), 0)), false); this->unk_A86 = 0; } } else { @@ -5096,7 +5096,7 @@ void func_8083A0F4(PlayState* play, Player* this) { // Same actor is used for small and large silver rocks, use actor params to identify large ones bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; - if (CVarGetInteger("gFasterHeavyBlockLift", 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 5.0f); } else { LinkAnimation_PlayOnce(play, &this->skelAnime, anim); @@ -5355,7 +5355,7 @@ s32 func_8083AD4C(PlayState* play, Player* this) { if (func_8002DD6C(this)) { bool shouldUseBowCamera = LINK_IS_ADULT; - if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ + if(CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0)){ shouldUseBowCamera = this->heldItemAction != PLAYER_IA_SLINGSHOT; } @@ -5423,7 +5423,7 @@ void func_8083AF44(PlayState* play, Player* this, s32 magicSpell) { //! magic value, it will be consumed to zero. Magic_RequestChange(play, sMagicSpellCosts[magicSpell], MAGIC_CONSUME_WAIT_PREVIEW); - u8 isFastFarores = CVarGetInteger("gFastFarores", 0) && this->itemAction == PLAYER_IA_FARORES_WIND; + u8 isFastFarores = CVarGetInteger(CVAR_ENHANCEMENT("FastFarores"), 0) && this->itemAction == PLAYER_IA_FARORES_WIND; if (isFastFarores) { LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, &gPlayerAnim_link_magic_tame, 0.83f * 2); @@ -6018,7 +6018,7 @@ s32 func_8083C6B8(PlayState* play, Player* this) { sp24 = this->actor.world.pos; sp24.y += 50.0f; - if (CVarGetInteger("gHoverFishing", 0) + if (CVarGetInteger(CVAR_ENHANCEMENT("HoverFishing"), 0) ? 0 : !(this->actor.bgCheckFlags & 1) || (this->actor.world.pos.z > 1300.0f) || BgCheck_SphVsFirstPoly(&play->colCtx, &sp24, 20.0f)) { @@ -6265,7 +6265,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { func_80832340(play, this); // Skip take breath animation on surface if Link didn't grab an item while underwater and the setting is enabled - if (CVarGetInteger("gSkipSwimDeepEndAnim", 0) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 0) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { auto lastAnimFrame = Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_deep_end); LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_swimer_swim_deep_end, 1.0f, lastAnimFrame, lastAnimFrame, ANIMMODE_ONCE, -6.0f); @@ -6547,7 +6547,7 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { } } - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; } @@ -6751,7 +6751,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { if(gSaveContext.pendingIceTrapCount) { gSaveContext.pendingIceTrapCount--; GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP)); - if (CVarGetInteger("gAddTraps.enabled", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0)) { return 1; } this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); @@ -6805,7 +6805,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { // Skip cutscenes from picking up consumables with "Fast Pickup Text" enabled, even when the player never picked it up before. // But only for bushes/rocks/enemies because otherwise it can lead to softlocks in deku mask theatre and potentially other places. - uint8_t skipItemCutscene = CVarGetInteger("gFastDrops", 0) && isDropToSkip; + uint8_t skipItemCutscene = CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0) && isDropToSkip; // Same as above but for rando. Rando is different because we want to enable cutscenes for items that the player already has because // those items could be a randomized item coming from scrubs, freestanding PoH's and keys. So we need to once again overrule @@ -6844,7 +6844,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { giEntry = this->getItemEntry; } EnBox* chest = (EnBox*)interactedActor; - if (CVarGetInteger("gFastChests", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FastChests"), 0) != 0) { giEntry.gi = -1 * abs(giEntry.gi); } @@ -7129,10 +7129,10 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall func_80832224(this); this->actor.prevPos = this->actor.world.pos; // #region SOH [Enhancement] - if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) > 1) { // increase animation speed when entering a tunnel LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, - ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f, + ((CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) + 1.0f) / 2.0f), 0.0f, Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), ANIMMODE_ONCE, 0.0f); Player_AnimReplaceApplyFlags(play, this, 0x9D); @@ -7222,10 +7222,10 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { if (this->linearVelocity > 0.0f) { this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; // #region SOH [Enhancement] - if (CVarGetInteger("gCrawlSpeed", 1) > 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) > 1) { // animation when exiting a tunnel forward LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_end, - ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), 0.0f, + ((CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) + 1.0f) / 2.0f), 0.0f, Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_end), ANIMMODE_ONCE, 0.0f); Player_AnimReplaceApplyFlags(play, this, 0x9D); @@ -7240,9 +7240,9 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { this->actor.shape.rot.y = this->actor.wallYaw; // #region SOH [Enhancement] // animation when exiting a tunnel backward - if (CVarGetInteger("gCrawlSpeed",1) > 1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"),1) > 1) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, - -1.0f * ((CVarGetInteger("gCrawlSpeed", 1) + 1.0f) / 2.0f), + -1.0f * ((CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) + 1.0f) / 2.0f), Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, 0.0f); Player_AnimReplaceApplyFlags(play, this, 0x9D); OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM); @@ -7547,9 +7547,9 @@ void func_8084029C(Player* this, f32 arg1) { } if ((this->currentBoots == PLAYER_BOOTS_HOVER || - (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) && + (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) && !(this->actor.bgCheckFlags & 1) && - (this->hoverBootsTimer != 0 || (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating))) { + (this->hoverBootsTimer != 0 || (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating))) { func_8002F8F0(&this->actor, NA_SE_PL_HOBBERBOOTS_LV - SFX_FLAG); } else if (func_8084021C(this->unk_868, arg1, 29.0f, 10.0f) || func_8084021C(this->unk_868, arg1, 29.0f, 24.0f)) { func_808327F8(this, this->linearVelocity); @@ -7742,7 +7742,7 @@ void func_808409CC(PlayState* play, Player* this) { if (sp34 < 4) { if (((sp34 != 0) && (sp34 != 3)) || ((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) && ((sp34 == 3) || Player_GetMeleeWeaponHeld(this)))) { - if ((sp34 == 1) && Player_HoldsTwoHandedWeapon(this) && CVarGetInteger("gTwoHandedIdle", 0) == 1) { + if ((sp34 == 1) && Player_HoldsTwoHandedWeapon(this) && CVarGetInteger(CVAR_ENHANCEMENT("TwoHandedIdle"), 0) == 1) { sp34 = 4; } sp38 = sp34 + 9; @@ -8285,7 +8285,7 @@ void Player_Action_80842180(Player* this, PlayState* play) { } } - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { sp2C *= 1.5f; } @@ -8462,7 +8462,7 @@ s32 func_808428D8(Player* this, PlayState* play) { this->meleeWeaponAnimation = PLAYER_MWA_STAB_1H; this->yaw = this->actor.shape.rot.y + this->unk_6BE; - if (!CVarGetInteger("gCrouchStabHammerFix", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { return 1; } @@ -8473,7 +8473,7 @@ s32 func_808428D8(Player* this, PlayState* play) { swordId = Player_GetMeleeWeaponHeld(this) - 1; } - if (swordId != 4 && !CVarGetInteger("gCrouchStabFix", 0)) { // 4 = Megaton Hammer + if (swordId != 4 && !CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabFix"), 0)) { // 4 = Megaton Hammer return 1; } @@ -8907,12 +8907,12 @@ void func_80843AE8(PlayState* play, Player* this) { LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_derth_rebirth, 1.0f, 99.0f, Animation_GetLastFrame(&gPlayerAnim_link_derth_rebirth), ANIMMODE_ONCE, 0.0f); } - if (CVarGetInteger("gFairyReviveEffect", 0)) { - if (CVarGetInteger("gFairyRevivePercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyReviveEffect"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyRevivePercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gFairyReviveHealth", 100) / 100 + 15) / 16 * 16; + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("FairyReviveHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gFairyReviveHealth", 20) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("FairyReviveHealth"), 20) * 16; } } else { gSaveContext.healthAccumulator = 0x140; @@ -9013,7 +9013,7 @@ s32 func_80843E64(PlayState* play, Player* this) { impactInfo = &D_80854600[impactIndex]; - if (Player_InflictDamageModified(play, impactInfo->damage * (1 << CVarGetInteger("gFallDamageMul", 0)), + if (Player_InflictDamageModified(play, impactInfo->damage * (1 << CVarGetInteger(CVAR_ENHANCEMENT("FallDamageMult"), 0)), false)) { return -1; } @@ -9833,7 +9833,7 @@ void Player_Action_80846120(Player* this, PlayState* play) { if (LinkAnimation_OnFrame(&this->skelAnime, 229.0f)) { Actor* heldActor = this->heldActor; - if (CVarGetInteger("gFasterHeavyBlockLift", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { // This is the difference in rotation when the animation is sped up 5x heldActor->shape.rot.x -= 3510; } @@ -9932,7 +9932,7 @@ void Player_Action_808464B0(Player* this, PlayState* play) { heldActor->velocity.y = 0.0f; heldActor->speedXZ = 0.0f; func_80834644(play, this); - if (heldActor->id == ACTOR_EN_BOM_CHU && !CVarGetInteger("gDisableFirstPersonChus", 0)) { + if (heldActor->id == ACTOR_EN_BOM_CHU && !CVarGetInteger(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 0)) { func_8083B8F4(this, play); } } @@ -10190,7 +10190,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { Player_UseItem(play, this, ITEM_NONE); Player_SetEquipmentData(play, this); this->prevBoots = this->currentBoots; - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) { if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_SOLD_OUT) { sMaskMemory = PLAYER_MASK_NONE; } @@ -10446,7 +10446,7 @@ void func_808473D4(PlayState* play, Player* this) { if (doAction != DO_ACTION_PUTAWAY) { this->unk_837 = 20; } else if (this->unk_837 != 0) { - if (CVarGetInteger("gInstantPutaway", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("InstantPutaway"), 0) != 0) { this->unk_837 = 0; } else { doAction = DO_ACTION_NONE; @@ -10483,7 +10483,7 @@ s32 Player_UpdateHoverBoots(Player* this) { s32 cond; if ((this->currentBoots == PLAYER_BOOTS_HOVER || - (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) && + (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) && (this->hoverBootsTimer != 0)) { this->hoverBootsTimer--; } else { @@ -10491,7 +10491,7 @@ s32 Player_UpdateHoverBoots(Player* this) { } cond = (this->currentBoots == PLAYER_BOOTS_HOVER || - (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) && + (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) && ((this->actor.yDistToWater >= 0.0f) || (func_80838144(sFloorType) >= 0) || func_8083816C(sFloorType)); if (cond && (this->actor.bgCheckFlags & 1) && (this->hoverBootsTimer != 0)) { @@ -10654,7 +10654,7 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) { sTouchedWallFlags = func_80041DB8(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId); // conflicts arise from these two being enabled at once, and with ClimbEverything on, FixVineFall is redundant anyway - if (CVarGetInteger("gFixVineFall", 0) && !CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixVineFall"), 0) && !CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0)) { /* This fixes the "started climbing a wall and then immediately fell off" bug. * The main idea is if a climbing wall is detected, double-check that it will * still be valid once climbing begins by doing a second raycast with a small @@ -11073,7 +11073,7 @@ void func_80848EF8(Player* this, PlayState* play) { if (CVarGetInteger("gCosmetics.Hud_StoneOfAgony.Changed", 0)) { stoneOfAgonyColor = CVarGetColor24("gCosmetics.Hud_StoneOfAgony.Value", stoneOfAgonyColor); } - if (CVarGetInteger("gVisualAgony", 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { + if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"), 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { s16 Top_Margins = (CVarGetInteger("gHUDMargin_T", 0) * -1); s16 Left_Margins = CVarGetInteger("gHUDMargin_L", 0); s16 Right_Margins = CVarGetInteger("gHUDMargin_R", 0); @@ -11157,7 +11157,7 @@ void func_80848EF8(Player* this, PlayState* play) { if (this->unk_6A0 > 4000000.0f) { this->unk_6A0 = 0.0f; - if (CVarGetInteger("gVisualAgony", 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { + if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"), 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { // This audio is placed here and not in previous CVar check to prevent ears ra.. :) Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E0); } @@ -11627,7 +11627,7 @@ void Player_Update(Actor* thisx, PlayState* play) { if (func_8084FCAC(this, play)) { if (gSaveContext.dogParams < 0) { // Disable object dependency to prevent losing dog in scenes other than market - if (Object_GetIndex(&play->objectCtx, OBJECT_DOG) < 0 && !CVarGetInteger("gDogFollowsEverywhere", 0)) { + if (Object_GetIndex(&play->objectCtx, OBJECT_DOG) < 0 && !CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0)) { gSaveContext.dogParams = 0; } else { gSaveContext.dogParams &= 0x7FFF; @@ -11638,7 +11638,7 @@ void Player_Update(Actor* thisx, PlayState* play) { sDogSpawnPos.z, 0, this->actor.shape.rot.y, 0, dogParams | 0x8000, true); if (dog != NULL) { // Room -1 allows actor to cross between rooms, similar to Navi - dog->room = CVarGetInteger("gDogFollowsEverywhere", 0) ? -1 : 0; + dog->room = CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0) ? -1 : 0; } } } @@ -11799,7 +11799,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, } - if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger("gHideBunnyHood", 0)) { + if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger(CVAR_ENHANCEMENT("HideBunnyHood"), 0)) { gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]); } @@ -11807,7 +11807,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, } if ((this->currentBoots == PLAYER_BOOTS_HOVER || - (CVarGetInteger("gIvanCoopModeEnabled", 0) && this->ivanFloating)) && + (CVarGetInteger(CVAR_ENHANCEMENT("IvanCoopModeEnabled"), 0) && this->ivanFloating)) && !(this->actor.bgCheckFlags & 1) && !(this->stateFlags1 & PLAYER_STATE1_ON_HORSE) && (this->hoverBootsTimer != 0)) { s32 sp5C; @@ -11892,7 +11892,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) { lod = 1; } - if (CVarGetInteger("gDisableLOD", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { lod = 0; } @@ -12072,7 +12072,7 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { if (CVarGetInteger("gMoveWhileFirstPerson", 0)) { f32 movementSpeed = LINK_IS_ADULT ? 9.0f : 8.25f; - if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { movementSpeed *= 1.5f; } @@ -12296,7 +12296,7 @@ s32 func_8084B3CC(PlayState* play, Player* this) { if (!func_8002DD6C(this) || Player_HoldsHookshot(this)) { s32 projectileItemToUse = ITEM_BOW; - if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ + if(CVarGetInteger(CVAR_ENHANCEMENT("BowSlingshotAmmoFix"), 0)){ projectileItemToUse = LINK_IS_ADULT ? ITEM_BOW : ITEM_SLINGSHOT; } @@ -12637,7 +12637,7 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) { phi_f2 = -1.0f; } - this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVarGetInteger("gClimbSpeed", 0); + this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVarGetInteger(CVAR_ENHANCEMENT("ClimbSpeed"), 0); if (this->av2.actionVar2 >= 0) { if ((this->actor.wallPoly != NULL) && (this->actor.wallBgId != BGCHECK_SCENE)) { @@ -12810,8 +12810,8 @@ void Player_Action_8084C760(Player* this, PlayState* play) { // player speed in a tunnel if (!Player_TryLeavingCrawlspace(this, play)) { // #region SOH [Enhancement] - if (CVarGetInteger("gCrawlSpeed", 1) > 1) { - this->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVarGetInteger("gCrawlSpeed", 1); + if (CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1) > 1) { + this->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 1); // #endregion } else { this->linearVelocity = sControlInput->rel.stick_y * 0.03f; @@ -13462,7 +13462,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { } this->av1.actionVar1 = 1; equipItem = giEntry.itemId; - equipNow = CVarGetInteger("gAskToEquip", 0) && giEntry.modIndex == MOD_NONE && + equipNow = CVarGetInteger(CVAR_ENHANCEMENT("AskToEquip"), 0) && giEntry.modIndex == MOD_NONE && equipItem >= ITEM_SWORD_KOKIRI && equipItem <= ITEM_TUNIC_ZORA && CHECK_AGE_REQ_ITEM(equipItem); @@ -13836,29 +13836,29 @@ void Player_Action_8084EAC0(Player* this, PlayState* play) { } else { s32 sp28 = D_808549FC[this->itemAction - PLAYER_IA_BOTTLE_POTION_RED]; - if (CVarGetInteger("gRedPotionEffect", 0) && this->itemAction == PLAYER_IA_BOTTLE_POTION_RED) { - if (CVarGetInteger("gRedPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RedPotionEffect"), 0) && this->itemAction == PLAYER_IA_BOTTLE_POTION_RED) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RedPercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gRedPotionHealth", 100) / 100 + 15) / 16 * 16; + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("RedPotionHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gRedPotionHealth", 20) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("RedPotionHealth"), 20) * 16; } - } else if (CVarGetInteger("gBluePotionEffects", 0) && + } else if (CVarGetInteger(CVAR_ENHANCEMENT("BluePotionEffects"), 0) && this->itemAction == PLAYER_IA_BOTTLE_POTION_BLUE) { - if (CVarGetInteger("gBlueHealthPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BlueHealthPercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gBluePotionHealth", 100) / 100 + 15) / 16 * 16; + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("BluePotionHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gBluePotionHealth", 20) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("BluePotionHealth"), 20) * 16; } - if (CVarGetInteger("gBlueManaPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("BlueManaPercentRestore"), 0)) { if (gSaveContext.magicState != MAGIC_STATE_ADD) { Magic_Fill(play); } Magic_RequestChange(play, - (gSaveContext.magicLevel * 48 * CVarGetInteger("gBluePotionMana", 100) / 100 + 15) / + (gSaveContext.magicLevel * 48 * CVarGetInteger(CVAR_ENHANCEMENT("BluePotionMana"), 100) / 100 + 15) / 16 * 16, MAGIC_ADD); } else { @@ -13866,18 +13866,18 @@ void Player_Action_8084EAC0(Player* this, PlayState* play) { Magic_Fill(play); } - Magic_RequestChange(play, CVarGetInteger("gBluePotionMana", 100), MAGIC_ADD); + Magic_RequestChange(play, CVarGetInteger(CVAR_ENHANCEMENT("BluePotionMana"), 100), MAGIC_ADD); ; } - } else if (CVarGetInteger("gGreenPotionEffect", 0) && + } else if (CVarGetInteger(CVAR_ENHANCEMENT("GreenPotionEffect"), 0) && this->itemAction == PLAYER_IA_BOTTLE_POTION_GREEN) { - if (CVarGetInteger("gGreenPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GreenPercentRestore"), 0)) { if (gSaveContext.magicState != MAGIC_STATE_ADD) { Magic_Fill(play); } Magic_RequestChange(play, - (gSaveContext.magicLevel * 48 * CVarGetInteger("gGreenPotionMana", 100) / 100 + 15) / + (gSaveContext.magicLevel * 48 * CVarGetInteger(CVAR_ENHANCEMENT("GreenPotionMana"), 100) / 100 + 15) / 16 * 16, MAGIC_ADD); } else { @@ -13885,25 +13885,25 @@ void Player_Action_8084EAC0(Player* this, PlayState* play) { Magic_Fill(play); } - Magic_RequestChange(play, CVarGetInteger("gGreenPotionMana", 100), MAGIC_ADD); + Magic_RequestChange(play, CVarGetInteger(CVAR_ENHANCEMENT("GreenPotionMana"), 100), MAGIC_ADD); ; } - } else if (CVarGetInteger("gMilkEffect", 0) && (this->itemAction == PLAYER_IA_BOTTLE_MILK_FULL || + } else if (CVarGetInteger(CVAR_ENHANCEMENT("MilkEffect"), 0) && (this->itemAction == PLAYER_IA_BOTTLE_MILK_FULL || this->itemAction == PLAYER_IA_BOTTLE_MILK_HALF)) { - if (CVarGetInteger("gMilkPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MilkPercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gMilkHealth", 100) / 100 + 15) / 16 * 16; + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("MilkHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gMilkHealth", 5) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("MilkHealth"), 5) * 16; } - if (CVarGetInteger("gSeparateHalfMilkEffect", 0) && + if (CVarGetInteger(CVAR_ENHANCEMENT("SeparateHalfMilkEffect"), 0) && this->itemAction == PLAYER_IA_BOTTLE_MILK_HALF) { - if (CVarGetInteger("gHalfMilkPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("HalfMilkPercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gHalfMilkHealth", 100) / 100 + 15) / 16 * + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("HalfMilkHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gHalfMilkHealth", 5) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("HalfMilkHealth"), 5) * 16; } } } else { @@ -13959,7 +13959,7 @@ void Player_Action_8084ECA4(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { if (this->av1.actionVar1 != 0) { if (this->av2.actionVar2 == 0) { - if (CVarGetInteger("gFastDrops", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { this->av1.actionVar1 = 0; } else { Message_StartTextbox(play, D_80854A04[this->av1.actionVar1 - 1].textId, &this->actor); @@ -13998,7 +13998,7 @@ void Player_Action_8084ECA4(Player* this, PlayState* play) { this->av2.actionVar2 = 0; this->interactRangeActor->parent = &this->actor; Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction)); - if (!CVarGetInteger("gFastDrops", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE; Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04); func_80835EA4(play, 4); @@ -14033,12 +14033,12 @@ void Player_Action_8084EED8(Player* this, PlayState* play) { Player_PlaySfx(this, NA_SE_EV_BOTTLE_CAP_OPEN); Player_PlaySfx(this, NA_SE_EV_FIATY_HEAL - SFX_FLAG); } else if (LinkAnimation_OnFrame(&this->skelAnime, 47.0f)) { - if (CVarGetInteger("gFairyEffect", 0)) { - if (CVarGetInteger("gFairyPercentRestore", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyEffect"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FairyPercentRestore"), 0)) { gSaveContext.healthAccumulator = - (gSaveContext.healthCapacity * CVarGetInteger("gFairyHealth", 100) / 100 + 15) / 16 * 16; + (gSaveContext.healthCapacity * CVarGetInteger(CVAR_ENHANCEMENT("FairyHealth"), 100) / 100 + 15) / 16 * 16; } else { - gSaveContext.healthAccumulator = CVarGetInteger("gFairyHealth", 8) * 16; + gSaveContext.healthAccumulator = CVarGetInteger(CVAR_ENHANCEMENT("FairyHealth"), 8) * 16; } } else { gSaveContext.healthAccumulator = 0x140; @@ -14695,7 +14695,7 @@ static AnimSfxEntry D_80854A8C[][2] = { }; void Player_Action_808507F4(Player* this, PlayState* play) { - u8 isFastFarores = CVarGetInteger("gFastFarores", 0) && this->itemAction == PLAYER_IA_FARORES_WIND; + u8 isFastFarores = CVarGetInteger(CVAR_ENHANCEMENT("FastFarores"), 0) && this->itemAction == PLAYER_IA_FARORES_WIND; if (LinkAnimation_Update(play, &this->skelAnime)) { if (this->av1.actionVar1 < 0) { if ((this->itemAction == PLAYER_IA_NAYRUS_LOVE) || isFastFarores || (gSaveContext.magicState == MAGIC_STATE_IDLE)) { @@ -15890,7 +15890,7 @@ void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) { sp24 = D_808547C4[this->cueId]; func_80852B4C(play, this, linkCsAction, &D_80854E50[ABS(sp24)]); - if (CVarGetInteger("gFixEyesOpenWhileSleeping", 0) && (play->csCtx.linkAction->action == 28 || play->csCtx.linkAction->action == 29)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 0) && (play->csCtx.linkAction->action == 28 || play->csCtx.linkAction->action == 29)) { this->skelAnime.jointTable[22].x = 8; } } diff --git a/soh/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c b/soh/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c index a1a46f6de..85c585462 100644 --- a/soh/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c +++ b/soh/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c @@ -222,7 +222,7 @@ static void draw_ico_sphere(Gfx** p_gfx_p, f32 x, f32 y, f32 z, f32 radius, Grap } void EffectSsSolderSrchBall_Draw(PlayState* play, u32 index, EffectSs* this) { - if (CVarGetInteger("gGuardVision", 0) == 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GuardVision"), 0) == 0) { return; } diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 327c1dd11..0517bfab6 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1318,10 +1318,10 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) { this->kbdY = 0; this->charIndex = 0; this->charBgAlpha = 0; - this->newFileNameCharCount = CVarGetInteger("gLinkDefaultName", 0) ? 4 : 0; + this->newFileNameCharCount = CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? 4 : 0; this->nameEntryBoxPosX = 120; this->nameEntryBoxAlpha = 0; - memcpy(Save_GetSaveMetaInfo(this->buttonIndex)->playerName, CVarGetInteger("gLinkDefaultName", 0) ? &linkName : &emptyName, 8); + memcpy(Save_GetSaveMetaInfo(this->buttonIndex)->playerName, CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? &linkName : &emptyName, 8); return; } } @@ -2005,7 +2005,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { &deathCountSplit[2]); // draw death count - if (CVarGetInteger("gFileSelectMoreInfo", 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) { FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE, vtxOffset); @@ -2029,7 +2029,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10; - if (CVarGetInteger("gFileSelectMoreInfo", 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { // draw hearts for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) { gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0); @@ -2046,7 +2046,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { textAlpha = 255; } - if (CVarGetInteger("gFileSelectMoreInfo", 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { DrawMoreInfo(this, fileIndex, textAlpha); } else { // draw quest items @@ -2336,7 +2336,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) { this->fileInfoAlpha[fileIndex]); // Draw the small file name box instead when more meta info is enabled - if (CVarGetInteger("gFileSelectMoreInfo", 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { // Location of file 1 small name box vertices gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0); @@ -2976,7 +2976,7 @@ void FileChoose_LoadGame(GameState* thisx) { gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.natureAmbienceId = 0xFF; gSaveContext.showTitleCard = true; - if (!CVarGetInteger("gDogFollowsEverywhere", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("DogFollowsEverywhere"), 0)) { gSaveContext.dogParams = 0; } gSaveContext.timer1State = 0; @@ -3282,7 +3282,7 @@ void FileChoose_Main(GameState* thisx) { sWindowContentColors[0][2] = 255; } - if (CVarGetInteger("gTimeFlowFileSelect", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 0) != 0) { gSaveContext.skyboxTime += 0x10; } diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 59afae8a5..f74c0298d 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -167,7 +167,7 @@ void Title_Draw(TitleContext* this) { Matrix_RotateZYX(0, sTitleRotY, 0, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(this->state.gfxCtx), G_MTX_LOAD); - if (CVarGetInteger("gAuthenticLogo", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("AuthenticLogo"), 0)) { gSPDisplayList(POLY_OPA_DISP++, gNintendo64LogoDL); } else { gSPDisplayList(POLY_OPA_DISP++, gShipLogoDL); @@ -192,7 +192,7 @@ void Title_Draw(TitleContext* this) { for (idx = 0, y = 94; idx < 16; idx++, y += 2) { - gDPLoadMultiTile(POLY_OPA_DISP++, CVarGetInteger("gAuthenticLogo", 0) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, + gDPLoadMultiTile(POLY_OPA_DISP++, CVarGetInteger(CVAR_ENHANCEMENT("AuthenticLogo"), 0) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, 0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 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); @@ -237,7 +237,7 @@ void Title_Main(GameState* thisx) { Title_Calc(this); Title_Draw(this); - if (!CVarGetInteger("gAuthenticLogo", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("AuthenticLogo"), 0)) { Gfx* gfx = POLY_OPA_DISP; s32 pad; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c index 3aa4a25d6..d2050bc80 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_debug.c @@ -641,7 +641,7 @@ void KaleidoScope_DrawDebugEditor(PlayState* play) { // Handles exiting the inventory editor with the L button // The editor is opened with `debugState` set to 1, and becomes closable after a frame once `debugState` is set to 2 s16 Debug_BTN = BTN_L; - if (CVarGetInteger("gNGCKaleidoSwitcher", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NGCKaleidoSwitcher"), 0) != 0) { Debug_BTN = BTN_Z; } if (pauseCtx->debugState == 1) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index d9d03d7cc..a67530f50 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -132,10 +132,10 @@ void KaleidoScope_DrawPlayerWork(PlayState* play) { //Vec3s rot; // Removed for not having it use din the function f32 scale; Input* input = &play->state.input[0]; - s16 RotationSpeed = 150 * CVarGetInteger("gPauseLiveLinkRotationSpeed", 0); - u8 AllowStickRotation = (CVarGetInteger("gPauseLiveLinkRotation", 0) == 3) ? true : false; - u8 AllowCRotation = (CVarGetInteger("gPauseLiveLinkRotation", 0) == 2) ? true : false; - u8 AllowDPadRotation = (CVarGetInteger("gPauseLiveLinkRotation", 0) == 1) ? true : false; + s16 RotationSpeed = 150 * CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLinkRotationSpeed"), 0); + u8 AllowStickRotation = (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 0) == 3) ? true : false; + u8 AllowCRotation = (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 0) == 2) ? true : false; + u8 AllowDPadRotation = (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLinkRotation"), 0) == 1) ? true : false; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { @@ -542,8 +542,8 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Allow Toggling of Strength when Pressing A on Strength Upgrade Slot if ((pauseCtx->cursorSpecialPos == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && CHECK_BTN_ALL(input->press.button, BTN_A) && - (pauseCtx->cursorX[PAUSE_EQUIP] == 0) && (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && CVarGetInteger("gToggleStrength", 0)) { - CVarSetInteger("gStrengthDisabled", !CVarGetInteger("gStrengthDisabled", 0)); + (pauseCtx->cursorX[PAUSE_EQUIP] == 0) && (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0)) { + CVarSetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), !CVarGetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0)); // Equip success sound Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); // Wait 10 frames before accepting input again @@ -569,10 +569,10 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Only BGS/Giant's Knife is affected, and it will revert to Master Sword. // If we have the feature toggled on - if (CVarGetInteger("gEquipmentCanBeRemoved", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("EquipmentCanBeRemoved"), 0)) { - if (CVarGetInteger("gEnhancements.SwordToggle", SWORD_TOGGLE_NONE) == SWORD_TOGGLE_BOTH_AGES || - (CVarGetInteger("gEnhancements.SwordToggle", SWORD_TOGGLE_NONE) == SWORD_TOGGLE_CHILD) && LINK_IS_CHILD) { + if (CVarGetInteger(CVAR_ENHANCEMENT("SwordToggle"), SWORD_TOGGLE_NONE) == SWORD_TOGGLE_BOTH_AGES || + (CVarGetInteger(CVAR_ENHANCEMENT("SwordToggle"), SWORD_TOGGLE_NONE) == SWORD_TOGGLE_CHILD) && LINK_IS_CHILD) { // If we're on the "swords" section of the equipment screen AND we're on a currently-equipped sword if (pauseCtx->cursorY[PAUSE_EQUIP] == 0 && pauseCtx->cursorX[PAUSE_EQUIP] == CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD)) { Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_NONE); @@ -640,7 +640,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); pauseCtx->unk_1E4 = 7; sEquipTimer = 10; - } else if (CVarGetInteger("gAssignableTunicsAndBoots", 0) != 0) { + } else if (CVarGetInteger(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 0) != 0) { // Only allow assigning tunic and boots to c-buttons if (pauseCtx->cursorY[PAUSE_EQUIP] > 1) { if (CHECK_OWNED_EQUIP(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP] - 1)) { @@ -680,7 +680,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { EQUIP_FAIL: if (CHECK_BTN_ALL(input->press.button, BTN_A)) { Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - } else if ((CVarGetInteger("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) { + } else if ((CVarGetInteger(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) { Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } } @@ -704,8 +704,8 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Do not Grey Out Strength Upgrade Name when Enabled // This needs to be outside the previous block since otherwise the nameColorSet is cleared to 0 by other menu pages when toggling if ((pauseCtx->pageIndex == PAUSE_EQUIP) && (pauseCtx->cursorX[PAUSE_EQUIP] == 0) && - (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && CVarGetInteger("gToggleStrength", 0)) { - if (CVarGetInteger("gStrengthDisabled", 0)) { + (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0)) { pauseCtx->nameColorSet = 1; } else { pauseCtx->nameColorSet = 0; @@ -735,7 +735,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Add zoom effect to strength item if cursor is hovering over it when toggle option is on if ((pauseCtx->cursorX[PAUSE_EQUIP] == 0) && (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && - CVarGetInteger("gToggleStrength", 0) && pauseCtx->cursorSpecialPos == 0) { + CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0) && pauseCtx->cursorSpecialPos == 0) { u8 row = 2; u8 column = 0; u8 equipVtxIndex = 16 * row + 4 * column; @@ -765,7 +765,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { if ((drawGreyItems && ((sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1) == ITEM_GAUNTLETS_SILVER || (sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1) == ITEM_GAUNTLETS_GOLD)) || - (CVarGetInteger("gToggleStrength", 0) && CVarGetInteger("gStrengthDisabled", 0) && sChildUpgrades[i] == UPG_STRENGTH)) { + (CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0) && sChildUpgrades[i] == UPG_STRENGTH)) { gDPSetGrayscaleColor(POLY_KAL_DISP++, 109, 109, 109, 255); gSPGrayscale(POLY_KAL_DISP++, true); } @@ -785,8 +785,8 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Grey Out Strength Upgrades when Disabled and the Toggle Strength Option is on if ((drawGreyItems && (((sAdultUpgradeItemBases[i] + CUR_UPG_VALUE(sAdultUpgrades[i]) - 1) == ITEM_BRACELET && - !(IS_RANDO) && !CVarGetInteger("gToggleStrength", 0)))) || - (CVarGetInteger("gToggleStrength", 0) && CVarGetInteger("gStrengthDisabled", 0) && sAdultUpgrades[i] == UPG_STRENGTH)) { + !(IS_RANDO) && !CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0)))) || + (CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0) && sAdultUpgrades[i] == UPG_STRENGTH)) { gDPSetGrayscaleColor(POLY_KAL_DISP++, 109, 109, 109, 255); gSPGrayscale(POLY_KAL_DISP++, true); } @@ -816,7 +816,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Render A button indicator when hovered over strength if ((pauseCtx->cursorX[PAUSE_EQUIP] == 0) && (pauseCtx->cursorY[PAUSE_EQUIP] == 2) && - CVarGetInteger("gToggleStrength", 0) && pauseCtx->cursorSpecialPos == 0 + CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0) && pauseCtx->cursorSpecialPos == 0 && pauseCtx->unk_1E4 == 0 && pauseCtx->state == 6) { u8 row = 2; u8 column = 0; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 1060131ab..004686a4e 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -70,7 +70,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gDPPipeSync(POLY_KAL_DISP++); if (i != 0) { - gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 31) * 4], 4, 0); + gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger(CVAR_ENHANCEMENT("BetterAmmoRendering"), 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 31) * 4], 4, 0); gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[i]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, @@ -79,7 +79,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); } - gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 32) * 4], 4, 0); + gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[((CVarGetInteger(CVAR_ENHANCEMENT("BetterAmmoRendering"), 0) ? sAllAmmoVtxOffset[slot] : sAmmoVtxOffset[slot]) + 32) * 4], 4, 0); gDPLoadTextureBlock(POLY_KAL_DISP++, ((u8*)_gAmmoDigit0Tex[ammo]), G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, @@ -313,7 +313,7 @@ bool CanMaskSelect() { // * zelda's letter check: Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) // * kak gate check: Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD) // and the mask quest is complete: Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE) - return CVarGetInteger("gMaskSelect", 0) && + return CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) && Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE) && Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); @@ -339,7 +339,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { //to allow adult link to wear it if the setting is enabled gSlotAgeReqs[SLOT_TRADE_CHILD] = ( - ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || + ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) ) && INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY @@ -348,7 +348,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { //also update the age requirement for the bunny hood itself gItemAgeReqs[ITEM_MASK_BUNNY] = - ((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || + ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0) ? AGE_REQ_NONE : AGE_REQ_CHILD; @@ -779,7 +779,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { gDPSetCombineLERP(POLY_KAL_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - u8 gBetterAmmoRendering = CVarGetInteger("gEnhancements.BetterAmmoRendering", 0); + u8 gBetterAmmoRendering = CVarGetInteger(CVAR_ENHANCEMENT("BetterAmmoRendering"), 0); for (i = 0; i < (gBetterAmmoRendering ? 24 : 15); i++) { if ((gBetterAmmoRendering ? ItemInSlotUsesAmmo(i) : gAmmoItems[i] != ITEM_NONE) && (gSaveContext.inventory.items[i] != ITEM_NONE)) { @@ -826,7 +826,7 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, sEquipMoveTimer = 10; if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) || (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) { - if (CVarGetInteger("gSkipArrowAnimation", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("SkipArrowAnimation"), 0)) { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } else { u16 index = 0; @@ -1037,7 +1037,7 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { if (D_8082A488 == 0) { pauseCtx->equipTargetItem -= 0xBF - ITEM_BOW_ARROW_FIRE; - if (!CVarGetInteger("gSeparateArrows", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("SeparateArrows"), 0)) { pauseCtx->equipTargetSlot = SLOT_BOW; } sEquipMoveTimer = 6; @@ -1123,7 +1123,7 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { pauseCtx->equipTargetItem = ITEM_BOW_ARROW_LIGHT; break; } - if (!CVarGetInteger("gSeparateArrows", 0)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("SeparateArrows"), 0)) { pauseCtx->equipTargetSlot = SLOT_BOW; } } @@ -1156,7 +1156,7 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { if (pauseCtx->equipTargetItem == ITEM_BOW) { if (gSaveContext.equips.buttonItems[otherButtonIndex] >= ITEM_BOW_ARROW_FIRE && gSaveContext.equips.buttonItems[otherButtonIndex] <= ITEM_BOW_ARROW_LIGHT && - !CVarGetInteger("gSeparateArrows", 0)) { + !CVarGetInteger(CVAR_ENHANCEMENT("SeparateArrows"), 0)) { gSaveContext.equips.buttonItems[otherButtonIndex] = gSaveContext.equips.buttonItems[targetButtonIndex]; gSaveContext.equips.cButtonSlots[otherSlotIndex] = gSaveContext.equips.cButtonSlots[pauseCtx->equipTargetCBtn]; Interface_LoadItemIcon2(play, otherButtonIndex); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 12fa4d19e..131fb7339 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1057,7 +1057,7 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { gSaveContext.buttonStatus[buttonIndex] = D_8082AB6C[pauseCtx->pageIndex + pt][buttonIndex]; } - if ((CVarGetInteger("gAssignableTunicsAndBoots", 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) { gSaveContext.buttonStatus[1] = BTN_ENABLED; gSaveContext.buttonStatus[2] = BTN_ENABLED; gSaveContext.buttonStatus[3] = BTN_ENABLED; @@ -1079,7 +1079,7 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { s16 Debug_BTN = BTN_L; s16 PageLeft_BTN = BTN_Z; - if (CVarGetInteger("gNGCKaleidoSwitcher", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("NGCKaleidoSwitcher"), 0) != 0) { Debug_BTN = BTN_Z; PageLeft_BTN = BTN_L; } @@ -1618,7 +1618,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, sPromptChoiceTexs[gSaveContext.language][1], 48, 16, 16); } else if (((pauseCtx->state == 7 && pauseCtx->unk_1EC >= 4) || pauseCtx->state == 0xF) && - !CVarGetInteger("gSkipSaveConfirmation", 0)) { + !CVarGetInteger(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 0)) { POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, sSaveConfirmationTexs[gSaveContext.language], 152, 16, 0); } else if ((pauseCtx->state != 7) || (pauseCtx->unk_1EC < 4)) { @@ -1890,14 +1890,14 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { gSPDisplayList(POLY_KAL_DISP++, gItemNamePanelDL); - if (CVarGetInteger("gUniformLR", 0) == 0) { // Restore the misplace gDPSetPrimColor + if (CVarGetInteger(CVAR_ENHANCEMENT("FixMenuLR"), 0) == 0) { // Restore the misplace gDPSetPrimColor gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 90, 100, 130, 255); } if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->unk_1E4 == 0)) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, D_808321A0, D_808321A2, D_808321A4, D_808321A6); } else { - if (CVarGetInteger("gUniformLR", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixMenuLR"), 0) != 0) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255); } } @@ -1905,14 +1905,14 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { gSPDisplayList(POLY_KAL_DISP++, gLButtonIconDL); - if (CVarGetInteger("gUniformLR", 0) == 0) { //Restore the misplace gDPSetPrimColor + if (CVarGetInteger(CVAR_ENHANCEMENT("FixMenuLR"), 0) == 0) { //Restore the misplace gDPSetPrimColor gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255); } if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) && (pauseCtx->unk_1E4 == 0)) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, D_808321A0, D_808321A2, D_808321A4, D_808321A6); } else { - if (CVarGetInteger("gUniformLR", 0) != 0) { + if (CVarGetInteger(CVAR_ENHANCEMENT("FixMenuLR"), 0) != 0) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 180, 210, 255, 255); } } @@ -2827,7 +2827,7 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorVtx[19].v.tc[1] = 0x400; // 24 items, 7 "item selected" backgrounds, 14 ammo digits (2 each for 7 items) -- then 4 vertices for each - pauseCtx->itemVtx = Graph_Alloc(gfxCtx, (24 + 7 + 2 * (CVarGetInteger("gEnhancements.BetterAmmoRendering", 0) ? ARRAY_COUNT(D_8082B11C_all) : ARRAY_COUNT(D_8082B11C))) * 4 * sizeof(Vtx)); + pauseCtx->itemVtx = Graph_Alloc(gfxCtx, (24 + 7 + 2 * (CVarGetInteger(CVAR_ENHANCEMENT("BetterAmmoRendering"), 0) ? ARRAY_COUNT(D_8082B11C_all) : ARRAY_COUNT(D_8082B11C))) * 4 * sizeof(Vtx)); for (phi_t4 = 0, phi_t2 = 0, phi_t5 = 58; phi_t4 < 4; phi_t4++, phi_t5 -= 32) { for (phi_t1 = -96, phi_t3 = 0; phi_t3 < 6; phi_t3++, phi_t2 += 4, phi_t1 += 32) { @@ -2917,7 +2917,7 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { } } - u8 gBetterAmmoRendering = CVarGetInteger("gEnhancements.BetterAmmoRendering", 0); + u8 gBetterAmmoRendering = CVarGetInteger(CVAR_ENHANCEMENT("BetterAmmoRendering"), 0); for (phi_t3 = 0; phi_t3 < (gBetterAmmoRendering ? ARRAY_COUNT(D_8082B11C_all) : ARRAY_COUNT(D_8082B11C)); phi_t3++) { phi_t4 = gBetterAmmoRendering ? D_8082B11C_all[phi_t3] : D_8082B11C[phi_t3]; @@ -3302,7 +3302,7 @@ void func_808265BC(PlayState* play) { pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode]; - if ((CVarGetInteger("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) { gSaveContext.buttonStatus[1] = BTN_ENABLED; gSaveContext.buttonStatus[2] = BTN_ENABLED; gSaveContext.buttonStatus[3] = BTN_ENABLED; @@ -4157,7 +4157,7 @@ void KaleidoScope_Update(PlayState* play) &D_801333E8); Play_PerformSave(play); pauseCtx->unk_1EC = 4; - D_8082B25C = CVarGetInteger("gSkipSaveConfirmation", 0) ? 3 /* 0.1 sec */ : 90 /* 3 secs */; + D_8082B25C = CVarGetInteger(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 0) ? 3 /* 0.1 sec */ : 90 /* 3 secs */; } } else if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) { @@ -4405,7 +4405,7 @@ void KaleidoScope_Update(PlayState* play) gSaveContext.savedSceneNum = play->sceneNum; Save_SaveFile(); pauseCtx->state = 0xF; - D_8082B25C = CVarGetInteger("gSkipSaveConfirmation", 0) ? 3 /* 0.1 sec */ : 90 /* 3 secs */; + D_8082B25C = CVarGetInteger(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 0) ? 3 /* 0.1 sec */ : 90 /* 3 secs */; } } break; @@ -4508,7 +4508,7 @@ void KaleidoScope_Update(PlayState* play) // Reset frame counter to prevent autosave on respawn play->gameplayFrames = 0; gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK; - gSaveContext.health = CVarGetInteger("gFullHealthSpawn", 0) ? gSaveContext.healthCapacity : 0x30; + gSaveContext.health = CVarGetInteger(CVAR_ENHANCEMENT("FullHealthSpawn"), 0) ? gSaveContext.healthCapacity : 0x30; Audio_QueueSeqCmd(0xF << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xA); gSaveContext.healthAccumulator = 0; gSaveContext.magicState = MAGIC_STATE_IDLE; From 303fe7d906ad7730d70471dc2811dc80b14c0c4b Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 25 Apr 2024 19:41:55 -0700 Subject: [PATCH 195/300] Swap all cosmetics CVars to macros. (#4065) Lots of renames. Co-authored-by: Garrett Cox --- .../cosmetics/CosmeticsEditor.cpp | 744 +++++++++--------- .../GameInteractor_RawAction.cpp | 72 +- soh/soh/Enhancements/nametag.cpp | 9 +- soh/soh/Enhancements/presets.h | 14 +- .../randomizer/randomizer_check_tracker.cpp | 2 +- soh/soh/OTRGlobals.cpp | 26 +- soh/src/code/z_actor.c | 44 +- soh/src/code/z_draw.c | 6 +- soh/src/code/z_eff_blure.c | 32 +- soh/src/code/z_en_item00.c | 20 +- soh/src/code/z_kankyo.c | 6 +- soh/src/code/z_lifemeter.c | 84 +- soh/src/code/z_map_exp.c | 152 ++-- soh/src/code/z_map_mark.c | 28 +- soh/src/code/z_message_PAL.c | 58 +- soh/src/code/z_parameter.c | 708 ++++++++--------- soh/src/code/z_player_lib.c | 32 +- .../actors/ovl_Arrow_Fire/z_arrow_fire.c | 8 +- .../actors/ovl_Arrow_Ice/z_arrow_ice.c | 8 +- .../actors/ovl_Arrow_Light/z_arrow_light.c | 8 +- .../ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c | 4 +- .../ovl_Bg_Spot01_Fusya/z_bg_spot01_fusya.c | 4 +- .../overlays/actors/ovl_En_Arrow/z_en_arrow.c | 32 +- .../actors/ovl_En_Bom_Chu/z_en_bom_chu.c | 4 +- soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c | 8 +- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 2 +- .../actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c | 20 +- .../actors/ovl_En_Firefly/z_en_firefly.c | 16 +- .../actors/ovl_En_G_Switch/z_en_g_switch.c | 50 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 2 +- soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c | 4 +- soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c | 4 +- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c | 6 +- .../actors/ovl_En_M_Thunder/z_en_m_thunder.c | 24 +- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 8 +- .../actors/ovl_En_Partner/z_en_partner.c | 8 +- .../ovl_Obj_Timeblock/z_obj_timeblock.c | 4 +- .../actors/ovl_player_actor/z_player.c | 34 +- .../ovl_file_choose/z_file_choose.c | 20 +- .../ovl_file_choose/z_file_nameset_PAL.c | 4 +- .../overlays/gamestates/ovl_title/z_title.c | 6 +- .../ovl_kaleido_scope/z_kaleido_collect.c | 26 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 6 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 82 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 102 +-- 45 files changed, 1271 insertions(+), 1270 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 8dbabd460..65659a80f 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -94,7 +94,7 @@ typedef struct { #define COSMETIC_OPTION(id, label, group, defaultColor, supportsAlpha, supportsRainbow, advancedOption) \ { id, { \ - "gCosmetics." id ".Value", "gCosmetics." id ".Rainbow", "gCosmetics." id ".Locked", "gCosmetics." id ".Changed", label, group, \ + CVAR_COSMETIC(id ".Value"), CVAR_COSMETIC(id ".Rainbow"), CVAR_COSMETIC(id ".Locked"), CVAR_COSMETIC(id ".Changed"), label, group, \ defaultColor, defaultColor, \ supportsAlpha, supportsRainbow, advancedOption \ } } @@ -153,8 +153,8 @@ typedef struct { gDPSetEnvColor(POLY_OPA_DISP++, 80, 70, 20, alpha); // with cosmetics change - if (CVarGetInteger("gCosmetics.World_Moon.Changed", 0)) { - Color_RGB8 moonColor = CVarGetColor24("gCosmetics.World_Moon.Value", (Color_RGB8){ 0, 0, 240 }); + if (CVarGetInteger(CVAR_COSMETIC("World.Moon.Changed"), 0)) { + Color_RGB8 moonColor = CVarGetColor24(CVAR_COSMETIC("World.Moon.Value"), (Color_RGB8){ 0, 0, 240 }); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, moonColor.r, moonColor.g, moonColor.b, alpha); gDPSetEnvColor(POLY_OPA_DISP++, moonColor.r / 2, moonColor.g / 2, moonColor.b / 2, alpha); } else { @@ -173,188 +173,188 @@ typedef struct { colors were darker than the gDPSetPrimColor. You will see many more examples of this below in the `ApplyOrResetCustomGfxPatches` method */ static std::map cosmeticOptions = { - COSMETIC_OPTION("Link_KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), - COSMETIC_OPTION("Link_GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), - COSMETIC_OPTION("Link_ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), - COSMETIC_OPTION("Link_Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), - COSMETIC_OPTION("Link_Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Link_Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), + COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), + COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), + COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), + COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), - COSMETIC_OPTION("MirrorShield_Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), - COSMETIC_OPTION("MirrorShield_Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("MirrorShield_Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), + COSMETIC_OPTION("MirrorShield.Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), - COSMETIC_OPTION("Swords_KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords_MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords_BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords_BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords.KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords.KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords.MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords.MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords.BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Swords.BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Gloves_GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), - COSMETIC_OPTION("Gloves_SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Gloves_GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), - COSMETIC_OPTION("Gloves_GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), + COSMETIC_OPTION("Gloves.GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Gloves.SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Gloves.GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), + COSMETIC_OPTION("Gloves.GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), - COSMETIC_OPTION("Equipment_BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Equipment_BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), - // COSMETIC_OPTION("Equipment_SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Equipment_SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), - COSMETIC_OPTION("Equipment_HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), - // COSMETIC_OPTION("Equipment_HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Equipment_HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - COSMETIC_OPTION("HookshotReticle_Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, false, false), - COSMETIC_OPTION("HookshotReticle_NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, false, false), - COSMETIC_OPTION("Equipment_BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Equipment_BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), - COSMETIC_OPTION("Equipment_BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment_ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), - COSMETIC_OPTION("Equipment_ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), - COSMETIC_OPTION("Equipment_BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), + COSMETIC_OPTION("Equipment.BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment.BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), + // COSMETIC_OPTION("Equipment.SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Equipment.SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), + COSMETIC_OPTION("Equipment.HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), + // COSMETIC_OPTION("Equipment.HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Equipment.HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement + COSMETIC_OPTION("HookshotReticle.Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, false, false), + COSMETIC_OPTION("HookshotReticle.NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, false, false), + COSMETIC_OPTION("Equipment.BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), + COSMETIC_OPTION("Equipment.BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), + COSMETIC_OPTION("Equipment.BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), - COSMETIC_OPTION("Consumable_Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), - COSMETIC_OPTION("Consumable_HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), - COSMETIC_OPTION("Consumable_DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable_DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable_MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), - COSMETIC_OPTION("Consumable_MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable_MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable_GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable_BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable_PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable_GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), - COSMETIC_OPTION("Consumable_SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), + COSMETIC_OPTION("Consumable.HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), + COSMETIC_OPTION("Consumable.DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), + COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), + COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), + COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Hud_Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud_Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud_MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Hud_EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), - COSMETIC_OPTION("Hud_EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), - COSMETIC_OPTION("Hud_NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("Hud_NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), + COSMETIC_OPTION("Hud.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), + COSMETIC_OPTION("Hud.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), + COSMETIC_OPTION("Hud.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), + COSMETIC_OPTION("Hud.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Hud.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Hud.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), + COSMETIC_OPTION("Hud.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Hud.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Hud.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Hud.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), + COSMETIC_OPTION("Hud.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), + COSMETIC_OPTION("Hud.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("Hud.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), - COSMETIC_OPTION("Kal_ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), - COSMETIC_OPTION("Kal_ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kal_ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kal_ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), - COSMETIC_OPTION("Kal_EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kal_QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kal_MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kal_MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), - COSMETIC_OPTION("Kal_SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kal_SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Kal_NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), + COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), - COSMETIC_OPTION("Title_FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Title_NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), - COSMETIC_OPTION("Title_N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), - // COSMETIC_OPTION("Title_FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), // Todo (Cosmetics): Kinda complicated - // COSMETIC_OPTION("Title_FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), // Todo (Cosmetics): Kinda complicated + COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), + // COSMETIC_OPTION("Title.FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), // Todo (Cosmetics): Kinda complicated + // COSMETIC_OPTION("Title.FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), // Todo (Cosmetics): Kinda complicated - COSMETIC_OPTION("Arrows_NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows_NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("Arrows_FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows_FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Arrows_IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), - COSMETIC_OPTION("Arrows_IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Arrows_LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Arrows_LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), + COSMETIC_OPTION("Arrows.NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("Arrows.FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Arrows.IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), + COSMETIC_OPTION("Arrows.IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), - // COSMETIC_OPTION("Magic_DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gDF_Col - // COSMETIC_OPTION("Magic_DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gDF_Env - // COSMETIC_OPTION("Magic_FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic_FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic_NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gNL_Diamond_Col / gNL_Orb_Col - // COSMETIC_OPTION("Magic_NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gNL_Diamond_Env / gNL_Orb_Env + // COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gDF_Col + // COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gDF_Env + // COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement + // COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gNL_Diamond_Col / gNL_Orb_Col + // COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gNL_Diamond_Env / gNL_Orb_Env - COSMETIC_OPTION("SpinAttack_Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), - COSMETIC_OPTION("SpinAttack_Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), - COSMETIC_OPTION("SpinAttack_Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("SpinAttack_Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), + COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), + COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), + COSMETIC_OPTION("SpinAttack.Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("SpinAttack.Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Trails_Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Trails_Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), - COSMETIC_OPTION("Trails_KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails_MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails_BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails_Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails_Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Trails.Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), + COSMETIC_OPTION("Trails.KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails.MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails.BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World_BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World_Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), - COSMETIC_OPTION("World_GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), - COSMETIC_OPTION("World_RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), + COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), + COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Navi_IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), - COSMETIC_OPTION("Navi_NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Navi_NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), - COSMETIC_OPTION("Navi_EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), - COSMETIC_OPTION("Navi_PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi_PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), + COSMETIC_OPTION("Navi.PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), - COSMETIC_OPTION("Ivan_IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Ivan_IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Ivan.IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Ivan.IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), - COSMETIC_OPTION("NPC_FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC_IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Health fairy - COSMETIC_OPTION("NPC_Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), - COSMETIC_OPTION("NPC_Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), - COSMETIC_OPTION("NPC_GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC_Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), - COSMETIC_OPTION("NPC_Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), - COSMETIC_OPTION("NPC_MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC_IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), + COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), + COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), + COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), + COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), + COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), }; static const char* MarginCvarList[] { - "gHearts", "gHeartsCount", "gMagicBar", "gVSOA", "gBBtn", "gABtn", "gStartBtn", - "gCBtnU", "gCBtnD", "gCBtnL", "gCBtnR", "gDPad", "gMinimap", - "gSKC", "gRC", "gCarrots", "gTimers", "gAS", "gTCM", "gTCB", "gIGT" + CVAR_COSMETIC("Hearts"), CVAR_COSMETIC("HeartsCount"), CVAR_COSMETIC("MagicBar"), CVAR_COSMETIC("VisualSoA"), CVAR_COSMETIC("BButton"), CVAR_COSMETIC("AButton"), CVAR_COSMETIC("StartButton"), + CVAR_COSMETIC("CUpButton"), CVAR_COSMETIC("CDownButton"), CVAR_COSMETIC("CLeftButton"), CVAR_COSMETIC("CRightButton"), CVAR_COSMETIC("Dpad"), CVAR_COSMETIC("Minimap"), + CVAR_COSMETIC("SmallKey"), CVAR_COSMETIC("Rupees"), CVAR_COSMETIC("Carrots"), CVAR_COSMETIC("Timers"), CVAR_COSMETIC("ArcheryScore"), CVAR_COSMETIC("TitleCard.Map"), CVAR_COSMETIC("TitleCard.Boss"), CVAR_COSMETIC("IGT") }; -static const char* MarginCvarNonAnchor[]{ "gCarrots", "gTimers", "gAS", "gTCM","gTCB" }; +static const char* MarginCvarNonAnchor[]{ CVAR_COSMETIC("Carrots"), CVAR_COSMETIC("Timers"), CVAR_COSMETIC("ArcheryScore"), CVAR_COSMETIC("TitleCard.Map"),CVAR_COSMETIC("TitleCard.Boss") }; ImVec4 GetRandomValue(int MaximumPossible){ ImVec4 NewColor; @@ -379,8 +379,8 @@ void SetMarginAll(const char* ButtonName, bool SetActivated) { //MarginCvarNonAnchor is an array that list every element that has No anchor by default, because if that the case this function will not touch it with pose type 0. u8 arrayLengthNonMargin = sizeof(MarginCvarNonAnchor) / sizeof(*MarginCvarNonAnchor); for (auto cvarName : MarginCvarList) { - std::string cvarPosType = std::string(cvarName).append("PosType"); - std::string cvarNameMargins = std::string(cvarName).append("UseMargins"); + std::string cvarPosType = std::string(cvarName).append(".PosType"); + std::string cvarNameMargins = std::string(cvarName).append(".UseMargins"); if (CVarGetInteger(cvarPosType.c_str(),0) <= 2 && SetActivated) { //Our element is not Hidden or Non anchor for (int i = 0; i < arrayLengthNonMargin; i++){ if ((strcmp(cvarName, MarginCvarNonAnchor[i]) == 0) && (CVarGetInteger(cvarPosType.c_str(), 0) == 0)) { //Our element is both in original position and do not have anchor by default so we skip it. @@ -403,8 +403,8 @@ void SetMarginAll(const char* ButtonName, bool SetActivated) { void ResetPositionAll() { if (ImGui::Button("Reset all positions")) { for (auto cvarName : MarginCvarList) { - std::string cvarPosType = std::string(cvarName).append("PosType"); - std::string cvarNameMargins = std::string(cvarName).append("UseMargins"); + std::string cvarPosType = std::string(cvarName).append(".PosType"); + std::string cvarNameMargins = std::string(cvarName).append(".UseMargins"); CVarSetInteger(cvarPosType.c_str(), 0); CVarSetInteger(cvarNameMargins.c_str(), false); //Turn margin off to everythings as that original position. } @@ -416,7 +416,7 @@ int hue = 0; // Runs every frame to update rainbow hue, a potential future optimization is to only run this a once or twice a second and increase the speed of the rainbow hue rotation. void CosmeticsUpdateTick() { int index = 0; - float rainbowSpeed = CVarGetFloat("gCosmetics.RainbowSpeed", 0.6f); + float rainbowSpeed = CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f); for (auto& [id, cosmeticOption] : cosmeticOptions) { if (cosmeticOption.supportsRainbow && CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { float frequency = 2 * M_PI / (360 * rainbowSpeed); @@ -440,7 +440,7 @@ void CosmeticsUpdateTick() { // If we don't want the rainbow color on items to be synced, offset the index for each item in the loop. // Technically this would work if you replaced "60" with 1 but the hue would be so close it's // indistinguishable, 60 gives us a big enough gap to notice the difference. - if (!CVarGetInteger("gCosmetics.RainbowSync", 0)) { + if (!CVarGetInteger(CVAR_COSMETIC("RainbowSync"), 0)) { index+= (60 * rainbowSpeed); } } @@ -459,7 +459,7 @@ void CosmeticsUpdateTick() { 5. GFX Command: The GFX command you want to insert */ void ApplyOrResetCustomGfxPatches(bool manualChange) { - static CosmeticOption& linkGoronTunic = cosmeticOptions.at("Link_GoronTunic"); + static CosmeticOption& linkGoronTunic = cosmeticOptions.at("Link.GoronTunic"); if (manualChange || CVarGetInteger(linkGoronTunic.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkGoronTunic.defaultColor.x, linkGoronTunic.defaultColor.y, linkGoronTunic.defaultColor.z, linkGoronTunic.defaultColor.w}; Color_RGBA8 color = CVarGetColor(linkGoronTunic.cvar, defaultColor); @@ -469,7 +469,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiGoronCollarColorDL, "Link_GoronTunic4", linkGoronTunic.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - static CosmeticOption& linkZoraTunic = cosmeticOptions.at("Link_ZoraTunic"); + static CosmeticOption& linkZoraTunic = cosmeticOptions.at("Link.ZoraTunic"); if (manualChange || CVarGetInteger(linkZoraTunic.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkZoraTunic.defaultColor.x, linkZoraTunic.defaultColor.y, linkZoraTunic.defaultColor.z, linkZoraTunic.defaultColor.w}; Color_RGBA8 color = CVarGetColor(linkZoraTunic.cvar, defaultColor); @@ -479,7 +479,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiZoraCollarColorDL, "Link_ZoraTunic4", linkZoraTunic.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - static CosmeticOption& linkHair = cosmeticOptions.at("Link_Hair"); + static CosmeticOption& linkHair = cosmeticOptions.at("Link.Hair"); if (manualChange || CVarGetInteger(linkHair.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkHair.defaultColor.x, linkHair.defaultColor.y, linkHair.defaultColor.z, linkHair.defaultColor.w}; Color_RGBA8 color = CVarGetColor(linkHair.cvar, defaultColor); @@ -502,7 +502,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } } - static CosmeticOption& linkLinen = cosmeticOptions.at("Link_Linen"); + static CosmeticOption& linkLinen = cosmeticOptions.at("Link.Linen"); if (manualChange || CVarGetInteger(linkLinen.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkLinen.defaultColor.x, linkLinen.defaultColor.y, linkLinen.defaultColor.z, linkLinen.defaultColor.w}; Color_RGBA8 color = CVarGetColor(linkLinen.cvar, defaultColor); @@ -544,7 +544,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } } - static CosmeticOption& linkBoots = cosmeticOptions.at("Link_Boots"); + static CosmeticOption& linkBoots = cosmeticOptions.at("Link.Boots"); if (manualChange || CVarGetInteger(linkBoots.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkBoots.defaultColor.x, linkBoots.defaultColor.y, linkBoots.defaultColor.z, linkBoots.defaultColor.w}; Color_RGBA8 color = CVarGetColor(linkBoots.cvar, defaultColor); @@ -581,7 +581,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } } - static CosmeticOption& mirrorShieldBody = cosmeticOptions.at("MirrorShield_Body"); + static CosmeticOption& mirrorShieldBody = cosmeticOptions.at("MirrorShield.Body"); if (manualChange || CVarGetInteger(mirrorShieldBody.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {mirrorShieldBody.defaultColor.x, mirrorShieldBody.defaultColor.y, mirrorShieldBody.defaultColor.z, mirrorShieldBody.defaultColor.w}; Color_RGBA8 color = CVarGetColor(mirrorShieldBody.cvar, defaultColor); @@ -594,7 +594,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingMirrorShieldNearDL, "MirrorShield_Body7", mirrorShieldBody.changedCvar, 28, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultRightHandHoldingMirrorShieldFarDL, "MirrorShield_Body8", mirrorShieldBody.changedCvar, 95, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& mirrorShieldMirror = cosmeticOptions.at("MirrorShield_Mirror"); + static CosmeticOption& mirrorShieldMirror = cosmeticOptions.at("MirrorShield.Mirror"); if (manualChange || CVarGetInteger(mirrorShieldMirror.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {mirrorShieldMirror.defaultColor.x, mirrorShieldMirror.defaultColor.y, mirrorShieldMirror.defaultColor.z, mirrorShieldMirror.defaultColor.w}; Color_RGBA8 color = CVarGetColor(mirrorShieldMirror.cvar, defaultColor); @@ -607,7 +607,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingMirrorShieldNearDL, "MirrorShield_Mirror7", mirrorShieldMirror.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultRightHandHoldingMirrorShieldFarDL, "MirrorShield_Mirror8", mirrorShieldMirror.changedCvar, 111, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& mirrorShieldEmblem = cosmeticOptions.at("MirrorShield_Emblem"); + static CosmeticOption& mirrorShieldEmblem = cosmeticOptions.at("MirrorShield.Emblem"); if (manualChange || CVarGetInteger(mirrorShieldEmblem.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {mirrorShieldEmblem.defaultColor.x, mirrorShieldEmblem.defaultColor.y, mirrorShieldEmblem.defaultColor.z, mirrorShieldEmblem.defaultColor.w}; Color_RGBA8 color = CVarGetColor(mirrorShieldEmblem.cvar, defaultColor); @@ -621,7 +621,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingMirrorShieldFarDL, "MirrorShield_Emblem8", mirrorShieldEmblem.changedCvar, 133, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& swordsKokiriBlade = cosmeticOptions.at("Swords_KokiriBlade"); + static CosmeticOption& swordsKokiriBlade = cosmeticOptions.at("Swords.KokiriBlade"); if (manualChange || CVarGetInteger(swordsKokiriBlade.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {swordsKokiriBlade.defaultColor.x, swordsKokiriBlade.defaultColor.y, swordsKokiriBlade.defaultColor.z, swordsKokiriBlade.defaultColor.w}; Color_RGBA8 color = CVarGetColor(swordsKokiriBlade.cvar, defaultColor); @@ -630,7 +630,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriBlade3", swordsKokiriBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriBlade4", swordsKokiriBlade.changedCvar, 6, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255)); } - // static CosmeticOption& swordsKokiriHilt = cosmeticOptions.at("Swords_KokiriHilt"); + // static CosmeticOption& swordsKokiriHilt = cosmeticOptions.at("Swords.KokiriHilt"); // if (manualChange || CVarGetInteger(swordsKokiriHilt.rainbowCvar, 0)) { // static Color_RGBA8 defaultColor = {swordsKokiriHilt.defaultColor.x, swordsKokiriHilt.defaultColor.y, swordsKokiriHilt.defaultColor.z, swordsKokiriHilt.defaultColor.w}; // Color_RGBA8 color = CVarGetColor(swordsKokiriHilt.cvar, defaultColor); @@ -671,7 +671,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt33", swordsKokiriHilt.changedCvar, 118, gsSPGrayscale(false)); // } // } - static CosmeticOption& swordsMasterBlade = cosmeticOptions.at("Swords_MasterBlade"); + static CosmeticOption& swordsMasterBlade = cosmeticOptions.at("Swords.MasterBlade"); if (manualChange || CVarGetInteger(swordsMasterBlade.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {swordsMasterBlade.defaultColor.x, swordsMasterBlade.defaultColor.y, swordsMasterBlade.defaultColor.z, swordsMasterBlade.defaultColor.w}; Color_RGBA8 color = CVarGetColor(swordsMasterBlade.cvar, defaultColor); @@ -682,7 +682,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterBlade5", swordsMasterBlade.changedCvar, 13, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterBlade6", swordsMasterBlade.changedCvar, 14, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - // static CosmeticOption& swordsMasterHilt = cosmeticOptions.at("Swords_MasterHilt"); + // static CosmeticOption& swordsMasterHilt = cosmeticOptions.at("Swords.MasterHilt"); // if (manualChange || CVarGetInteger(swordsMasterHilt.rainbowCvar, 0)) { // static Color_RGBA8 defaultColor = {swordsMasterHilt.defaultColor.x, swordsMasterHilt.defaultColor.y, swordsMasterHilt.defaultColor.z, swordsMasterHilt.defaultColor.w}; // Color_RGBA8 color = CVarGetColor(swordsMasterHilt.cvar, defaultColor); @@ -729,7 +729,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt39", swordsMasterHilt.changedCvar, 280, gsSPEndDisplayList()); // } // } - static CosmeticOption& swordsBiggoronBlade = cosmeticOptions.at("Swords_BiggoronBlade"); + static CosmeticOption& swordsBiggoronBlade = cosmeticOptions.at("Swords.BiggoronBlade"); if (manualChange || CVarGetInteger(swordsBiggoronBlade.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {swordsBiggoronBlade.defaultColor.x, swordsBiggoronBlade.defaultColor.y, swordsBiggoronBlade.defaultColor.z, swordsBiggoronBlade.defaultColor.w}; Color_RGBA8 color = CVarGetColor(swordsBiggoronBlade.cvar, defaultColor); @@ -738,7 +738,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronBlade3", swordsBiggoronBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronBlade4", swordsBiggoronBlade.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } - // static CosmeticOption& swordsBiggoronHilt = cosmeticOptions.at("Swords_BiggoronHilt"); + // static CosmeticOption& swordsBiggoronHilt = cosmeticOptions.at("Swords.BiggoronHilt"); // if (manualChange || CVarGetInteger(swordsBiggoronHilt.rainbowCvar, 0)) { // static Color_RGBA8 defaultColor = {swordsBiggoronHilt.defaultColor.x, swordsBiggoronHilt.defaultColor.y, swordsBiggoronHilt.defaultColor.z, swordsBiggoronHilt.defaultColor.w}; // Color_RGBA8 color = CVarGetColor(swordsBiggoronHilt.cvar, defaultColor); @@ -758,7 +758,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // } // } - static CosmeticOption& glovesGoronBracelet = cosmeticOptions.at("Gloves_GoronBracelet"); + static CosmeticOption& glovesGoronBracelet = cosmeticOptions.at("Gloves.GoronBracelet"); if (manualChange || CVarGetInteger(glovesGoronBracelet.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {glovesGoronBracelet.defaultColor.x, glovesGoronBracelet.defaultColor.y, glovesGoronBracelet.defaultColor.z, glovesGoronBracelet.defaultColor.w}; Color_RGBA8 color = CVarGetColor(glovesGoronBracelet.cvar, defaultColor); @@ -771,21 +771,21 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet5", glovesGoronBracelet.changedCvar, 39, gsSPGrayscale(false)); } } - static CosmeticOption& glovesSilverGauntlets = cosmeticOptions.at("Gloves_SilverGauntlets"); + static CosmeticOption& glovesSilverGauntlets = cosmeticOptions.at("Gloves.SilverGauntlets"); if (manualChange || CVarGetInteger(glovesSilverGauntlets.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {glovesSilverGauntlets.defaultColor.x, glovesSilverGauntlets.defaultColor.y, glovesSilverGauntlets.defaultColor.z, glovesSilverGauntlets.defaultColor.w}; Color_RGBA8 color = CVarGetColor(glovesSilverGauntlets.cvar, defaultColor); PATCH_GFX(gGiSilverGauntletsColorDL, "Gloves_SilverGauntlets1", glovesSilverGauntlets.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiSilverGauntletsColorDL, "Gloves_SilverGauntlets2", glovesSilverGauntlets.changedCvar, 4, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } - static CosmeticOption& glovesGoldenGauntlets = cosmeticOptions.at("Gloves_GoldenGauntlets"); + static CosmeticOption& glovesGoldenGauntlets = cosmeticOptions.at("Gloves.GoldenGauntlets"); if (manualChange || CVarGetInteger(glovesGoldenGauntlets.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {glovesGoldenGauntlets.defaultColor.x, glovesGoldenGauntlets.defaultColor.y, glovesGoldenGauntlets.defaultColor.z, glovesGoldenGauntlets.defaultColor.w}; Color_RGBA8 color = CVarGetColor(glovesGoldenGauntlets.cvar, defaultColor); PATCH_GFX(gGiGoldenGauntletsColorDL, "Gloves_GoldenGauntlets1", glovesGoldenGauntlets.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGoldenGauntletsColorDL, "Gloves_GoldenGauntlets2", glovesGoldenGauntlets.changedCvar, 4, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } - static CosmeticOption& glovesGauntletsGem = cosmeticOptions.at("Gloves_GauntletsGem"); + static CosmeticOption& glovesGauntletsGem = cosmeticOptions.at("Gloves.GauntletsGem"); if (manualChange || CVarGetInteger(glovesGauntletsGem.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {glovesGauntletsGem.defaultColor.x, glovesGauntletsGem.defaultColor.y, glovesGauntletsGem.defaultColor.z, glovesGauntletsGem.defaultColor.w}; Color_RGBA8 color = CVarGetColor(glovesGauntletsGem.cvar, defaultColor); @@ -797,7 +797,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightGauntletPlate3DL, "Gloves_GauntletsGem6", glovesGauntletsGem.changedCvar, 42, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBoomerangBody = cosmeticOptions.at("Equipment_BoomerangBody"); + static CosmeticOption& equipmentBoomerangBody = cosmeticOptions.at("Equipment.BoomerangBody"); if (manualChange || CVarGetInteger(equipmentBoomerangBody.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBoomerangBody.defaultColor.x, equipmentBoomerangBody.defaultColor.y, equipmentBoomerangBody.defaultColor.z, equipmentBoomerangBody.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBoomerangBody.cvar, defaultColor); @@ -807,7 +807,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkChildLeftFistAndBoomerangFarDL, "Equipment_BoomerangBody4", equipmentBoomerangBody.changedCvar, 9, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gBoomerangDL, "Equipment_BoomerangBody5", equipmentBoomerangBody.changedCvar, 39, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBoomerangGem = cosmeticOptions.at("Equipment_BoomerangGem"); + static CosmeticOption& equipmentBoomerangGem = cosmeticOptions.at("Equipment.BoomerangGem"); if (manualChange || CVarGetInteger(equipmentBoomerangGem.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBoomerangGem.defaultColor.x, equipmentBoomerangGem.defaultColor.y, equipmentBoomerangGem.defaultColor.z, equipmentBoomerangGem.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBoomerangGem.cvar, defaultColor); @@ -819,7 +819,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // PATCH_GFX(gLinkChildLeftFistAndBoomerangFarDL, "Equipment_BoomerangGem5", equipmentBoomerangGem.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - // static CosmeticOption& equipmentSlingshotBody = cosmeticOptions.at("Equipment_SlingshotBody"); + // static CosmeticOption& equipmentSlingshotBody = cosmeticOptions.at("Equipment.SlingshotBody"); // if (manualChange || CVarGetInteger(equipmentSlingshotBody.rainbowCvar, 0)) { // static Color_RGBA8 defaultColor = {equipmentSlingshotBody.defaultColor.x, equipmentSlingshotBody.defaultColor.y, equipmentSlingshotBody.defaultColor.z, equipmentSlingshotBody.defaultColor.w}; // Color_RGBA8 color = CVarGetColor(equipmentSlingshotBody.cvar, defaultColor); @@ -843,7 +843,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody16",equipmentSlingshotBody.changedCvar, 138, gsSPEndDisplayList()); // } // } - static CosmeticOption& equipmentSlingshotString = cosmeticOptions.at("Equipment_SlingshotString"); + static CosmeticOption& equipmentSlingshotString = cosmeticOptions.at("Equipment.SlingshotString"); if (manualChange || CVarGetInteger(equipmentSlingshotString.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentSlingshotString.defaultColor.x, equipmentSlingshotString.defaultColor.y, equipmentSlingshotString.defaultColor.z, equipmentSlingshotString.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentSlingshotString.cvar, defaultColor); @@ -852,7 +852,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkChildSlinghotStringDL, "Equipment_SlingshotString3",equipmentSlingshotString.changedCvar, 9, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBowTips = cosmeticOptions.at("Equipment_BowTips"); + static CosmeticOption& equipmentBowTips = cosmeticOptions.at("Equipment.BowTips"); if (manualChange || CVarGetInteger(equipmentBowTips.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBowTips.defaultColor.x, equipmentBowTips.defaultColor.y, equipmentBowTips.defaultColor.z, equipmentBowTips.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBowTips.cvar, defaultColor); @@ -862,7 +862,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingBowNearDL, "Equipment_BowTips4", equipmentBowTips.changedCvar, 26, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultRightHandHoldingBowFarDL, "Equipment_BowTips5", equipmentBowTips.changedCvar, 25, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBowString = cosmeticOptions.at("Equipment_BowString"); + static CosmeticOption& equipmentBowString = cosmeticOptions.at("Equipment.BowString"); if (manualChange || CVarGetInteger(equipmentBowString.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBowString.defaultColor.x, equipmentBowString.defaultColor.y, equipmentBowString.defaultColor.z, equipmentBowString.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBowString.cvar, defaultColor); @@ -870,7 +870,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiBowDL, "Equipment_BowString2", equipmentBowString.changedCvar, 106, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultBowStringDL, "Equipment_BowString3", equipmentBowString.changedCvar, 9, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBowBody = cosmeticOptions.at("Equipment_BowBody"); + static CosmeticOption& equipmentBowBody = cosmeticOptions.at("Equipment.BowBody"); if (manualChange || CVarGetInteger(equipmentBowBody.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBowBody.defaultColor.x, equipmentBowBody.defaultColor.y, equipmentBowBody.defaultColor.z, equipmentBowBody.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBowBody.cvar, defaultColor); @@ -880,7 +880,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingBowNearDL, "Equipment_BowBody4", equipmentBowBody.changedCvar, 33, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultRightHandHoldingBowFarDL, "Equipment_BowBody5", equipmentBowBody.changedCvar, 31, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBowHandle = cosmeticOptions.at("Equipment_BowHandle"); + static CosmeticOption& equipmentBowHandle = cosmeticOptions.at("Equipment.BowHandle"); if (manualChange || CVarGetInteger(equipmentBowHandle.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBowHandle.defaultColor.x, equipmentBowHandle.defaultColor.y, equipmentBowHandle.defaultColor.z, equipmentBowHandle.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBowHandle.cvar, defaultColor); @@ -891,7 +891,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightHandHoldingBowFarDL, "Equipment_BowHandle5", equipmentBowHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentHammerHead = cosmeticOptions.at("Equipment_HammerHead"); + static CosmeticOption& equipmentHammerHead = cosmeticOptions.at("Equipment.HammerHead"); if (manualChange || CVarGetInteger(equipmentHammerHead.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentHammerHead.defaultColor.x, equipmentHammerHead.defaultColor.y, equipmentHammerHead.defaultColor.z, equipmentHammerHead.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentHammerHead.cvar, defaultColor); @@ -902,7 +902,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultLeftHandHoldingHammerNearDL, "Equipment_HammerHead5", equipmentHammerHead.changedCvar, 38, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingHammerFarDL, "Equipment_HammerHead6", equipmentHammerHead.changedCvar, 38, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentHammerHandle = cosmeticOptions.at("Equipment_HammerHandle"); + static CosmeticOption& equipmentHammerHandle = cosmeticOptions.at("Equipment.HammerHandle"); if (manualChange || CVarGetInteger(equipmentHammerHandle.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentHammerHandle.defaultColor.x, equipmentHammerHandle.defaultColor.y, equipmentHammerHandle.defaultColor.z, equipmentHammerHandle.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentHammerHandle.cvar, defaultColor); @@ -912,7 +912,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultLeftHandHoldingHammerFarDL, "Equipment_HammerHandle6", equipmentHammerHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentChuFace = cosmeticOptions.at("Equipment_ChuFace"); + static CosmeticOption& equipmentChuFace = cosmeticOptions.at("Equipment.ChuFace"); if (manualChange || CVarGetInteger(equipmentChuFace.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentChuFace.defaultColor.x, equipmentChuFace.defaultColor.y, equipmentChuFace.defaultColor.z, equipmentChuFace.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentChuFace.cvar, defaultColor); @@ -925,7 +925,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gBombchuDL, "Equipment_ChuFace5", equipmentChuFace.changedCvar, 27, gsSPGrayscale(false)); } } - static CosmeticOption& equipmentChuBody = cosmeticOptions.at("Equipment_ChuBody"); + static CosmeticOption& equipmentChuBody = cosmeticOptions.at("Equipment.ChuBody"); if (manualChange || CVarGetInteger(equipmentChuBody.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentChuBody.defaultColor.x, equipmentChuBody.defaultColor.y, equipmentChuBody.defaultColor.z, equipmentChuBody.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentChuBody.cvar, defaultColor); @@ -936,7 +936,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gBombchuDL, "Equipment_ChuBody5", equipmentChuBody.changedCvar, 46, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& equipmentBunnyHood = cosmeticOptions.at("Equipment_BunnyHood"); + static CosmeticOption& equipmentBunnyHood = cosmeticOptions.at("Equipment.BunnyHood"); if (manualChange || CVarGetInteger(equipmentBunnyHood.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBunnyHood.defaultColor.x, equipmentBunnyHood.defaultColor.y, equipmentBunnyHood.defaultColor.z, equipmentBunnyHood.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBunnyHood.cvar, defaultColor); @@ -956,7 +956,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } } - static CosmeticOption& consumableGreenRupee = cosmeticOptions.at("Consumable_GreenRupee"); + static CosmeticOption& consumableGreenRupee = cosmeticOptions.at("Consumable.GreenRupee"); if (manualChange || CVarGetInteger(consumableGreenRupee.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableGreenRupee.defaultColor.x, consumableGreenRupee.defaultColor.y, consumableGreenRupee.defaultColor.z, consumableGreenRupee.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableGreenRupee.cvar, defaultColor); @@ -976,7 +976,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { ResourceMgr_UnpatchGfxByName(gRainbowBridgeDL, "RainbowBridge_EndGrayscaleAndEndDlist"); } } - static CosmeticOption& consumableBlueRupee = cosmeticOptions.at("Consumable_BlueRupee"); + static CosmeticOption& consumableBlueRupee = cosmeticOptions.at("Consumable.BlueRupee"); if (manualChange || CVarGetInteger(consumableBlueRupee.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableBlueRupee.defaultColor.x, consumableBlueRupee.defaultColor.y, consumableBlueRupee.defaultColor.z, consumableBlueRupee.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableBlueRupee.cvar, defaultColor); @@ -985,7 +985,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiBlueRupeeOuterColorDL, "Consumable_BlueRupee3", consumableBlueRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); PATCH_GFX(gGiBlueRupeeOuterColorDL, "Consumable_BlueRupee4", consumableBlueRupee.changedCvar, 4, gsDPSetEnvColor(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, 255)); } - static CosmeticOption& consumableRedRupee = cosmeticOptions.at("Consumable_RedRupee"); + static CosmeticOption& consumableRedRupee = cosmeticOptions.at("Consumable.RedRupee"); if (manualChange || CVarGetInteger(consumableRedRupee.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableRedRupee.defaultColor.x, consumableRedRupee.defaultColor.y, consumableRedRupee.defaultColor.z, consumableRedRupee.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableRedRupee.cvar, defaultColor); @@ -994,7 +994,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiRedRupeeOuterColorDL, "Consumable_RedRupee3", consumableRedRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); PATCH_GFX(gGiRedRupeeOuterColorDL, "Consumable_RedRupee4", consumableRedRupee.changedCvar, 4, gsDPSetEnvColor(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, 255)); } - static CosmeticOption& consumablePurpleRupee = cosmeticOptions.at("Consumable_PurpleRupee"); + static CosmeticOption& consumablePurpleRupee = cosmeticOptions.at("Consumable.PurpleRupee"); if (manualChange || CVarGetInteger(consumablePurpleRupee.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumablePurpleRupee.defaultColor.x, consumablePurpleRupee.defaultColor.y, consumablePurpleRupee.defaultColor.z, consumablePurpleRupee.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumablePurpleRupee.cvar, defaultColor); @@ -1003,7 +1003,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiPurpleRupeeOuterColorDL, "Consumable_PurpleRupee3", consumablePurpleRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); PATCH_GFX(gGiPurpleRupeeOuterColorDL, "Consumable_PurpleRupee4", consumablePurpleRupee.changedCvar, 4, gsDPSetEnvColor(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, 255)); } - static CosmeticOption& consumableGoldRupee = cosmeticOptions.at("Consumable_GoldRupee"); + static CosmeticOption& consumableGoldRupee = cosmeticOptions.at("Consumable.GoldRupee"); if (manualChange || CVarGetInteger(consumableGoldRupee.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableGoldRupee.defaultColor.x, consumableGoldRupee.defaultColor.y, consumableGoldRupee.defaultColor.z, consumableGoldRupee.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableGoldRupee.cvar, defaultColor); @@ -1013,7 +1013,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiGoldRupeeOuterColorDL, "Consumable_GoldRupee4", consumableGoldRupee.changedCvar, 4, gsDPSetEnvColor(color.r * 0.75f, color.g * 0.75f, color.b * 0.75f, 255)); } - static CosmeticOption& consumableHearts = cosmeticOptions.at("Consumable_Hearts"); + static CosmeticOption& consumableHearts = cosmeticOptions.at("Consumable.Hearts"); if (manualChange || CVarGetInteger(consumableHearts.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableHearts.defaultColor.x, consumableHearts.defaultColor.y, consumableHearts.defaultColor.z, consumableHearts.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableHearts.cvar, defaultColor); @@ -1028,7 +1028,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiRedPotColorDL, "Consumable_Hearts9", consumableHearts.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiRedPotColorDL, "Consumable_Hearts10", consumableHearts.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - static CosmeticOption& consumableMagic = cosmeticOptions.at("Consumable_Magic"); + static CosmeticOption& consumableMagic = cosmeticOptions.at("Consumable.Magic"); if (manualChange || CVarGetInteger(consumableMagic.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableMagic.defaultColor.x, consumableMagic.defaultColor.y, consumableMagic.defaultColor.z, consumableMagic.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableMagic.cvar, defaultColor); @@ -1040,7 +1040,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiGreenPotColorDL, "Consumable_Magic6", consumableMagic.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - static CosmeticOption& npcGoldenSkulltula = cosmeticOptions.at("NPC_GoldenSkulltula"); + static CosmeticOption& npcGoldenSkulltula = cosmeticOptions.at("NPC.GoldenSkulltula"); if (manualChange || CVarGetInteger(npcGoldenSkulltula.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {npcGoldenSkulltula.defaultColor.x, npcGoldenSkulltula.defaultColor.y, npcGoldenSkulltula.defaultColor.z, npcGoldenSkulltula.defaultColor.w}; Color_RGBA8 color = CVarGetColor(npcGoldenSkulltula.cvar, defaultColor); @@ -1056,7 +1056,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(object_st_DL_003FB0, "NPC_GoldenSkulltula10", npcGoldenSkulltula.changedCvar, 119, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255)); } - static CosmeticOption& npcGerudo = cosmeticOptions.at("NPC_Gerudo"); + static CosmeticOption& npcGerudo = cosmeticOptions.at("NPC.Gerudo"); if (manualChange || CVarGetInteger(npcGerudo.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {npcGerudo.defaultColor.x, npcGerudo.defaultColor.y, npcGerudo.defaultColor.z, npcGerudo.defaultColor.w}; Color_RGBA8 color = CVarGetColor(npcGerudo.cvar, defaultColor); @@ -1070,35 +1070,35 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGerudoPurpleRightHandDL, "NPC_Gerudo8", npcGerudo.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& npcMetalTrap = cosmeticOptions.at("NPC_MetalTrap"); + static CosmeticOption& npcMetalTrap = cosmeticOptions.at("NPC.MetalTrap"); if (manualChange || CVarGetInteger(npcMetalTrap.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {npcMetalTrap.defaultColor.x, npcMetalTrap.defaultColor.y, npcMetalTrap.defaultColor.z, npcMetalTrap.defaultColor.w}; Color_RGBA8 color = CVarGetColor(npcMetalTrap.cvar, defaultColor); PATCH_GFX(gSlidingBladeTrapDL, "NPC_MetalTrap1", npcMetalTrap.changedCvar, 59, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - static CosmeticOption& n64LogoRed = cosmeticOptions.at("Title_N64LogoRed"); + static CosmeticOption& n64LogoRed = cosmeticOptions.at("Title.N64LogoRed"); if (manualChange || CVarGetInteger(n64LogoRed.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {n64LogoRed.defaultColor.x, n64LogoRed.defaultColor.y, n64LogoRed.defaultColor.z, n64LogoRed.defaultColor.w}; Color_RGBA8 color = CVarGetColor(n64LogoRed.cvar, defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoRed1", n64LogoRed.changedCvar, 17, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoRed2", n64LogoRed.changedCvar, 18, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } - static CosmeticOption& n64LogoBlue = cosmeticOptions.at("Title_N64LogoBlue"); + static CosmeticOption& n64LogoBlue = cosmeticOptions.at("Title.N64LogoBlue"); if (manualChange || CVarGetInteger(n64LogoBlue.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {n64LogoBlue.defaultColor.x, n64LogoBlue.defaultColor.y, n64LogoBlue.defaultColor.z, n64LogoBlue.defaultColor.w}; Color_RGBA8 color = CVarGetColor(n64LogoBlue.cvar, defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoBlue1", n64LogoBlue.changedCvar, 29, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoBlue2", n64LogoBlue.changedCvar, 30, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } - static CosmeticOption& n64LogoGreen = cosmeticOptions.at("Title_N64LogoGreen"); + static CosmeticOption& n64LogoGreen = cosmeticOptions.at("Title.N64LogoGreen"); if (manualChange || CVarGetInteger(n64LogoGreen.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {n64LogoGreen.defaultColor.x, n64LogoGreen.defaultColor.y, n64LogoGreen.defaultColor.z, n64LogoGreen.defaultColor.w}; Color_RGBA8 color = CVarGetColor(n64LogoGreen.cvar, defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoGreen1", n64LogoGreen.changedCvar, 56, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoGreen2", n64LogoGreen.changedCvar, 57, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } - static CosmeticOption& n64LogoYellow = cosmeticOptions.at("Title_N64LogoYellow"); + static CosmeticOption& n64LogoYellow = cosmeticOptions.at("Title.N64LogoYellow"); if (manualChange || CVarGetInteger(n64LogoYellow.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {n64LogoYellow.defaultColor.x, n64LogoYellow.defaultColor.y, n64LogoYellow.defaultColor.z, n64LogoYellow.defaultColor.w}; Color_RGBA8 color = CVarGetColor(n64LogoYellow.cvar, defaultColor); @@ -1107,9 +1107,9 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } if (gPlayState != nullptr) { - if (CVarGetInteger("gCosmetics.Link_BodyScale.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("Link.BodyScale.Changed"), 0)) { static Player* player = GET_PLAYER(gPlayState); - float scale = CVarGetFloat("gCosmetics.Link_BodyScale.Value", 0.01f); + float scale = CVarGetFloat(CVAR_COSMETIC("Link.BodyScale.Value"), 0.01f); player->actor.scale.x = scale; player->actor.scale.y = scale; player->actor.scale.z = scale; @@ -1128,13 +1128,13 @@ void Table_InitHeader(bool has_header = true) { ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); } void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ - std::string CvarLabel = CvarName + "UseMargins"; + std::string CvarLabel = CvarName + ".UseMargins"; std::string Label = ElementName + " use margins"; UIWidgets::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); UIWidgets::Tooltip("Using this allow you move the element with General margins sliders"); } void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){ - std::string CvarLabel = CvarName + "PosType"; + std::string CvarLabel = CvarName + ".PosType"; UIWidgets::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); UIWidgets::Tooltip("This will use original intended elements position"); UIWidgets::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); @@ -1149,8 +1149,8 @@ void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = UIWidgets::Tooltip("This will make your elements hidden"); } void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ - std::string PosXCvar = CvarName+"PosX"; - std::string PosYCvar = CvarName+"PosY"; + std::string PosXCvar = CvarName + ".PosX"; + std::string PosYCvar = CvarName + ".PosY"; std::string InvisibleLabelX = "##"+PosXCvar; std::string InvisibleLabelY = "##"+PosYCvar; UIWidgets::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0); @@ -1160,7 +1160,7 @@ void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX } void DrawScaleSlider(const std::string CvarName,float DefaultValue){ std::string InvisibleLabel = "##"+CvarName; - std::string CvarLabel = CvarName+"Scale"; + std::string CvarLabel = CvarName + ".Scale"; //Disabled for now. feature not done and several fixes needed to be merged. //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true); } @@ -1224,11 +1224,11 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableHeartsCounts", 1, FlagsTable)) { ImGui::TableSetupColumn("Hearts counts settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Hearts counts", "gHearts"); - DrawPositionsRadioBoxes("gHeartsCount"); - DrawPositionSlider("gHeartsCount",-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x); - DrawScaleSlider("gHeartsCount",0.7f); - UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", "gHeartsLineLength", 0, 20, "", 10); + DrawUseMarginsSlider("Hearts counts", CVAR_COSMETIC("Hearts")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("HeartsCount")); + DrawPositionSlider(CVAR_COSMETIC("HeartsCount"),-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x); + DrawScaleSlider(CVAR_COSMETIC("HeartsCount"),0.7f); + UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", CVAR_COSMETIC("Hearts.LineLength"), 0, 20, "", 10); UIWidgets::Tooltip("This will set the length of a row of hearts. Set to 0 for unlimited length."); ImGui::NewLine(); ImGui::EndTable(); @@ -1238,12 +1238,12 @@ void Draw_Placements(){ if (ImGui::BeginTable("tablemmpos", 1, FlagsTable)) { ImGui::TableSetupColumn("Magic meter settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Magic meter", "gMagicBar"); - DrawPositionsRadioBoxes("gMagicBar"); - UIWidgets::EnhancementRadioButton("Anchor to life bar", "gMagicBarPosType", 5); + DrawUseMarginsSlider("Magic meter", CVAR_COSMETIC("MagicBar")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("MagicBar")); + UIWidgets::EnhancementRadioButton("Anchor to life bar", CVAR_COSMETIC("MagicBar.PosType"), 5); UIWidgets::Tooltip("This will make your elements follow the bottom of the life meter"); - DrawPositionSlider("gMagicBar", 0, ImGui::GetWindowViewport()->Size.y/2, -5, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider("gMagicBar",1.0f); + DrawPositionSlider(CVAR_COSMETIC("MagicBar"), 0, ImGui::GetWindowViewport()->Size.y/2, -5, ImGui::GetWindowViewport()->Size.x/2); + DrawScaleSlider(CVAR_COSMETIC("MagicBar"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } @@ -1252,34 +1252,34 @@ void Draw_Placements(){ if (ImGui::BeginTable("tabledvisualstoneofagony", 1, FlagsTable)) { ImGui::TableSetupColumn("Visual stone of agony settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Visual stone of agony", "gVSOA"); - DrawPositionsRadioBoxes("gVSOA"); + DrawUseMarginsSlider("Visual stone of agony", CVAR_COSMETIC("VisualSoA")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("VisualSoA")); s16 Min_X_VSOA = 0; s16 Max_X_VSOA = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gVSOAPosType",0) == 2){ + if(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"),0) == 2){ Max_X_VSOA = 290; - } else if(CVarGetInteger("gVSOAPosType",0) == 4){ + } else if(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"),0) == 4){ Min_X_VSOA = (ImGui::GetWindowViewport()->Size.x/2)*-1; } - DrawPositionSlider("gVSOA", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_VSOA, Max_X_VSOA); - DrawScaleSlider("gVSOA",1.0f); + DrawPositionSlider(CVAR_COSMETIC("VisualSoA"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_VSOA, Max_X_VSOA); + DrawScaleSlider(CVAR_COSMETIC("VisualSoA"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", "gBBtn", 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", "gABtn", -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", "gStartBtn", 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); - C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", "gCBtnU", "gCBtnUPosType", 0.5f); - C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", "gCBtnD", "gCBtnDPosType", 0.87f); - C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", "gCBtnL", "gCBtnLPosType", 0.87f); - C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", "gCBtnR", "gCBtnRPosType", 0.87f); + Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", CVAR_COSMETIC("BButton"), 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", CVAR_COSMETIC("AButton"), -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", CVAR_COSMETIC("StartButton"), 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); + C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", CVAR_COSMETIC("CUpButton"), CVAR_COSMETIC("CUpButton.PosType"), 0.5f); + C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", CVAR_COSMETIC("CDownButton"), CVAR_COSMETIC("CDownButton.PosType"), 0.87f); + C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", CVAR_COSMETIC("CLeftButton"), CVAR_COSMETIC("CLeftButton.PosType"), 0.87f); + C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", CVAR_COSMETIC("CRightButton"), CVAR_COSMETIC("CRightButton.PosType"), 0.87f); if (CVarGetInteger("gDpadEquips",0) && ImGui::CollapsingHeader("DPad items position")) { if (ImGui::BeginTable("tabledpaditems", 1, FlagsTable)) { ImGui::TableSetupColumn("DPad items settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("DPad items", "gDPad"); - DrawPositionsRadioBoxes("gDPad"); + DrawUseMarginsSlider("DPad items", CVAR_COSMETIC("Dpad")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("Dpad")); s16 Min_X_Dpad = 0; s16 Max_X_Dpad = ImGui::GetWindowViewport()->Size.x/2; if(CVarGetInteger("gDPadPosType",0) == 2){ @@ -1287,41 +1287,41 @@ void Draw_Placements(){ } else if(CVarGetInteger("gDPadPosType",0) == 4){ Min_X_Dpad = (ImGui::GetWindowViewport()->Size.x/2)*-1; } - DrawPositionSlider("gDPad", 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_Dpad, Max_X_Dpad); - DrawScaleSlider("gDPad",1.0f); + DrawPositionSlider(CVAR_COSMETIC("Dpad"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_Dpad, Max_X_Dpad); + DrawScaleSlider(CVAR_COSMETIC("Dpad"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", "gMinimap", (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", "gSKC", 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", "gRC", -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", "gCarrots", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); - Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", "gTimers", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", "gAS", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", "gTCM", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", "gTCB", 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", "gIGT", 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); + Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", CVAR_COSMETIC("Minimap"), (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", CVAR_COSMETIC("SmallKey"), 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", CVAR_COSMETIC("Rupees"), -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", CVAR_COSMETIC("Carrots"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); + Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", CVAR_COSMETIC("Timers"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", CVAR_COSMETIC("ArcheryScore"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", CVAR_COSMETIC("TitleCard.Map"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", CVAR_COSMETIC("TitleCard.Boss"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", CVAR_COSMETIC("IGT"), 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); if (ImGui::CollapsingHeader("Enemy Health Bar position")) { if (ImGui::BeginTable("enemyhealthbar", 1, FlagsTable)) { ImGui::TableSetupColumn("Enemy Health Bar settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - std::string posTypeCVar = "gCosmetics.Hud_EnemyHealthBarPosType"; + std::string posTypeCVar = CVAR_COSMETIC("HUD.EnemyHealthBarPosType"); UIWidgets::EnhancementRadioButton("Anchor to Enemy", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_ACTOR); UIWidgets::Tooltip("This will use enemy on screen position"); UIWidgets::EnhancementRadioButton("Anchor to the top", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_TOP); UIWidgets::Tooltip("This will make your elements follow the top edge of your game window"); UIWidgets::EnhancementRadioButton("Anchor to the bottom", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_BOTTOM); UIWidgets::Tooltip("This will make your elements follow the bottom edge of your game window"); - DrawPositionSlider("gCosmetics.Hud_EnemyHealthBar", -SCREEN_HEIGHT, SCREEN_HEIGHT, -ImGui::GetWindowViewport()->Size.x / 2, ImGui::GetWindowViewport()->Size.x / 2); - if (UIWidgets::EnhancementSliderInt("Health Bar Width: %d", "##EnemyHealthBarWidth", "gCosmetics.Hud_EnemyHealthBarWidth.Value", 32, 128, "", 64)) { - CVarSetInteger("gCosmetics.Hud_EnemyHealthBarWidth.Changed", 1); + DrawPositionSlider(CVAR_COSMETIC("HUD.EnemyHealthBar"), -SCREEN_HEIGHT, SCREEN_HEIGHT, -ImGui::GetWindowViewport()->Size.x / 2, ImGui::GetWindowViewport()->Size.x / 2); + if (UIWidgets::EnhancementSliderInt("Health Bar Width: %d", "##EnemyHealthBarWidth", CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value"), 32, 128, "", 64)) { + CVarSetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed"), 1); } UIWidgets::Tooltip("This will change the width of the health bar"); ImGui::SameLine(); if (ImGui::Button("Reset##EnemyHealthBarWidth")) { - CVarClear("gCosmetics.Hud_EnemyHealthBarWidth.Value"); - CVarClear("gCosmetics.Hud_EnemyHealthBarWidth.Changed"); + CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value")); + CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); @@ -1351,13 +1351,13 @@ void DrawSillyTab() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } - if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %.3fx", "##Link_BodyScale", "gCosmetics.Link_BodyScale.Value", 0.001f, 0.025f, "", 0.01f, true)) { - CVarSetInteger("gCosmetics.Link_BodyScale.Changed", 1); + if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %.3fx", "##Link_BodyScale", CVAR_COSMETIC("Link.BodyScale.Value"), 0.001f, 0.025f, "", 0.01f, true)) { + CVarSetInteger(CVAR_COSMETIC("Link.BodyScale.Changed"), 1); } ImGui::SameLine(); if (ImGui::Button("Reset##Link_BodyScale")) { - CVarClear("gCosmetics.Link_BodyScale.Value"); - CVarClear("gCosmetics.Link_BodyScale.Changed"); + CVarClear(CVAR_COSMETIC("Link.BodyScale.Value")); + CVarClear(CVAR_COSMETIC("Link.BodyScale.Changed")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); if (gPlayState != nullptr) { static Player* player = GET_PLAYER(gPlayState); @@ -1366,31 +1366,31 @@ void DrawSillyTab() { player->actor.scale.z = 0.01f; } } - if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", "gCosmetics.Link_HeadScale.Value", 0.4f, 4.0f, "", 1.0f, false)) { - CVarSetInteger("gCosmetics.Link_HeadScale.Changed", 1); + if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", CVAR_COSMETIC("Link.HeadScale.Value"), 0.4f, 4.0f, "", 1.0f, false)) { + CVarSetInteger(CVAR_COSMETIC("Link.HeadScale.Changed"), 1); } - Reset_Option_Double("Reset##Link_HeadScale", "gCosmetics.Link_HeadScale"); - if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", "gCosmetics.Link_SwordScale.Value", 1.0f, 2.5f, "", 1.0f, false)) { - CVarSetInteger("gCosmetics.Link_SwordScale.Changed", 1); + Reset_Option_Double("Reset##Link_HeadScale", CVAR_COSMETIC("Link.HeadScale")); + if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", CVAR_COSMETIC("Link.SwordScale.Value"), 1.0f, 2.5f, "", 1.0f, false)) { + CVarSetInteger(CVAR_COSMETIC("Link.SwordScale.Changed"), 1); } - Reset_Option_Double("Reset##Link_SwordScale", "gCosmetics.Link_SwordScale"); - UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength", -300.0f, 1000.0f, "", 0.0f, false); - Reset_Option_Single("Reset##BunnyHood_EarLength", "gCosmetics.BunnyHood_EarLength"); - UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread", -300.0f, 500.0f, "", 0.0f, false); - Reset_Option_Single("Reset##BunnyHood_EarSpread", "gCosmetics.BunnyHood_EarSpread"); - UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", "gCosmetics.Goron_NeckLength", 0.0f, 1000.0f, "", 0.0f, false); - Reset_Option_Single("Reset##Goron_NeckLength", "gCosmetics.Goron_NeckLength"); + Reset_Option_Double("Reset##Link_SwordScale", CVAR_COSMETIC("Link.SwordScale")); + UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", CVAR_COSMETIC("BunnyHood.EarLength"), -300.0f, 1000.0f, "", 0.0f, false); + Reset_Option_Single("Reset##BunnyHood_EarLength", CVAR_COSMETIC("BunnyHood.EarLength")); + UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", CVAR_COSMETIC("BunnyHood.EarSpread"), -300.0f, 500.0f, "", 0.0f, false); + Reset_Option_Single("Reset##BunnyHood_EarSpread", CVAR_COSMETIC("BunnyHood.EarSpread")); + UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength"), 0.0f, 1000.0f, "", 0.0f, false); + Reset_Option_Single("Reset##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength")); UIWidgets::EnhancementCheckbox("Unfix Goron Spin", "gUnfixGoronSpin"); - UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", "gCosmetics.Fairies_Size", 0.25f, 5.0f, "", 1.0f, false); - Reset_Option_Single("Reset##Fairies_Size", "gCosmetics.Fairies_Size"); - UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed", 0.25f, 5.0f, "", 1.0f, false); - Reset_Option_Single("Reset##N64Logo_SpinSpeed", "gCosmetics.N64Logo_SpinSpeed"); - UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", "gCosmetics.Moon_Size", 0.5f, 2.0f, "", 1.0f, false); - Reset_Option_Single("Reset##Moon_Size", "gCosmetics.Moon_Size"); - if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed.Value", 100.0f, 6000.0f, "", 100.0f, false)) { - CVarSetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 1); + UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", CVAR_COSMETIC("Fairies.Size"), 0.25f, 5.0f, "", 1.0f, false); + Reset_Option_Single("Reset##Fairies_Size", CVAR_COSMETIC("Fairies.Size")); + UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", CVAR_COSMETIC("N64Logo.SpinSpeed"), 0.25f, 5.0f, "", 1.0f, false); + Reset_Option_Single("Reset##N64Logo_SpinSpeed", CVAR_COSMETIC("N64Logo.SpinSpeed")); + UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", CVAR_COSMETIC("Moon.Size"), 0.5f, 2.0f, "", 1.0f, false); + Reset_Option_Single("Reset##Moon_Size", CVAR_COSMETIC("Moon.Size")); + if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", CVAR_COSMETIC("Kak.Windmill_Speed.Value"), 100.0f, 6000.0f, "", 100.0f, false)) { + CVarSetInteger(CVAR_COSMETIC("Kak.Windmill_Speed.Changed"), 1); } - Reset_Option_Double("Reset##Kak_Windmill_Speed", "gCosmetics.Kak_Windmill_Speed"); + Reset_Option_Double("Reset##Kak_Windmill_Speed", CVAR_COSMETIC("Kak.Windmill_Speed")); ImGui::EndDisabled(); } @@ -1424,89 +1424,89 @@ void ToggleRainbow(CosmeticOption& cosmeticOption, bool state) { } void ApplySideEffects(CosmeticOption& cosmeticOption) { - if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) { return; } // This bit is kind of experimental, not sure how I feel about it yet, but it allows for // advanced cosmetic options to be changed based on a non-advanced option. if (cosmeticOption.label == "Bow Body") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Equipment_BowTips"), 0.5f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Equipment_BowHandle"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Equipment.BowTips"), 0.5f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Equipment.BowHandle"), 1.0f); CopyMultipliedColor(cosmeticOption, cosmeticOption, 4.0f); } else if (cosmeticOption.label == "Idle Primary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_IdleSecondary"), 0.5f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi.IdleSecondary"), 0.5f); } else if (cosmeticOption.label == "Enemy Primary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_EnemySecondary"), 0.5f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi.EnemySecondary"), 0.5f); } else if (cosmeticOption.label == "NPC Primary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_NPCSecondary"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi.NPCSecondary"), 1.0f); } else if (cosmeticOption.label == "Props Primary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi_PropsSecondary"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Navi.PropsSecondary"), 1.0f); } else if (cosmeticOption.label == "Ivan Idle Primary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Ivan_IdleSecondary"), 0.5f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Ivan.IdleSecondary"), 0.5f); } else if (cosmeticOption.label == "Level 1 Secondary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level1Primary"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack.Level1Primary"), 2.0f); } else if (cosmeticOption.label == "Level 2 Secondary") { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack_Level2Primary"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack.Level2Primary"), 2.0f); } else if (cosmeticOption.label == "Item Select Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_ItemSelB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_ItemSelC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_ItemSelD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_ItemSelD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelD"), 1.0f); } } else if (cosmeticOption.label == "Equip Select Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_EquipSelB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_EquipSelC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_EquipSelD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_EquipSelD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelD"), 1.0f); } } else if (cosmeticOption.label == "Map Dungeon Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_MapSelDunD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelDunD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunD"), 1.0f); } } else if (cosmeticOption.label == "Quest Status Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_QuestStatusD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_QuestStatusD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusD"), 1.0f); } } else if (cosmeticOption.label == "Map Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_MapSelectB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_MapSelectC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_MapSelectD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_MapSelectD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectD"), 1.0f); } } else if (cosmeticOption.label == "Save Color") { if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - ToggleRainbow(cosmeticOptions.at("Kal_SaveB"), true); - ToggleRainbow(cosmeticOptions.at("Kal_SaveC"), true); - ToggleRainbow(cosmeticOptions.at("Kal_SaveD"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.SaveB"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.SaveC"), true); + ToggleRainbow(cosmeticOptions.at("Kaleido.SaveD"), true); } else { - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveB"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveC"), 2.0f); - CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kal_SaveD"), 1.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveB"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveC"), 2.0f); + CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveD"), 1.0f); } } } @@ -1552,44 +1552,44 @@ void ResetColor(CosmeticOption& cosmeticOption) { // This portion should match 1:1 the multiplied colors in `ApplySideEffect()` if (cosmeticOption.label == "Bow Body") { - ResetColor(cosmeticOptions.at("Equipment_BowTips")); - ResetColor(cosmeticOptions.at("Equipment_BowHandle")); + ResetColor(cosmeticOptions.at("Equipment.BowTips")); + ResetColor(cosmeticOptions.at("Equipment.BowHandle")); } else if (cosmeticOption.label == "Idle Primary") { - ResetColor(cosmeticOptions.at("Navi_IdleSecondary")); + ResetColor(cosmeticOptions.at("Navi.IdleSecondary")); } else if (cosmeticOption.label == "Enemy Primary") { - ResetColor(cosmeticOptions.at("Navi_EnemySecondary")); + ResetColor(cosmeticOptions.at("Navi.EnemySecondary")); } else if (cosmeticOption.label == "NPC Primary") { - ResetColor(cosmeticOptions.at("Navi_NPCSecondary")); + ResetColor(cosmeticOptions.at("Navi.NPCSecondary")); } else if (cosmeticOption.label == "Props Primary") { - ResetColor(cosmeticOptions.at("Navi_PropsSecondary")); + ResetColor(cosmeticOptions.at("Navi.PropsSecondary")); } else if (cosmeticOption.label == "Level 1 Secondary") { - ResetColor(cosmeticOptions.at("SpinAttack_Level1Primary")); + ResetColor(cosmeticOptions.at("SpinAttack.Level1Primary")); } else if (cosmeticOption.label == "Level 2 Secondary") { - ResetColor(cosmeticOptions.at("SpinAttack_Level2Primary")); + ResetColor(cosmeticOptions.at("SpinAttack.Level2Primary")); } else if (cosmeticOption.label == "Item Select Color") { - ResetColor(cosmeticOptions.at("Kal_ItemSelB")); - ResetColor(cosmeticOptions.at("Kal_ItemSelC")); - ResetColor(cosmeticOptions.at("Kal_ItemSelD")); + ResetColor(cosmeticOptions.at("Kaleido.ItemSelB")); + ResetColor(cosmeticOptions.at("Kaleido.ItemSelC")); + ResetColor(cosmeticOptions.at("Kaleido.ItemSelD")); } else if (cosmeticOption.label == "Equip Select Color") { - ResetColor(cosmeticOptions.at("Kal_EquipSelB")); - ResetColor(cosmeticOptions.at("Kal_EquipSelC")); - ResetColor(cosmeticOptions.at("Kal_EquipSelD")); + ResetColor(cosmeticOptions.at("Kaleido.EquipSelB")); + ResetColor(cosmeticOptions.at("Kaleido.EquipSelC")); + ResetColor(cosmeticOptions.at("Kaleido.EquipSelD")); } else if (cosmeticOption.label == "Map Dungeon Color") { - ResetColor(cosmeticOptions.at("Kal_MapSelDunB")); - ResetColor(cosmeticOptions.at("Kal_MapSelDunC")); - ResetColor(cosmeticOptions.at("Kal_MapSelDunD")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelDunB")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelDunC")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelDunD")); } else if (cosmeticOption.label == "Quest Status Color") { - ResetColor(cosmeticOptions.at("Kal_QuestStatusB")); - ResetColor(cosmeticOptions.at("Kal_QuestStatusC")); - ResetColor(cosmeticOptions.at("Kal_QuestStatusD")); + ResetColor(cosmeticOptions.at("Kaleido.QuestStatusB")); + ResetColor(cosmeticOptions.at("Kaleido.QuestStatusC")); + ResetColor(cosmeticOptions.at("Kaleido.QuestStatusD")); } else if (cosmeticOption.label == "Map Color") { - ResetColor(cosmeticOptions.at("Kal_MapSelectB")); - ResetColor(cosmeticOptions.at("Kal_MapSelectC")); - ResetColor(cosmeticOptions.at("Kal_MapSelectD")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelectB")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelectC")); + ResetColor(cosmeticOptions.at("Kaleido.MapSelectD")); } else if (cosmeticOption.label == "Save Color") { - ResetColor(cosmeticOptions.at("Kal_SaveB")); - ResetColor(cosmeticOptions.at("Kal_SaveC")); - ResetColor(cosmeticOptions.at("Kal_SaveD")); + ResetColor(cosmeticOptions.at("Kaleido.SaveB")); + ResetColor(cosmeticOptions.at("Kaleido.SaveC")); + ResetColor(cosmeticOptions.at("Kaleido.SaveD")); } } @@ -1655,7 +1655,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) { ImGui::SameLine((ImGui::CalcTextSize("Mirror Shield Mirror").x * 1.0f) + 60.0f); if (ImGui::Button(("Random##" + label).c_str())) { for (auto& [id, cosmeticOption] : cosmeticOptions) { - if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) && !CVarGetInteger(cosmeticOption.lockedCvar, 0)) { + if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) && !CVarGetInteger(cosmeticOption.lockedCvar, 0)) { RandomizeColor(cosmeticOption); } } @@ -1673,7 +1673,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } for (auto& [id, cosmeticOption] : cosmeticOptions) { - if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0))) { + if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0))) { DrawCosmeticRow(cosmeticOption); } } @@ -1693,13 +1693,13 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::Text("Color Scheme"); ImGui::SameLine(); - UIWidgets::EnhancementCombobox("gCosmetics.DefaultColorScheme", colorSchemes, COLORSCHEME_N64); - UIWidgets::EnhancementCheckbox("Advanced Mode", "gCosmetics.AdvancedMode"); + UIWidgets::EnhancementCombobox(CVAR_COSMETIC("DefaultColorScheme"), colorSchemes, COLORSCHEME_N64); + UIWidgets::EnhancementCheckbox("Advanced Mode", CVAR_COSMETIC("AdvancedMode")); UIWidgets::InsertHelpHoverText( "Some cosmetic options may not apply if you have any mods that provide custom models for the cosmetic option.\n\n" "For example, if you have custom Link model, then the Link's Hair color option will most likely not apply." ); - if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) { if (ImGui::Button("Lock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (cosmeticOption.advancedOption) { @@ -1718,9 +1718,9 @@ void CosmeticsEditorWindow::DrawElement() { LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } - UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync"); - UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false, true); - UIWidgets::EnhancementCheckbox("Randomize All on New Scene", "gCosmetics.RandomizeAllOnNewScene"); + UIWidgets::EnhancementCheckbox("Sync Rainbow colors", CVAR_COSMETIC("RainbowSync")); + UIWidgets::EnhancementSliderFloat("Rainbow Speed: %.3f", "##rainbowSpeed", CVAR_COSMETIC("RainbowSpeed"), 0.03f, 1.0f, "", 0.6f, false, true); + UIWidgets::EnhancementCheckbox("Randomize All on New Scene", CVAR_COSMETIC("RandomizeAllOnNewScene")); UIWidgets::Tooltip("Enables randomizing all unlocked cosmetics when you enter a new scene."); if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { @@ -1739,7 +1739,7 @@ void CosmeticsEditorWindow::DrawElement() { if (ImGui::Button("Lock All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { for (auto& [id, cosmeticOption] : cosmeticOptions) { - if (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + if (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) { CVarSetInteger(cosmeticOption.lockedCvar, 1); } } @@ -1748,7 +1748,7 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::SameLine(); if (ImGui::Button("Unlock All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { for (auto& [id, cosmeticOption] : cosmeticOptions) { - if (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + if (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) { CVarSetInteger(cosmeticOption.lockedCvar, 0); } } @@ -1770,13 +1770,13 @@ void CosmeticsEditorWindow::DrawElement() { DrawCosmeticGroup(COSMETICS_GROUP_ARROWS); DrawCosmeticGroup(COSMETICS_GROUP_SPIN_ATTACK); DrawCosmeticGroup(COSMETICS_GROUP_TRAILS); - if (UIWidgets::EnhancementSliderInt("Trails Duration: %d", "##Trails_Duration", "gCosmetics.Trails_Duration.Value", 2, 20, "", 4)) { - CVarSetInteger("gCosmetics.Trails_Duration.Changed", 1); + if (UIWidgets::EnhancementSliderInt("Trails Duration: %d", "##Trails_Duration", CVAR_COSMETIC("Trails.Duration.Value"), 2, 20, "", 4)) { + CVarSetInteger(CVAR_COSMETIC("Trails.Duration.Changed"), 1); } ImGui::SameLine(); if (ImGui::Button("Reset##Trails_Duration")) { - CVarClear("gCosmetics.Trails_Duration.Value"); - CVarClear("gCosmetics.Trails_Duration.Changed"); + CVarClear(CVAR_COSMETIC("Trails.Duration.Value")); + CVarClear(CVAR_COSMETIC("Trails.Duration.Changed")); LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::EndTabItem(); @@ -1826,7 +1826,7 @@ void RegisterOnGameFrameUpdateHook() { void Cosmetics_RegisterOnSceneInitHook() { GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { - if (CVarGetInteger("gCosmetics.RandomizeAllOnNewScene", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("RandomizeAllOnNewScene"), 0)) { CosmeticsEditor_RandomizeAll(); } }); @@ -1855,7 +1855,7 @@ void CosmeticsEditorWindow::InitElement() { void CosmeticsEditor_RandomizeAll() { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && - (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0))) { + (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0))) { RandomizeColor(cosmeticOption); } } @@ -1867,7 +1867,7 @@ void CosmeticsEditor_RandomizeAll() { void CosmeticsEditor_RandomizeGroup(CosmeticGroup group) { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (!CVarGetInteger(cosmeticOption.lockedCvar, 0) && - (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) && + (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) && cosmeticOption.group == group) { RandomizeColor(cosmeticOption); } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 6d66d1c8b..229f76cbb 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -428,34 +428,34 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint switch (cosmeticCategory) { case GI_COSMETICS_TUNICS: - CVarSetColor("gCosmetics.Link_KokiriTunic.Value", newColor); - CVarSetInteger("gCosmetics.Link_KokiriTunic.Changed", 1); - CVarSetColor("gCosmetics.Link_GoronTunic.Value", newColor); - CVarSetInteger("gCosmetics.Link_GoronTunic.Changed", 1); - CVarSetColor("gCosmetics.Link_ZoraTunic.Value", newColor); - CVarSetInteger("gCosmetics.Link_ZoraTunic.Changed", 1); + CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Link.GoronTunic.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Link.ZoraTunic.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 1); break; case GI_COSMETICS_NAVI: - CVarSetColor("gCosmetics.Navi_EnemyPrimary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_EnemyPrimary.Changed", 1); - CVarSetColor("gCosmetics.Navi_EnemySecondary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_EnemySecondary.Changed", 1); - CVarSetColor("gCosmetics.Navi_IdlePrimary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_IdlePrimary.Changed", 1); - CVarSetColor("gCosmetics.Navi_IdleSecondary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_IdleSecondary.Changed", 1); - CVarSetColor("gCosmetics.Navi_NPCPrimary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_NPCPrimary.Changed", 1); - CVarSetColor("gCosmetics.Navi_NPCSecondary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_NPCSecondary.Changed", 1); - CVarSetColor("gCosmetics.Navi_PropsPrimary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_PropsPrimary.Changed", 1); - CVarSetColor("gCosmetics.Navi_PropsSecondary.Value", newColor); - CVarSetInteger("gCosmetics.Navi_PropsSecondary.Changed", 1); + CVarSetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 1); + CVarSetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 1); break; case GI_COSMETICS_HAIR: - CVarSetColor("gCosmetics.Link_Hair.Value", newColor); - CVarSetInteger("gCosmetics.Link_Hair.Changed", 1); + CVarSetColor(CVAR_COSMETIC("Link.Hair.Value"), newColor); + CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1); break; } @@ -465,18 +465,18 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { const char* cvarsToLock[12] = { - "gCosmetics.Link_KokiriTunic.Locked", - "gCosmetics.Link_GoronTunic.Locked", - "gCosmetics.Link_ZoraTunic.Locked", - "gCosmetics.Navi_EnemyPrimary.Locked", - "gCosmetics.Navi_EnemySecondary.Locked", - "gCosmetics.Navi_IdlePrimary.Locked", - "gCosmetics.Navi_IdleSecondary.Locked", - "gCosmetics.Navi_NPCPrimary.Locked", - "gCosmetics.Navi_NPCSecondary.Locked", - "gCosmetics.Navi_PropsPrimary.Locked", - "gCosmetics.Navi_PropsSecondary.Locked", - "gCosmetics.Link_Hair.Locked" + CVAR_COSMETIC("Link.KokiriTunic.Locked"), + CVAR_COSMETIC("Link.GoronTunic.Locked"), + CVAR_COSMETIC("Link.ZoraTunic.Locked"), + CVAR_COSMETIC("Navi.EnemyPrimary.Locked"), + CVAR_COSMETIC("Navi.EnemySecondary.Locked"), + CVAR_COSMETIC("Navi.IdlePrimary.Locked"), + CVAR_COSMETIC("Navi.IdleSecondary.Locked"), + CVAR_COSMETIC("Navi.NPCPrimary.Locked"), + CVAR_COSMETIC("Navi.NPCSecondary.Locked"), + CVAR_COSMETIC("Navi.PropsPrimary.Locked"), + CVAR_COSMETIC("Navi.PropsSecondary.Locked"), + CVAR_COSMETIC("Link.Hair.Locked") }; if (excludeBiddingWarColors) { diff --git a/soh/soh/Enhancements/nametag.cpp b/soh/soh/Enhancements/nametag.cpp index 038ba4e1f..0d4ce2a0c 100644 --- a/soh/soh/Enhancements/nametag.cpp +++ b/soh/soh/Enhancements/nametag.cpp @@ -5,6 +5,7 @@ #include "soh/frame_interpolation.h" #include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" extern "C" { #include "z64.h" @@ -70,11 +71,11 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) { Color_RGBA8 textboxColor = { 0, 0, 0, 80}; Color_RGBA8 textColor = { 255, 255, 255, 255 }; - if (CVarGetInteger("gCosmetics.Hud_NameTagActorBackground.Changed", 0)) { - textboxColor = CVarGetColor("gCosmetics.Hud_NameTagActorBackground.Value", textboxColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) { + textboxColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorBackground.Value"), textboxColor); } - if (CVarGetInteger("gCosmetics.Hud_NameTagActorText.Changed", 0)) { - textColor = CVarGetColor("gCosmetics.Hud_NameTagActorText.Value", textColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorText.Changed"), 0)) { + textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor); } FrameInterpolation_RecordOpenChild(nameTag->actor, 10); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 930b89b80..8064fc66c 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -345,12 +345,12 @@ const std::vector cheatCvars = { CVAR_CHEAT("DekuStick"), CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), - "gCosmetics.Link_BodyScale.Changed", - "gCosmetics.Link_BodyScale.Value", - "gCosmetics.Link_HeadScale.Changed", - "gCosmetics.Link_HeadScale.Value", - "gCosmetics.Link_SwordScale.Changed", - "gCosmetics.Link_SwordScale.Value", + CVAR_COSMETIC("Link.BodyScale.Changed"), + CVAR_COSMETIC("Link.BodyScale.Value"), + CVAR_COSMETIC("Link.HeadScale.Changed"), + CVAR_COSMETIC("Link.HeadScale.Value"), + CVAR_COSMETIC("Link.SwordScale.Changed"), + CVAR_COSMETIC("Link.SwordScale.Value"), CVAR_ENHANCEMENT("RememberMapToggleState"), }; @@ -950,7 +950,7 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 4), - PRESET_ENTRY_S32("gCosmetics.Goron_NeckLength", 1000), + PRESET_ENTRY_S32(CVAR_COSMETIC("Goron.NeckLength"), 1000), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1), diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index ba8aab9fb..1123cba72 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1516,7 +1516,7 @@ static std::set rainbowCVars = { int hue = 0; void RainbowTick() { - float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat("gCosmetics.RainbowSpeed", 0.6f)); + float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f)); for (auto& cvar : rainbowCVars) { if (CVarGetInteger((cvar + "RBM").c_str(), 0) == 0) { continue; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 5b0ef431d..71b738b96 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2123,17 +2123,17 @@ Color_RGB8 GetColorForControllerLED() { switch (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC)) { case EQUIP_VALUE_TUNIC_KOKIRI: color = source == LED_SOURCE_TUNIC_COSMETICS - ? CVarGetColor24("gCosmetics.Link_KokiriTunic.Value", kokiriColor) + ? CVarGetColor24(CVAR_COSMETIC("Link.KokiriTunic.Value"), kokiriColor) : kokiriColor; break; case EQUIP_VALUE_TUNIC_GORON: color = source == LED_SOURCE_TUNIC_COSMETICS - ? CVarGetColor24("gCosmetics.Link_GoronTunic.Value", goronColor) + ? CVarGetColor24(CVAR_COSMETIC("Link.GoronTunic.Value"), goronColor) : goronColor; break; case EQUIP_VALUE_TUNIC_ZORA: color = source == LED_SOURCE_TUNIC_COSMETICS - ? CVarGetColor24("gCosmetics.Link_ZoraTunic.Value", zoraColor) + ? CVarGetColor24(CVAR_COSMETIC("Link.ZoraTunic.Value"), zoraColor) : zoraColor; break; } @@ -2145,16 +2145,16 @@ Color_RGB8 GetColorForControllerLED() { switch (category) { case ACTORCAT_PLAYER: if (source == LED_SOURCE_NAVI_COSMETICS && - CVarGetInteger("gCosmetics.Navi_IdlePrimary.Changed", 0)) { - color = CVarGetColor24("gCosmetics.Navi_IdlePrimary.Value", defaultIdleColor.inner); + CVarGetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("Navi.IdlePrimary.Value"), defaultIdleColor.inner); break; } color = LEDColorDefaultNaviColorList[category].inner; break; case ACTORCAT_NPC: if (source == LED_SOURCE_NAVI_COSMETICS && - CVarGetInteger("gCosmetics.Navi_NPCPrimary.Changed", 0)) { - color = CVarGetColor24("gCosmetics.Navi_NPCPrimary.Value", defaultNPCColor.inner); + CVarGetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("Navi.NPCPrimary.Value"), defaultNPCColor.inner); break; } color = LEDColorDefaultNaviColorList[category].inner; @@ -2162,23 +2162,23 @@ Color_RGB8 GetColorForControllerLED() { case ACTORCAT_ENEMY: case ACTORCAT_BOSS: if (source == LED_SOURCE_NAVI_COSMETICS && - CVarGetInteger("gCosmetics.Navi_EnemyPrimary.Changed", 0)) { - color = CVarGetColor24("gCosmetics.Navi_EnemyPrimary.Value", defaultEnemyColor.inner); + CVarGetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), defaultEnemyColor.inner); break; } color = LEDColorDefaultNaviColorList[category].inner; break; default: if (source == LED_SOURCE_NAVI_COSMETICS && - CVarGetInteger("gCosmetics.Navi_PropsPrimary.Changed", 0)) { - color = CVarGetColor24("gCosmetics.Navi_PropsPrimary.Value", defaultPropsColor.inner); + CVarGetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("Navi.PropsPrimary.Value"), defaultPropsColor.inner); break; } color = LEDColorDefaultNaviColorList[category].inner; } } else { // No target actor. - if (source == LED_SOURCE_NAVI_COSMETICS && CVarGetInteger("gCosmetics.Navi_IdlePrimary.Changed", 0)) { - color = CVarGetColor24("gCosmetics.Navi_IdlePrimary.Value", defaultIdleColor.inner); + if (source == LED_SOURCE_NAVI_COSMETICS && CVarGetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("Navi.IdlePrimary.Value"), defaultIdleColor.inner); } else { color = LEDColorDefaultNaviColorList[ACTORCAT_PLAYER].inner; } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 87c4f9b46..4242b9ecc 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -353,50 +353,50 @@ void func_8002BE98(TargetContext* targetCtx, s32 actorCategory, PlayState* play) } void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, PlayState* play) { - if (CVarGetInteger("gCosmetics.Navi_IdlePrimary.Changed", 0)) { - sNaviColorList[ACTORCAT_PLAYER].inner = CVarGetColor("gCosmetics.Navi_IdlePrimary.Value", defaultIdlePrimaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 0)) { + sNaviColorList[ACTORCAT_PLAYER].inner = CVarGetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), defaultIdlePrimaryColor); } else { sNaviColorList[ACTORCAT_PLAYER].inner = defaultIdlePrimaryColor; } - if (CVarGetInteger("gCosmetics.Navi_IdleSecondary.Changed", 0)) { - sNaviColorList[ACTORCAT_PLAYER].outer = CVarGetColor("gCosmetics.Navi_IdleSecondary.Value", defaultIdleSecondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 0)) { + sNaviColorList[ACTORCAT_PLAYER].outer = CVarGetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), defaultIdleSecondaryColor); } else { sNaviColorList[ACTORCAT_PLAYER].outer = defaultIdleSecondaryColor; } - if (CVarGetInteger("gCosmetics.Navi_NPCPrimary.Changed", 0)) { - sNaviColorList[ACTORCAT_NPC].inner = CVarGetColor("gCosmetics.Navi_NPCPrimary.Value", defaultNPCPrimaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 0)) { + sNaviColorList[ACTORCAT_NPC].inner = CVarGetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), defaultNPCPrimaryColor); } else { sNaviColorList[ACTORCAT_NPC].inner = defaultNPCPrimaryColor; } - if (CVarGetInteger("gCosmetics.Navi_NPCSecondary.Changed", 0)) { - sNaviColorList[ACTORCAT_NPC].outer = CVarGetColor("gCosmetics.Navi_NPCSecondary.Value", defaultNPCSecondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 0)) { + sNaviColorList[ACTORCAT_NPC].outer = CVarGetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), defaultNPCSecondaryColor); } else { sNaviColorList[ACTORCAT_NPC].outer = defaultNPCSecondaryColor; } - if (CVarGetInteger("gCosmetics.Navi_EnemyPrimary.Changed", 0)) { - sNaviColorList[ACTORCAT_ENEMY].inner = CVarGetColor("gCosmetics.Navi_EnemyPrimary.Value", defaultEnemyPrimaryColor); - sNaviColorList[ACTORCAT_BOSS].inner = CVarGetColor("gCosmetics.Navi_EnemyPrimary.Value", defaultEnemyPrimaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 0)) { + sNaviColorList[ACTORCAT_ENEMY].inner = CVarGetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), defaultEnemyPrimaryColor); + sNaviColorList[ACTORCAT_BOSS].inner = CVarGetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), defaultEnemyPrimaryColor); } else { sNaviColorList[ACTORCAT_ENEMY].inner = defaultEnemyPrimaryColor; sNaviColorList[ACTORCAT_BOSS].inner = defaultEnemyPrimaryColor; } - if (CVarGetInteger("gCosmetics.Navi_EnemySecondary.Changed", 0)) { - sNaviColorList[ACTORCAT_ENEMY].outer = CVarGetColor("gCosmetics.Navi_EnemySecondary.Value", defaultEnemySecondaryColor); - sNaviColorList[ACTORCAT_BOSS].outer = CVarGetColor("gCosmetics.Navi_EnemySecondary.Value", defaultEnemySecondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 0)) { + sNaviColorList[ACTORCAT_ENEMY].outer = CVarGetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), defaultEnemySecondaryColor); + sNaviColorList[ACTORCAT_BOSS].outer = CVarGetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), defaultEnemySecondaryColor); } else { sNaviColorList[ACTORCAT_ENEMY].outer = defaultEnemySecondaryColor; sNaviColorList[ACTORCAT_BOSS].outer = defaultEnemySecondaryColor; } - if (CVarGetInteger("gCosmetics.Navi_PropsPrimary.Changed", 0)) { - sNaviColorList[ACTORCAT_PROP].inner = CVarGetColor("gCosmetics.Navi_PropsPrimary.Value", defaultPropsPrimaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 0)) { + sNaviColorList[ACTORCAT_PROP].inner = CVarGetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), defaultPropsPrimaryColor); } else { sNaviColorList[ACTORCAT_PROP].inner = defaultPropsPrimaryColor; } - if (CVarGetInteger("gCosmetics.Navi_PropsSecondary.Changed", 0)) { - sNaviColorList[ACTORCAT_PROP].outer = CVarGetColor("gCosmetics.Navi_PropsSecondary.Value", defaultPropsSecondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 0)) { + sNaviColorList[ACTORCAT_PROP].outer = CVarGetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), defaultPropsSecondaryColor); } else { sNaviColorList[ACTORCAT_PROP].outer = defaultPropsSecondaryColor; } @@ -1119,10 +1119,10 @@ void TitleCard_Draw(PlayState* play, TitleCardContext* titleCtx) { if (titleCtx->alpha != 0) { width = titleCtx->width; height = titleCtx->height; - s16 TitleCard_PosX_Modifier = (titleCtx->isBossCard ? CVarGetInteger("gTCBPosX", 0) : CVarGetInteger("gTCMPosX", 0)); - s16 TitleCard_PosY_Modifier = (titleCtx->isBossCard ? CVarGetInteger("gTCBPosY", 0) : CVarGetInteger("gTCMPosY", 0)); - s16 TitleCard_PosType_Checker = (titleCtx->isBossCard ? CVarGetInteger("gTCBPosType", 0) : CVarGetInteger("gTCMPosType", 0)); - s16 TitleCard_Margin_Checker = (titleCtx->isBossCard ? CVarGetInteger("gTCBUseMargins", 0) : CVarGetInteger("gTCMUseMargins", 0)); + s16 TitleCard_PosX_Modifier = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosX"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosX"), 0)); + s16 TitleCard_PosY_Modifier = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosY"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosY"), 0)); + s16 TitleCard_PosType_Checker = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.PosType"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.PosType"), 0)); + s16 TitleCard_Margin_Checker = (titleCtx->isBossCard ? CVarGetInteger(CVAR_COSMETIC("TitleCard.Boss.UseMargins"), 0) : CVarGetInteger(CVAR_COSMETIC("TitleCard.Map.UseMargins"), 0)); s16 TitleCard_MarginX = 0; s16 TitleCard_PosX = titleCtx->x; s16 TitleCard_PosY = titleCtx->y; diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c index e9ab95398..4307f03ce 100644 --- a/soh/src/code/z_draw.c +++ b/soh/src/code/z_draw.c @@ -761,13 +761,13 @@ void GetItem_DrawRecoveryHeart(PlayState* play, s16 drawId) { 1 * -(play->state.frames * 2), 32, 32)); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); - if (CVarGetInteger("gCosmetics.Consumable_Hearts.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Consumable_Hearts.Value", (Color_RGB8) { 255, 70, 50 }); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("Consumable.Hearts.Value"), (Color_RGB8) { 255, 70, 50 }); gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255); gSPGrayscale(POLY_XLU_DISP++, true); } gSPDisplayList(POLY_XLU_DISP++, sDrawItemTable[drawId].dlists[0]); - if (CVarGetInteger("gCosmetics.Consumable_Hearts.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { gSPGrayscale(POLY_XLU_DISP++, false); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/code/z_eff_blure.c b/soh/src/code/z_eff_blure.c index e770a9096..82e50fc65 100644 --- a/soh/src/code/z_eff_blure.c +++ b/soh/src/code/z_eff_blure.c @@ -208,8 +208,8 @@ s32 EffectBlure_Update(void* thisx) { switch (this->trailType) { //there HAS to be a better way to do this. case 2: - if (CVarGetInteger("gCosmetics.Trails_Boomerang.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_Boomerang.Value", (Color_RGBA8){ 255, 255, 100, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.Boomerang.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.Boomerang.Value"), (Color_RGBA8){ 255, 255, 100, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 100, 255 }; @@ -217,8 +217,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 3: - if (CVarGetInteger("gCosmetics.Trails_Bombchu.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_Bombchu.Value", (Color_RGBA8){ 250, 0, 0, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.Bombchu.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.Bombchu.Value"), (Color_RGBA8){ 250, 0, 0, 255 }); this->p1StartColor.r = color.r; this->p2StartColor.r = color.r * 0.8f; this->p1EndColor.r = color.r * 0.6f; @@ -248,8 +248,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 4: - if (CVarGetInteger("gCosmetics.Trails_KokiriSword.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_KokiriSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.KokiriSword.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.KokiriSword.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 255, 255 }; @@ -257,8 +257,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 5: - if (CVarGetInteger("gCosmetics.Trails_MasterSword.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_MasterSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.MasterSword.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.MasterSword.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 255, 255 }; @@ -266,8 +266,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 6: - if (CVarGetInteger("gCosmetics.Trails_BiggoronSword.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_BiggoronSword.Value", (Color_RGBA8){ 255, 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.BiggoronSword.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.BiggoronSword.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 255, 255 }; @@ -275,8 +275,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 7: - if (CVarGetInteger("gCosmetics.Trails_Stick.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_Stick.Value", (Color_RGBA8){ 255, 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.Stick.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.Stick.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 255, 255 }; @@ -284,8 +284,8 @@ s32 EffectBlure_Update(void* thisx) { } break; case 8: - if (CVarGetInteger("gCosmetics.Trails_Hammer.Changed", 0)) { - color = CVarGetColor("gCosmetics.Trails_Hammer.Value", (Color_RGBA8){ 255, 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Trails.Hammer.Changed"), 0)) { + color = CVarGetColor(CVAR_COSMETIC("Trails.Hammer.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); changed = 1; } else if (changed) { color = (Color_RGBA8){ 255, 255, 255, 255 }; @@ -317,8 +317,8 @@ s32 EffectBlure_Update(void* thisx) { // Don't override boomerang and bombchu trail durations if (this->trailType != 2 && this->trailType != 3) { - if (CVarGetInteger("gCosmetics.Trails_Duration.Changed", 0)) { - this->elemDuration = CVarGetInteger("gCosmetics.Trails_Duration.Value", 4); + if (CVarGetInteger(CVAR_COSMETIC("Trails.Duration.Changed"), 0)) { + this->elemDuration = CVarGetInteger(CVAR_COSMETIC("Trails.Duration.Value"), 4); } } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 4f59e29df..7a2b9d3d8 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1316,24 +1316,24 @@ void EnItem00_DrawRupee(EnItem00* this, PlayState* play) { u8 shouldColor = 0; switch (texIndex) { case 0: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0); break; case 1: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_BlueRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_BlueRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0); break; case 2: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_RedRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_RedRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0); break; case 4: // orange rupee texture corresponds to the purple rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_PurpleRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_PurpleRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0); break; case 3: // pink rupee texture corresponds to the gold rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GoldRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GoldRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GoldRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GoldRupee.Changed"), 0); break; } diff --git a/soh/src/code/z_kankyo.c b/soh/src/code/z_kankyo.c index 77c7546f8..90ac9135f 100644 --- a/soh/src/code/z_kankyo.c +++ b/soh/src/code/z_kankyo.c @@ -1384,7 +1384,7 @@ void Environment_DrawSunAndMoon(PlayState* play) { color = CLAMP_MIN(color, 0.0f); scale = -15.0f * color + 25.0f; - scale *= CVarGetFloat("gCosmetics.Moon_Size", 1.0f); + scale *= CVarGetFloat(CVAR_COSMETIC("Moon.Size"), 1.0f); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); temp = -y / 80.0f; @@ -1396,8 +1396,8 @@ void Environment_DrawSunAndMoon(PlayState* play) { gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_LOAD); Gfx_SetupDL_51Opa(play->state.gfxCtx); gDPPipeSync(POLY_OPA_DISP++); - if (CVarGetInteger("gCosmetics.World_Moon.Changed", 0)) { - Color_RGB8 moonColor = CVarGetColor24("gCosmetics.World_Moon.Value", (Color_RGB8){ 0, 0, 240 }); + if (CVarGetInteger(CVAR_COSMETIC("World.Moon.Changed"), 0)) { + Color_RGB8 moonColor = CVarGetColor24(CVAR_COSMETIC("World.Moon.Value"), (Color_RGB8){ 0, 0, 240 }); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, moonColor.r, moonColor.g, moonColor.b, alpha); gDPSetEnvColor(POLY_OPA_DISP++, moonColor.r / 2, moonColor.g / 2, moonColor.b / 2, alpha); } else { diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index bc337df4c..da4c16a51 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -120,20 +120,20 @@ s16 sHeartsDDEnv[2][3]; void HealthMeter_Init(PlayState* play) { InterfaceContext* interfaceCtx = &play->interfaceCtx; Color_RGB8 mainColor = {HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_Hearts.Changed", 0)) { - mainColor = CVarGetColor24("gCosmetics.Consumable_Hearts.Value", mainColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { + mainColor = CVarGetColor24(CVAR_COSMETIC("Consumable.Hearts.Value"), mainColor); } Color_RGB8 mainBorder = {HEARTS_ENV_R, HEARTS_ENV_G, HEARTS_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_HeartBorder.Changed", 0)) { - mainBorder = CVarGetColor24("gCosmetics.Consumable_HeartBorder.Value", mainBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.HeartBorder.Changed"), 0)) { + mainBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.HeartBorder.Value"), mainBorder); } Color_RGB8 ddColor = {HEARTS_DD_ENV_R, HEARTS_DD_ENV_G, HEARTS_DD_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHearts.Changed", 0)) { - ddColor = CVarGetColor24("gCosmetics.Consumable_DDHearts.Value", ddColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHearts.Changed"), 0)) { + ddColor = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHearts.Value"), ddColor); } Color_RGB8 ddBorder = {HEARTS_DD_PRIM_R, HEARTS_DD_PRIM_G, HEARTS_DD_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHeartBorder.Changed", 0)) { - ddBorder = CVarGetColor24("gCosmetics.Consumable_DDHeartBorder.Value", ddBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHeartBorder.Changed"), 0)) { + ddBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHeartBorder.Value"), ddBorder); } interfaceCtx->unk_228 = 0x140; @@ -182,20 +182,20 @@ void HealthMeter_Update(PlayState* play) { Bottom_LM_Margin = CVarGetInteger("gHUDMargin_B", 0); Color_RGB8 mainColor = {HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_Hearts.Changed", 0)) { - mainColor = CVarGetColor24("gCosmetics.Consumable_Hearts.Value", mainColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { + mainColor = CVarGetColor24(CVAR_COSMETIC("Consumable.Hearts.Value"), mainColor); } Color_RGB8 mainBorder = {HEARTS_ENV_R, HEARTS_ENV_G, HEARTS_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_HeartBorder.Changed", 0)) { - mainBorder = CVarGetColor24("gCosmetics.Consumable_HeartBorder.Value", mainBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.HeartBorder.Changed"), 0)) { + mainBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.HeartBorder.Value"), mainBorder); } Color_RGB8 ddColor = {HEARTS_DD_ENV_R, HEARTS_DD_ENV_G, HEARTS_DD_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHearts.Changed", 0)) { - ddColor = CVarGetColor24("gCosmetics.Consumable_DDHearts.Value", ddColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHearts.Changed"), 0)) { + ddColor = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHearts.Value"), ddColor); } Color_RGB8 ddBorder = {HEARTS_DD_PRIM_R, HEARTS_DD_PRIM_G, HEARTS_DD_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHeartBorder.Changed", 0)) { - ddBorder = CVarGetColor24("gCosmetics.Consumable_DDHeartBorder.Value", ddBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHeartBorder.Changed"), 0)) { + ddBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHeartBorder.Value"), ddBorder); } if (interfaceCtx->unk_200 != 0) { @@ -336,20 +336,20 @@ static void* sHeartDDTextures[] = { s16 getHealthMeterXOffset() { s16 X_Margins; - if (CVarGetInteger("gHeartsUseMargins", 0) != 0) + if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) X_Margins = Left_LM_Margin; else X_Margins = 0; - if (CVarGetInteger("gHeartsCountPosType", 0) != 0) { - if (CVarGetInteger("gHeartsCountPosType", 0) == 1) {//Anchor Left - return OTRGetDimensionFromLeftEdge(CVarGetInteger("gHeartsCountPosX", 0)+X_Margins+70.0f); - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 1) {//Anchor Left + return OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 2) {//Anchor Right X_Margins = Right_LM_Margin; - return OTRGetDimensionFromRightEdge(CVarGetInteger("gHeartsCountPosX", 0)+X_Margins+70.0f); - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 3) {//Anchor None - return CVarGetInteger("gHeartsCountPosX", 0)+70.0f;; - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 4) {//Hidden + return OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 3) {//Anchor None + return CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+70.0f;; + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 4) {//Hidden return -9999; } } else { @@ -359,15 +359,15 @@ s16 getHealthMeterXOffset() { s16 getHealthMeterYOffset() { s16 Y_Margins; - if (CVarGetInteger("gHeartsUseMargins", 0) != 0) + if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) Y_Margins = (Top_LM_Margin*-1); else Y_Margins = 0; f32 HeartsScale = 0.7f; - if (CVarGetInteger("gHeartsCountPosType", 0) != 0) { - HeartsScale = CVarGetFloat("gHeartsCountScale", 0.7f); - return CVarGetInteger("gHeartsCountPosY", 0)+Y_Margins+(HeartsScale*15); + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { + HeartsScale = CVarGetFloat(CVAR_COSMETIC("HeartsCount.Scale"), 0.7f); + return CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); } else { return 0.0f+Y_Margins; } @@ -397,8 +397,8 @@ void HealthMeter_Draw(PlayState* play) { u8* curBgImgLoaded = NULL; s32 ddHeartCountMinusOne = gSaveContext.isDoubleDefenseAcquired ? totalHeartCount - 1 : -1; f32 HeartsScale = 0.7f; - if (CVarGetInteger("gHeartsCountPosType", 0) != 0) { - HeartsScale = CVarGetFloat("gHeartsCountScale", 0.7f); + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { + HeartsScale = CVarGetFloat(CVAR_COSMETIC("HeartsCount.Scale"), 0.7f); } static u32 epoch = 0; epoch++; @@ -413,7 +413,7 @@ void HealthMeter_Draw(PlayState* play) { /* s16 X_Margins; s16 Y_Margins; - if (CVarGetInteger("gHeartsUseMargins", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) { X_Margins = Left_LM_Margin; Y_Margins = (Top_LM_Margin*-1); } else { @@ -422,16 +422,16 @@ void HealthMeter_Draw(PlayState* play) { } s16 PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins; s16 PosY_original = 0.0f+Y_Margins; - if (CVarGetInteger("gHeartsCountPosType", 0) != 0) { - offsetY = CVarGetInteger("gHeartsCountPosY", 0)+Y_Margins+(HeartsScale*15); - if (CVarGetInteger("gHeartsCountPosType", 0) == 1) {//Anchor Left - offsetX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gHeartsCountPosX", 0)+X_Margins+70.0f); - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { + offsetY = CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); + if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 1) {//Anchor Left + offsetX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 2) {//Anchor Right X_Margins = Right_LM_Margin; - offsetX = OTRGetDimensionFromRightEdge(CVarGetInteger("gHeartsCountPosX", 0)+X_Margins+70.0f); - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 3) {//Anchor None - offsetX = CVarGetInteger("gHeartsCountPosX", 0)+70.0f; - } else if (CVarGetInteger("gHeartsCountPosType", 0) == 4) {//Hidden + offsetX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 3) {//Anchor None + offsetX = CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+70.0f; + } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 4) {//Hidden offsetX = -9999; } } else { @@ -626,7 +626,7 @@ void HealthMeter_Draw(PlayState* play) { } offsetX += 10.0f; - s32 lineLength = CVarGetInteger("gHeartsLineLength", 10); + s32 lineLength = CVarGetInteger(CVAR_COSMETIC("Hearts.LineLength"), 10); if (lineLength != 0 && (i+1)%lineLength == 0) { offsetX = PosX_anchor; offsetY += 10.0f; diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 2370f3a58..abee561aa 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -606,17 +606,17 @@ void Minimap_DrawCompassIcons(PlayState* play) { Player* player = GET_PLAYER(play); s16 tempX, tempZ; Color_RGB8 lastEntranceColor = { 200, 0, 0 }; - if (CVarGetInteger("gCosmetics.Hud_MinimapEntrance.Changed", 0)) { - lastEntranceColor = CVarGetColor24("gCosmetics.Hud_MinimapEntrance.Value", lastEntranceColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.MinimapEntrance.Changed"), 0)) { + lastEntranceColor = CVarGetColor24(CVAR_COSMETIC("HUD.MinimapEntrance.Value"), lastEntranceColor); } Color_RGB8 currentPositionColor = { 200, 255, 0 }; - if (CVarGetInteger("gCosmetics.Hud_MinimapPosition.Changed", 0)) { - currentPositionColor = CVarGetColor24("gCosmetics.Hud_MinimapPosition.Value", currentPositionColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.MinimapPosition.Changed"), 0)) { + currentPositionColor = CVarGetColor24(CVAR_COSMETIC("HUD.MinimapPosition.Value"), currentPositionColor); } s16 X_Margins_Minimap; s16 Y_Margins_Minimap; - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) { - if (CVarGetInteger("gMinimapPosType", 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; Y_Margins_Minimap = Bottom_MM_Margin; } else { X_Margins_Minimap = 0; @@ -656,21 +656,21 @@ void Minimap_DrawCompassIcons(PlayState* play) { tempZ /= R_COMPASS_SCALE_Y; s16 tempXOffset = R_COMPASS_OFFSET_X + (CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset : 0); - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None + OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None Matrix_Translate( - (tempXOffset + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); @@ -690,21 +690,21 @@ void Minimap_DrawCompassIcons(PlayState* play) { tempZ = sPlayerInitialPosZ; tempX /= R_COMPASS_SCALE_X * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); tempZ /= R_COMPASS_SCALE_Y; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None + OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None Matrix_Translate( - (tempXOffset + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f), - (R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10) / 10.0f), + (R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); @@ -727,8 +727,8 @@ void Minimap_Draw(PlayState* play) { InterfaceContext* interfaceCtx = &play->interfaceCtx; s32 mapIndex = gSaveContext.mapIndex; Color_RGB8 minimapColor = {0, 255, 255}; - if (CVarGetInteger("gCosmetics.Hud_Minimap.Changed", 0)) { - minimapColor = CVarGetColor24("gCosmetics.Hud_Minimap.Value", minimapColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.Changed"), 0)) { + minimapColor = CVarGetColor24(CVAR_COSMETIC("HUD.Minimap.Value"), minimapColor); } OPEN_DISPS(play->state.gfxCtx); @@ -742,8 +742,8 @@ void Minimap_Draw(PlayState* play) { //Minimap margins s16 X_Margins_Minimap; s16 Y_Margins_Minimap; - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) { - if (CVarGetInteger("gMinimapPosType", 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; Y_Margins_Minimap = Bottom_MM_Margin; } else { X_Margins_Minimap = 0; @@ -761,7 +761,7 @@ void Minimap_Draw(PlayState* play) { case SCENE_SHADOW_TEMPLE: case SCENE_BOTTOM_OF_THE_WELL: case SCENE_ICE_CAVERN: - if (!R_MINIMAP_DISABLED && CVarGetInteger("gMinimapPosType", 0) != 4) { // Not Hidden + if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineLERP(OVERLAY_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0); @@ -776,16 +776,16 @@ void Minimap_Draw(PlayState* play) { s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + X_Margins_Minimap); s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - dgnMiniMapY = R_DGN_MINIMAP_Y+CVarGetInteger("gMinimapPosY", 0)+Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - dgnMiniMapX = OTRGetDimensionFromLeftEdge(R_DGN_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - dgnMiniMapX = OTRGetDimensionFromRightEdge(R_DGN_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None - dgnMiniMapX = CVarGetInteger("gMinimapPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + dgnMiniMapY = R_DGN_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)+Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + dgnMiniMapX = OTRGetDimensionFromLeftEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + dgnMiniMapX = OTRGetDimensionFromRightEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + dgnMiniMapX = CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); } } @@ -839,7 +839,7 @@ void Minimap_Draw(PlayState* play) { case SCENE_GORON_CITY: case SCENE_LON_LON_RANCH: case SCENE_OUTSIDE_GANONS_CASTLE: - if (!R_MINIMAP_DISABLED && CVarGetInteger("gMinimapPosType", 0) != 4) { // Not Hidden + if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); @@ -853,16 +853,16 @@ void Minimap_Draw(PlayState* play) { s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + X_Margins_Minimap); s16 oWMiniMapY = R_OW_MINIMAP_Y + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - oWMiniMapY = R_OW_MINIMAP_Y+CVarGetInteger("gMinimapPosY", 0)+Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - oWMiniMapX = OTRGetDimensionFromLeftEdge(R_OW_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - oWMiniMapX = OTRGetDimensionFromRightEdge(R_OW_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None - oWMiniMapX = CVarGetInteger("gMinimapPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + oWMiniMapY = R_OW_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)+Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + oWMiniMapX = OTRGetDimensionFromLeftEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + oWMiniMapX = OTRGetDimensionFromRightEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + oWMiniMapX = CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); } } @@ -901,16 +901,16 @@ void Minimap_Draw(PlayState* play) { s16 entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap); s16 entranceY = newY + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - entranceY = newY + CVarGetInteger("gMinimapPosY", 0) + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) == 1) { // Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - entranceX = OTRGetRectDimensionFromLeftEdge(newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0)); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) { // Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0)); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) { // Anchor None - entranceX = newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + entranceY = newY + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0) + Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) { // Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + entranceX = OTRGetRectDimensionFromLeftEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) { // Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) { // Anchor None + entranceX = newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); } } @@ -937,16 +937,16 @@ void Minimap_Draw(PlayState* play) { s16 origX = CVarGetInteger("gMirroredWorld", 0) ? 256 : 270; s16 entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap); s16 entranceY = 154 + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - entranceY = 154 + Y_Margins_Minimap + CVarGetInteger("gMinimapPosY", 0); - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - entranceX = OTRGetRectDimensionFromLeftEdge(origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0)); - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0)); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None - entranceX = origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + entranceY = 154 + Y_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + entranceX = OTRGetRectDimensionFromLeftEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + entranceX = origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); } } diff --git a/soh/src/code/z_map_mark.c b/soh/src/code/z_map_mark.c index 212fad139..c9d5d753f 100644 --- a/soh/src/code/z_map_mark.c +++ b/soh/src/code/z_map_mark.c @@ -120,8 +120,8 @@ void MapMark_DrawForDungeon(PlayState* play) { s32 X_Margins_Minimap_ic; s32 Y_Margins_Minimap_ic; - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) { - if (CVarGetInteger("gMinimapPosType", 0) == 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; Y_Margins_Minimap_ic = Bottom_MC_Margin; } else { X_Margins_Minimap_ic = 0; @@ -146,24 +146,24 @@ void MapMark_DrawForDungeon(PlayState* play) { //Minimap chest / boss icon const s32 PosX_Minimap_ori = GREG(94) + OTRGetRectDimensionFromRightEdge(markPointX+X_Margins_Minimap_ic) + 204; const s32 PosY_Minimap_ori = GREG(95) + markPoint->y + Y_Margins_Minimap_ic + 140; - if (CVarGetInteger("gMinimapPosType", 0) != 0) { - rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger("gMinimapPosY", 0)); - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap_ic = Left_MC_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { + rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)); + if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Left_MC_Margin;}; if (play->sceneNum == SCENE_DEKU_TREE || play->sceneNum == SCENE_DODONGOS_CAVERN || play->sceneNum == SCENE_JABU_JABU || play->sceneNum == SCENE_FOREST_TEMPLE || play->sceneNum == SCENE_FIRE_TEMPLE || play->sceneNum == SCENE_WATER_TEMPLE || play->sceneNum == SCENE_SPIRIT_TEMPLE || play->sceneNum == SCENE_SHADOW_TEMPLE || play->sceneNum == SCENE_BOTTOM_OF_THE_WELL || play->sceneNum == SCENE_ICE_CAVERN) { - rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic); + rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); } else { - rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic); + rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); } - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; - rectLeft = OTRGetRectDimensionFromRightEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic); - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None - rectLeft = markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic; - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; + rectLeft = OTRGetRectDimensionFromRightEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + rectLeft = markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic; + } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 4) {//Hidden rectLeft = -9999; } } else { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 149ca72df..3a77fb35f 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -99,30 +99,30 @@ void Message_ResetOcarinaNoteState(void) { sOcarinaNoteABtnEnv = (Color_RGB8){ 10, 10, 10 }; sOcarinaNoteCBtnPrim = (Color_RGB8){ 255, 255, 50 }; sOcarinaNoteCBtnEnv = (Color_RGB8){ 10, 10, 10 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - sOcarinaNoteABtnPrim = CVarGetColor24("gCosmetics.Hud_AButton.Value", sOcarinaNoteABtnPrim); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + sOcarinaNoteABtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), sOcarinaNoteABtnPrim); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { sOcarinaNoteABtnPrim = (Color_RGB8){ 80, 255, 150 }; } - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - sOcarinaNoteCBtnPrim = CVarGetColor24("gCosmetics.Hud_CButtons.Value", sOcarinaNoteCBtnPrim); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + sOcarinaNoteCBtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), sOcarinaNoteCBtnPrim); } sOcarinaNoteCUpBtnPrim = sOcarinaNoteCBtnPrim; sOcarinaNoteCDownBtnPrim = sOcarinaNoteCBtnPrim; sOcarinaNoteCLeftBtnPrim = sOcarinaNoteCBtnPrim; sOcarinaNoteCRightBtnPrim = sOcarinaNoteCBtnPrim; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - sOcarinaNoteCUpBtnPrim = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", sOcarinaNoteCUpBtnPrim); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + sOcarinaNoteCUpBtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), sOcarinaNoteCUpBtnPrim); } - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - sOcarinaNoteCDownBtnPrim = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", sOcarinaNoteCDownBtnPrim); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + sOcarinaNoteCDownBtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), sOcarinaNoteCDownBtnPrim); } - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - sOcarinaNoteCLeftBtnPrim = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", sOcarinaNoteCLeftBtnPrim); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + sOcarinaNoteCLeftBtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), sOcarinaNoteCLeftBtnPrim); } - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - sOcarinaNoteCRightBtnPrim = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", sOcarinaNoteCRightBtnPrim); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + sOcarinaNoteCRightBtnPrim = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), sOcarinaNoteCRightBtnPrim); } } @@ -463,14 +463,14 @@ void Message_DrawTextboxIcon(PlayState* play, Gfx** p, s16 x, s16 y) { { 0, 0, 0 }, { 0, 130, 255 }, }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_AButton.Value", (Color_RGB8){ 50, 130, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), (Color_RGB8){ 50, 130, 255 }); sIconPrimColors[0].r = color.r - 50; sIconPrimColors[0].g = color.g - 50; sIconPrimColors[0].b = color.b - 50; sIconPrimColors[1] = color; sIconEnvColors[1] = color; - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { sIconPrimColors[0] = (Color_RGB8){ 0, 200, 80 }; sIconPrimColors[1] = (Color_RGB8){ 50, 255, 130 }; sIconEnvColors[1] = (Color_RGB8){ 50, 255, 130 }; @@ -2018,14 +2018,14 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 50, 50, 255 }, }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_AButton.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteAPrimColors[0].r = (color.r / 255.0f) * 95; sOcarinaNoteAPrimColors[0].g = (color.g / 255.0f) * 95; sOcarinaNoteAPrimColors[0].b = (color.b / 255.0f) * 95; sOcarinaNoteAPrimColors[1] = color; sOcarinaNoteAEnvColors[1] = color; - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { sOcarinaNoteAPrimColors[0] = (Color_RGB8){ 80, 255, 150 }; sOcarinaNoteAPrimColors[1] = (Color_RGB8){ 100, 255, 200 }; sOcarinaNoteAEnvColors[1] = (Color_RGB8){ 50, 255, 50 }; @@ -2039,8 +2039,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 110, 110, 50 }, }; - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CButtons.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCPrimColors[0] = color; sOcarinaNoteCPrimColors[1] = color; sOcarinaNoteCEnvColors[1].r = (color.r / 255.0f) * 95; @@ -2056,8 +2056,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 110, 110, 50 }, }; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCUpPrimColors[0] = color; sOcarinaNoteCUpPrimColors[1] = color; sOcarinaNoteCUpEnvColors[1].r = (color.r / 255.0f) * 95; @@ -2073,8 +2073,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 110, 110, 50 }, }; - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCDownPrimColors[0] = color; sOcarinaNoteCDownPrimColors[1] = color; sOcarinaNoteCDownEnvColors[1].r = (color.r / 255.0f) * 95; @@ -2090,8 +2090,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 110, 110, 50 }, }; - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCLeftPrimColors[0] = color; sOcarinaNoteCLeftPrimColors[1] = color; sOcarinaNoteCLeftEnvColors[1].r = (color.r / 255.0f) * 95; @@ -2107,8 +2107,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) { { 10, 10, 10 }, { 110, 110, 50 }, }; - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", (Color_RGB8){ 100, 200, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), (Color_RGB8){ 100, 200, 255 }); sOcarinaNoteCRightPrimColors[0] = color; sOcarinaNoteCRightPrimColors[1] = color; sOcarinaNoteCRightEnvColors[1].r = (color.r / 255.0f) * 95; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index dd6949e8e..9b8f85042 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3354,22 +3354,22 @@ void Interface_UpdateMagicBar(PlayState* play) { Color_RGB8 MagicBorder_2 = { 255, 255, 150 }; Color_RGB8 MagicBorder_3 = { 255, 255, 50 }; - if (CVarGetInteger("gCosmetics.Consumable_MagicBorderActive.Changed", 0)) { //This will make custom color based on users selected colors. - sMagicBorderColors[0][0] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_0).r; - sMagicBorderColors[0][1] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_0).g; - sMagicBorderColors[0][2] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_0).b; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorderActive.Changed"), 0)) { //This will make custom color based on users selected colors. + sMagicBorderColors[0][0] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_0).r; + sMagicBorderColors[0][1] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_0).g; + sMagicBorderColors[0][2] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_0).b; - sMagicBorderColors[1][0] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_1).r/2; - sMagicBorderColors[1][1] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_1).g/2; - sMagicBorderColors[1][2] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_1).b/2; + sMagicBorderColors[1][0] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_1).r/2; + sMagicBorderColors[1][1] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_1).g/2; + sMagicBorderColors[1][2] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_1).b/2; - sMagicBorderColors[2][0] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_2).r/2.5; - sMagicBorderColors[2][1] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_2).g/2.5; - sMagicBorderColors[2][2] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_2).b/2.5; + sMagicBorderColors[2][0] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_2).r/2.5; + sMagicBorderColors[2][1] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_2).g/2.5; + sMagicBorderColors[2][2] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_2).b/2.5; - sMagicBorderColors[3][0] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_3).r/3; - sMagicBorderColors[3][1] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_3).g/3; - sMagicBorderColors[3][2] = CVarGetColor24("gCosmetics.Consumable_MagicBorderActive.Value", MagicBorder_3).b/3; + sMagicBorderColors[3][0] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_3).r/3; + sMagicBorderColors[3][1] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_3).g/3; + sMagicBorderColors[3][2] = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorderActive.Value"), MagicBorder_3).b/3; } static s16 sMagicBorderIndexes[] = { 0, 1, 1, 0 }; @@ -3429,15 +3429,15 @@ void Interface_UpdateMagicBar(PlayState* play) { if (gSaveContext.magic <= 0) { gSaveContext.magic = 0; gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger("gCosmetics.Consumable_MagicBorder.Changed", 0)) { - sMagicBorder = CVarGetColor24("gCosmetics.Consumable_MagicBorder.Value", sMagicBorder_ori); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); } else { sMagicBorder = sMagicBorder_ori; } } else if (gSaveContext.magic == gSaveContext.magicTarget) { gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger("gCosmetics.Consumable_MagicBorder.Changed", 0)) { - sMagicBorder = CVarGetColor24("gCosmetics.Consumable_MagicBorder.Value", sMagicBorder_ori); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); } else { sMagicBorder = sMagicBorder_ori; } @@ -3482,8 +3482,8 @@ void Interface_UpdateMagicBar(PlayState* play) { break; case MAGIC_STATE_RESET: - if (CVarGetInteger("gCosmetics.Consumable_MagicBorder.Changed", 0)) { - sMagicBorder = CVarGetColor24("gCosmetics.Consumable_MagicBorder.Value", sMagicBorder_ori); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); } else { sMagicBorder = sMagicBorder_ori; } @@ -3508,8 +3508,8 @@ void Interface_UpdateMagicBar(PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_GLASSMODE_OFF, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); gSaveContext.magicState = MAGIC_STATE_IDLE; - if (CVarGetInteger("gCosmetics.Consumable_MagicBorder.Changed", 0)) { - sMagicBorder = CVarGetColor24("gCosmetics.Consumable_MagicBorder.Value", sMagicBorder_ori); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); } else { sMagicBorder = sMagicBorder_ori; } @@ -3604,11 +3604,11 @@ void Interface_DrawMagicBar(PlayState* play) { Color_RGB8 magicbar_yellow = {250,250,0}; //Magic bar being used Color_RGB8 magicbar_green = {R_MAGIC_FILL_COLOR(0),R_MAGIC_FILL_COLOR(1),R_MAGIC_FILL_COLOR(2)}; //Magic bar fill - if (CVarGetInteger("gCosmetics.Consumable_MagicActive.Changed", 0)) { - magicbar_yellow = CVarGetColor24("gCosmetics.Consumable_MagicActive.Value", magicbar_yellow); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicActive.Changed"), 0)) { + magicbar_yellow = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicActive.Value"), magicbar_yellow); } - if (CVarGetInteger("gCosmetics.Consumable_Magic.Changed", 0)) { - magicbar_green = CVarGetColor24("gCosmetics.Consumable_Magic.Value", magicbar_green); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Magic.Changed"), 0)) { + magicbar_green = CVarGetColor24(CVAR_COSMETIC("Consumable.Magic.Value"), magicbar_green); } OPEN_DISPS(play->state.gfxCtx); @@ -3616,7 +3616,7 @@ void Interface_DrawMagicBar(PlayState* play) { if (gSaveContext.magicLevel != 0) { s16 X_Margins; s16 Y_Margins; - if (CVarGetInteger("gMagicBarUseMargins", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) { X_Margins = Left_HUD_Margin; Y_Margins = (Top_HUD_Margin*-1); } else { @@ -3634,40 +3634,40 @@ void Interface_DrawMagicBar(PlayState* play) { s16 rMagicBarX; s16 PosX_MidEnd; s16 rMagicFillX; - s32 lineLength = CVarGetInteger("gHeartsLineLength", 10); - if (CVarGetInteger("gMagicBarPosType", 0) != 0) { - magicBarY = CVarGetInteger("gMagicBarPosY", 0)+Y_Margins; - if (CVarGetInteger("gMagicBarPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gMagicBarUseMargins", 0) != 0) {X_Margins = Left_HUD_Margin;}; - PosX_Start = OTRGetDimensionFromLeftEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins); - rMagicBarX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins); - PosX_MidEnd = OTRGetDimensionFromLeftEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8); - rMagicFillX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8); - } else if (CVarGetInteger("gMagicBarPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gMagicBarUseMargins", 0) != 0) {X_Margins = Right_HUD_Margin;}; - PosX_Start = OTRGetDimensionFromRightEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins); - rMagicBarX = OTRGetDimensionFromRightEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins); - PosX_MidEnd = OTRGetDimensionFromRightEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8); - rMagicFillX = OTRGetDimensionFromRightEdge(CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8); - } else if (CVarGetInteger("gMagicBarPosType", 0) == 3) {//Anchor None - PosX_Start = CVarGetInteger("gMagicBarPosX", 0)+X_Margins; - rMagicBarX = CVarGetInteger("gMagicBarPosX", 0)+X_Margins; - PosX_MidEnd = CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8; - rMagicFillX = CVarGetInteger("gMagicBarPosX", 0)+X_Margins+8; - } else if (CVarGetInteger("gMagicBarPosType", 0) == 4) {//hidden + s32 lineLength = CVarGetInteger(CVAR_COSMETIC("Hearts.LineLength"), 10); + if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) != 0) { + magicBarY = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosY"), 0)+Y_Margins; + if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) {X_Margins = Left_HUD_Margin;}; + PosX_Start = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); + rMagicBarX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); + PosX_MidEnd = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); + rMagicFillX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); + } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) {X_Margins = Right_HUD_Margin;}; + PosX_Start = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); + rMagicBarX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); + PosX_MidEnd = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); + rMagicFillX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); + } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 3) {//Anchor None + PosX_Start = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins; + rMagicBarX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins; + PosX_MidEnd = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8; + rMagicFillX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8; + } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 4) {//hidden PosX_Start = -9999; rMagicBarX = -9999; PosX_MidEnd = -9999; rMagicFillX = -9999; - } else if (CVarGetInteger("gMagicBarPosType", 0) == 5) {//Anchor To life meter + } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 5) {//Anchor To life meter magicBarY = R_MAGIC_BAR_SMALL_Y-2 + magicDrop*(lineLength == 0 ? 0 : (gSaveContext.healthCapacity-1)/(0x10*lineLength)) + - CVarGetInteger("gMagicBarPosY", 0) + getHealthMeterYOffset(); - s16 xPushover = CVarGetInteger("gMagicBarPosX", 0) + getHealthMeterXOffset() + R_MAGIC_BAR_X-1; + CVarGetInteger(CVAR_COSMETIC("MagicBar.PosY"), 0) + getHealthMeterYOffset(); + s16 xPushover = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_BAR_X-1; PosX_Start = xPushover; rMagicBarX = xPushover; PosX_MidEnd = xPushover+8; - rMagicFillX = CVarGetInteger("gMagicBarPosX", 0) + getHealthMeterXOffset() + R_MAGIC_FILL_X-1; + rMagicFillX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_FILL_X-1; } } else { if ((gSaveContext.healthCapacity-1)/0x10 >= lineLength && lineLength != 0) { @@ -3780,18 +3780,18 @@ void Interface_DrawEnemyHealthBar(TargetContext* targetCtx, PlayState* play) { Color_RGBA8 healthbar_border = { 255, 255, 255, 255 }; s16 healthbar_fillWidth = 64; s16 healthbar_actorOffset = 40; - s32 healthbar_offsetX = CVarGetInteger("gCosmetics.Hud_EnemyHealthBarPosX", 0); - s32 healthbar_offsetY = CVarGetInteger("gCosmetics.Hud_EnemyHealthBarPosY", 0); - s8 anchorType = CVarGetInteger("gCosmetics.Hud_EnemyHealthBarPosType", ENEMYHEALTH_ANCHOR_ACTOR); + s32 healthbar_offsetX = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosX"), 0); + s32 healthbar_offsetY = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosY"), 0); + s8 anchorType = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosType"), ENEMYHEALTH_ANCHOR_ACTOR); - if (CVarGetInteger("gCosmetics.Hud_EnemyHealthBar.Changed", 0)) { - healthbar_red = CVarGetColor("gCosmetics.Hud_EnemyHealthBar.Value", healthbar_red); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Changed"), 0)) { + healthbar_red = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBar.Value"), healthbar_red); } - if (CVarGetInteger("gCosmetics.Hud_EnemyHealthBorder.Changed", 0)) { - healthbar_border = CVarGetColor("gCosmetics.Hud_EnemyHealthBorder.Value", healthbar_border); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBorder.Changed"), 0)) { + healthbar_border = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBorder.Value"), healthbar_border); } - if (CVarGetInteger("gCosmetics.Hud_EnemyHealthBarWidth.Changed", 0)) { - healthbar_fillWidth = CVarGetInteger("gCosmetics.Hud_EnemyHealthBarWidth.Value", healthbar_fillWidth); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed"), 0)) { + healthbar_fillWidth = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value"), healthbar_fillWidth); } OPEN_DISPS(play->state.gfxCtx); @@ -3971,37 +3971,37 @@ void Interface_DrawItemButtons(PlayState* play) { s16 height; Color_RGB8 bButtonColor = { 0, 150, 0 }; - if (CVarGetInteger("gCosmetics.Hud_BButton.Changed", 0)) { - bButtonColor = CVarGetColor24("gCosmetics.Hud_BButton.Value", bButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.Changed"), 0)) { + bButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.BButton.Value"), bButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { bButtonColor = (Color_RGB8){ 255, 30, 30 }; } Color_RGB8 cButtonsColor = { 255, 160, 0 }; - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - cButtonsColor = CVarGetColor24("gCosmetics.Hud_CButtons.Value", cButtonsColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); } Color_RGB8 cUpButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); } Color_RGB8 cDownButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); } Color_RGB8 cLeftButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); } Color_RGB8 cRightButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); } Color_RGB8 startButtonColor = { 200, 0, 0 }; - if (CVarGetInteger("gCosmetics.Hud_StartButton.Changed", 0)) { - startButtonColor = CVarGetColor24("gCosmetics.Hud_StartButton.Value", startButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.Changed"), 0)) { + startButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.StartButton.Value"), startButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { startButtonColor = (Color_RGB8){ 120, 120, 120 }; } @@ -4010,12 +4010,12 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_BtnB; s16 BBtn_Size = 32; int BBtnScaled = BBtn_Size * 0.95f; - if (CVarGetInteger("gBBtnPosType", 0) != 0) { - BBtnScaled = BBtn_Size * CVarGetFloat("gBBtnScale", 0.95f); + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { + BBtnScaled = BBtn_Size * CVarGetFloat(CVAR_COSMETIC("BButton.Scale"), 0.95f); } int BBtn_factor = (1 << 10) * BBtn_Size / BBtnScaled; - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; @@ -4025,17 +4025,17 @@ void Interface_DrawItemButtons(PlayState* play) { s16 PosY_BtnB_ori = R_ITEM_BTN_Y(0)+Y_Margins_BtnB; s16 PosX_BtnB; s16 PosY_BtnB; - if (CVarGetInteger("gBBtnPosType", 0) != 0) { - PosY_BtnB = CVarGetInteger("gBBtnPosY", 0)+Y_Margins_BtnB; - if (CVarGetInteger("gBBtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - PosX_BtnB = OTRGetDimensionFromLeftEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB); - } else if (CVarGetInteger("gBBtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - PosX_BtnB = OTRGetDimensionFromRightEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB); - } else if (CVarGetInteger("gBBtnPosType", 0) == 3) {//Anchor None - PosX_BtnB = CVarGetInteger("gBBtnPosX", 0); - } else if (CVarGetInteger("gBBtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { + PosY_BtnB = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB; + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + PosX_BtnB = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + PosX_BtnB = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None + PosX_BtnB = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden PosX_BtnB = -9999; } } else { @@ -4045,8 +4045,8 @@ void Interface_DrawItemButtons(PlayState* play) { //Start Button s16 X_Margins_StartBtn; s16 Y_Margins_StartBtn; - if (CVarGetInteger("gStartBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gStartBtnPosType", 0) == 0) { + if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 0) { X_Margins_StartBtn = Right_HUD_Margin; }; Y_Margins_StartBtn = Top_HUD_Margin*-1; @@ -4057,8 +4057,8 @@ void Interface_DrawItemButtons(PlayState* play) { s16 StartBtn_Icon_H = 32; s16 StartBtn_Icon_W = 32; float Start_BTN_Scale = 0.75f; - if (CVarGetInteger("gStartBtnPosType", 0) != 0) { - Start_BTN_Scale = CVarGetFloat("gStartBtnScale", 0.75f); + if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) != 0) { + Start_BTN_Scale = CVarGetFloat(CVAR_COSMETIC("StartButton.Scale"), 0.75f); } int StartBTN_H_Scaled = StartBtn_Icon_H * Start_BTN_Scale; int StartBTN_W_Scaled = StartBtn_Icon_W * Start_BTN_Scale; @@ -4070,17 +4070,17 @@ void Interface_DrawItemButtons(PlayState* play) { s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT(); s16 PosX_StartBtn; s16 PosY_StartBtn; - if (CVarGetInteger("gStartBtnPosType", 0) != 0) { - PosY_StartBtn = CVarGetInteger("gStartBtnPosY", 0)-(Start_BTN_Scale*13)+Y_Margins_StartBtn; - if (CVarGetInteger("gStartBtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;}; - PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVarGetInteger("gStartBtnPosX", 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); - } else if (CVarGetInteger("gStartBtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;}; - PosX_StartBtn = OTRGetDimensionFromRightEdge(CVarGetInteger("gStartBtnPosX", 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); - } else if (CVarGetInteger("gStartBtnPosType", 0) == 3) {//Anchor None - PosX_StartBtn = CVarGetInteger("gStartBtnPosX", 0); - } else if (CVarGetInteger("gStartBtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) != 0) { + PosY_StartBtn = CVarGetInteger(CVAR_COSMETIC("StartButton.PosY"), 0)-(Start_BTN_Scale*13)+Y_Margins_StartBtn; + if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;}; + PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); + } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;}; + PosX_StartBtn = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); + } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 3) {//Anchor None + PosX_StartBtn = CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 4) {//Hidden PosX_StartBtn = -9999; } } else { @@ -4100,29 +4100,29 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_CR; s16 Y_Margins_CU; s16 Y_Margins_CD; - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnLPosType", 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnRPosType", 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger("gCBtnUUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnUPosType", 0) == 0) {X_Margins_CU = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 0) {X_Margins_CU = Right_HUD_Margin;}; Y_Margins_CU = (Top_HUD_Margin*-1); } else { X_Margins_CU = 0; Y_Margins_CU = 0; } - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnDPosType", 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4140,23 +4140,23 @@ void Interface_DrawItemButtons(PlayState* play) { s16 C_Down_BTN_Pos[2]; //C button Left s16 C_Left_BTN_Size = 32; - float CLeftScale = CVarGetFloat("gCBtnLScale", 0.87f); + float CLeftScale = CVarGetFloat(CVAR_COSMETIC("CLeftButton.Scale"), 0.87f); int CLeftScaled = C_Left_BTN_Size * 0.87f; - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { CLeftScaled = C_Left_BTN_Size * CLeftScale; } int CLeft_factor = (1 << 10) * C_Left_BTN_Size / CLeftScaled; - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { - C_Left_BTN_Pos[1] = CVarGetInteger("gCBtnLPosY", 0)+Y_Margins_CL; - if (CVarGetInteger("gCBtnLPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - C_Left_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - C_Left_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 3) {//Anchor None - C_Left_BTN_Pos[0] = CVarGetInteger("gCBtnLPosX", 0); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + C_Left_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + C_Left_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + C_Left_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None + C_Left_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden C_Left_BTN_Pos[0] = -9999; } } else { @@ -4165,23 +4165,23 @@ void Interface_DrawItemButtons(PlayState* play) { } //C button Right s16 C_Right_BTN_Size = 32; - float CRightScale = CVarGetFloat("gCBtnRScale", 0.87f); + float CRightScale = CVarGetFloat(CVAR_COSMETIC("CRightButton.Scale"), 0.87f); int CRightScaled = C_Right_BTN_Size * 0.87f; - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { CRightScaled = C_Right_BTN_Size * CRightScale; } int CRight_factor = (1 << 10) * C_Right_BTN_Size / CRightScaled; - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { - C_Right_BTN_Pos[1] = CVarGetInteger("gCBtnRPosY", 0)+Y_Margins_CR; - if (CVarGetInteger("gCBtnRPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - C_Right_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - C_Right_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 3) {//Anchor None - C_Right_BTN_Pos[0] = CVarGetInteger("gCBtnRPosX", 0); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + C_Right_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + C_Right_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + C_Right_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None + C_Right_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden C_Right_BTN_Pos[0] = -9999; } } else { @@ -4191,22 +4191,22 @@ void Interface_DrawItemButtons(PlayState* play) { //C Button Up s16 C_Up_BTN_Size = 32; int CUpScaled = C_Up_BTN_Size * 0.5f; - float CUpScale = CVarGetFloat("gCBtnUScale", 0.5f); - if (CVarGetInteger("gCBtnUPosType", 0) != 0) { + float CUpScale = CVarGetFloat(CVAR_COSMETIC("CUpButton.Scale"), 0.5f); + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) != 0) { CUpScaled = C_Up_BTN_Size * CUpScale; } int CUp_factor = (1 << 10) * C_Up_BTN_Size / CUpScaled; - if (CVarGetInteger("gCBtnUPosType", 0) != 0) { - C_Up_BTN_Pos[1] = CVarGetInteger("gCBtnUPosY", 0)+Y_Margins_CU; - if (CVarGetInteger("gCBtnUPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnUUseMargins", 0) != 0) {X_Margins_CU = Left_HUD_Margin;}; - C_Up_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnUPosX", 0)+X_Margins_CU); - } else if (CVarGetInteger("gCBtnUPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnUUseMargins", 0) != 0) {X_Margins_CU = Right_HUD_Margin;}; - C_Up_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnUPosX", 0)+X_Margins_CU); - } else if (CVarGetInteger("gCBtnUPosType", 0) == 3) {//Anchor None - C_Up_BTN_Pos[0] = CVarGetInteger("gCBtnUPosX", 0); - } else if (CVarGetInteger("gCBtnUPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) != 0) { + C_Up_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CUpButton.PosY"), 0)+Y_Margins_CU; + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Left_HUD_Margin;}; + C_Up_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0)+X_Margins_CU); + } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Right_HUD_Margin;}; + C_Up_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0)+X_Margins_CU); + } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 3) {//Anchor None + C_Up_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 4) {//Hidden C_Up_BTN_Pos[0] = -9999; } } else { @@ -4215,24 +4215,24 @@ void Interface_DrawItemButtons(PlayState* play) { } //C Button down s16 C_Down_BTN_Size = 32; - float CDownScale = CVarGetFloat("gCBtnDScale", 0.87f); - if (CVarGetInteger("gCBtnDPosType", 0) == 0) { + float CDownScale = CVarGetFloat(CVAR_COSMETIC("CDownButton.Scale"), 0.87f); + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) { CDownScale = 0.87f; } int CDownScaled = C_Down_BTN_Size * CDownScale; int CDown_factor = (1 << 10) * C_Down_BTN_Size / CDownScaled; int PositionAdjustment = CDownScaled/2; - if (CVarGetInteger("gCBtnDPosType", 0) != 0) { - C_Down_BTN_Pos[1] = CVarGetInteger("gCBtnDPosY", 0)+Y_Margins_CD; - if (CVarGetInteger("gCBtnDPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - C_Down_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - C_Down_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 3) {//Anchor None - C_Down_BTN_Pos[0] = CVarGetInteger("gCBtnDPosX", 0); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { + C_Down_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + C_Down_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + C_Down_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None + C_Down_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden C_Down_BTN_Pos[0] = -9999; } } else { @@ -4360,22 +4360,22 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_CL; s16 Y_Margins_CR; s16 Y_Margins_CD; - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnLPosType", 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnRPosType", 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnDPosType", 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4393,17 +4393,17 @@ void Interface_DrawItemButtons(PlayState* play) { }; s16 ItemIconPos[3][2]; //(X,Y) //C button Left - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger("gCBtnLPosY", 0)+Y_Margins_CL; - if (CVarGetInteger("gCBtnLPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger("gCBtnLPosX", 0); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4411,17 +4411,17 @@ void Interface_DrawItemButtons(PlayState* play) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C Button down - if (CVarGetInteger("gCBtnDPosType", 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger("gCBtnDPosY", 0)+Y_Margins_CD; - if (CVarGetInteger("gCBtnDPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger("gCBtnDPosX", 0); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4429,17 +4429,17 @@ void Interface_DrawItemButtons(PlayState* play) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C button Right - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger("gCBtnRPosY", 0)+Y_Margins_CR; - if (CVarGetInteger("gCBtnRPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger("gCBtnRPosX", 0); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4489,29 +4489,29 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnLPosType", 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnRPosType", 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnDPosType", 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4591,17 +4591,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[7][1] = ItemIconPos_ori[7][1]; } //B Button - if (CVarGetInteger("gBBtnPosType", 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger("gBBtnPosY", 0)+Y_Margins_BtnB; - if (CVarGetInteger("gBBtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB); - } else if (CVarGetInteger("gBBtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB); - } else if (CVarGetInteger("gBBtnPosType", 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger("gBBtnPosX", 0); - } else if (CVarGetInteger("gBBtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB; + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4609,17 +4609,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C button Left - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger("gCBtnLPosY", 0)+Y_Margins_CL; - if (CVarGetInteger("gCBtnLPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger("gCBtnLPosX", 0); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4627,17 +4627,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C Button down - if (CVarGetInteger("gCBtnDPosType", 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger("gCBtnDPosY", 0)+Y_Margins_CD; - if (CVarGetInteger("gCBtnDPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger("gCBtnDPosX", 0); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4645,17 +4645,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[2][1] = ItemIconPos_ori[2][1]; } //C button Right - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { - ItemIconPos[3][1] = CVarGetInteger("gCBtnRPosY", 0)+Y_Margins_CR; - if (CVarGetInteger("gCBtnRPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 3) {//Anchor None - ItemIconPos[3][0] = CVarGetInteger("gCBtnRPosX", 0); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[3][0] = -9999; } } else { @@ -4698,29 +4698,29 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnLPosType", 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnRPosType", 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnDPosType", 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4792,17 +4792,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { //B Button s16 PosX_adjust = 1; s16 PosY_adjust = 17; - if (CVarGetInteger("gBBtnPosType", 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger("gBBtnPosY", 0)+Y_Margins_BtnB+PosY_adjust; - if (CVarGetInteger("gBBtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB+PosX_adjust); - } else if (CVarGetInteger("gBBtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB+PosX_adjust); - } else if (CVarGetInteger("gBBtnPosType", 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger("gBBtnPosX", 0)+PosX_adjust; - } else if (CVarGetInteger("gBBtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4810,17 +4810,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C button Left - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger("gCBtnLPosY", 0)+Y_Margins_CL+PosY_adjust; - if (CVarGetInteger("gCBtnLPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL+PosX_adjust); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL+PosX_adjust); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger("gCBtnLPosX", 0)+PosX_adjust; - } else if (CVarGetInteger("gCBtnLPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4828,17 +4828,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C Button down - if (CVarGetInteger("gCBtnDPosType", 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger("gCBtnDPosY", 0)+Y_Margins_CD+PosY_adjust; - if (CVarGetInteger("gCBtnDPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD+PosX_adjust); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD+PosX_adjust); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger("gCBtnDPosX", 0)+PosX_adjust; - } else if (CVarGetInteger("gCBtnDPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4846,17 +4846,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[2][1] = ItemIconPos_ori[2][1]; } //C button Right - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { - ItemIconPos[3][1] = CVarGetInteger("gCBtnRPosY", 0)+Y_Margins_CR+PosY_adjust; - if (CVarGetInteger("gCBtnRPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR+PosX_adjust); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR+PosX_adjust); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 3) {//Anchor None - ItemIconPos[3][0] = CVarGetInteger("gCBtnRPosX", 0)+PosX_adjust; - } else if (CVarGetInteger("gCBtnRPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[3][0] = -9999; } } else { @@ -5085,19 +5085,19 @@ void Interface_Draw(PlayState* play) { Color_RGB8 rColor; Color_RGB8 keyCountColor = { 200, 230, 255 }; - if (CVarGetInteger("gCosmetics.Hud_KeyCount.Changed", 0)) { - keyCountColor = CVarGetColor24("gCosmetics.Hud_KeyCount.Value", keyCountColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.KeyCount.Changed"), 0)) { + keyCountColor = CVarGetColor24(CVAR_COSMETIC("HUD.KeyCount.Value"), keyCountColor); } Color_RGB8 dPadColor = { 255, 255, 255 }; - if (CVarGetInteger("gCosmetics.Hud_Dpad.Changed", 0)) { - dPadColor = CVarGetColor24("gCosmetics.Hud_Dpad.Value", dPadColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.Changed"), 0)) { + dPadColor = CVarGetColor24(CVAR_COSMETIC("HUD.Dpad.Value"), dPadColor); } Color_RGB8 aButtonColor = { 90, 90, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 0, 200, 50 }; } @@ -5146,37 +5146,37 @@ void Interface_Draw(PlayState* play) { if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { switch (CUR_UPG_VALUE(UPG_WALLET)) { case 0: - if (CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0)) { - rColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", rupeeWalletColors[0]); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); } else { rColor = rupeeWalletColors[0]; } break; case 1: - if (CVarGetInteger("gCosmetics.Consumable_BlueRupee.Changed", 0)) { - rColor = CVarGetColor24("gCosmetics.Consumable_BlueRupee.Value", rupeeWalletColors[1]); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), rupeeWalletColors[1]); } else { rColor = rupeeWalletColors[1]; } break; case 2: - if (CVarGetInteger("gCosmetics.Consumable_RedRupee.Changed", 0)) { - rColor = CVarGetColor24("gCosmetics.Consumable_RedRupee.Value", rupeeWalletColors[2]); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), rupeeWalletColors[2]); } else { rColor = rupeeWalletColors[2]; } break; case 3: - if (CVarGetInteger("gCosmetics.Consumable_PurpleRupee.Changed", 0)) { - rColor = CVarGetColor24("gCosmetics.Consumable_PurpleRupee.Value", rupeeWalletColors[3]); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), rupeeWalletColors[3]); } else { rColor = rupeeWalletColors[3]; } break; } } else { - if (CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", rupeeWalletColors)) { - rColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", rupeeWalletColors[0]); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), rupeeWalletColors)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); } else { rColor = rupeeWalletColors[0]; } @@ -5421,24 +5421,24 @@ void Interface_Draw(PlayState* play) { s16 BbtnPosY; s16 X_Margins_BtnB_label; s16 Y_Margins_BtnB_label; - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gBBtnPosType", 0) == 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; Y_Margins_BtnB_label = (Top_HUD_Margin*-1); } else { X_Margins_BtnB_label = 0; Y_Margins_BtnB_label = 0; } - if (CVarGetInteger("gBBtnPosType", 0) != 0) { - BbtnPosY = CVarGetInteger("gBBtnPosY", 0)+Y_Margins_BtnB_label+PosY_adjust; - if (CVarGetInteger("gBBtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB_label = Left_HUD_Margin;}; - BbtnPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB_label+PosX_adjust); - } else if (CVarGetInteger("gBBtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; - BbtnPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gBBtnPosX", 0)+X_Margins_BtnB_label+PosX_adjust); - } else if (CVarGetInteger("gBBtnPosType", 0) == 3) {//Anchor None - BbtnPosX = CVarGetInteger("gBBtnPosX", 0)+PosX_adjust; - } else if (CVarGetInteger("gBBtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { + BbtnPosY = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB_label+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Left_HUD_Margin;}; + BbtnPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; + BbtnPosX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None + BbtnPosX = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden BbtnPosX = -9999; } } else { @@ -5597,7 +5597,7 @@ void Interface_Draw(PlayState* play) { Gfx_SetupDL_42Overlay(play->state.gfxCtx); s16 X_Margins_BtnA; s16 Y_Margins_BtnA; - if (CVarGetInteger("gABtnUseMargins", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) { X_Margins_BtnA = Right_HUD_Margin; Y_Margins_BtnA = (Top_HUD_Margin*-1); } else { @@ -5612,21 +5612,21 @@ void Interface_Draw(PlayState* play) { s16 PosY_BtnA; s16 rAIconX; s16 rAIconY; - if (CVarGetInteger("gABtnPosType", 0) != 0) { - PosY_BtnA = CVarGetInteger("gABtnPosY", 0)+Y_Margins_BtnA; + if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) != 0) { + PosY_BtnA = CVarGetInteger(CVAR_COSMETIC("AButton.PosY"), 0)+Y_Margins_BtnA; rAIconY = 98.0f - PosY_BtnA; - if (CVarGetInteger("gABtnPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gABtnUseMargins", 0) != 0) {X_Margins_BtnA = Left_HUD_Margin;}; - PosX_BtnA = OTRGetDimensionFromLeftEdge(CVarGetInteger("gABtnPosX", 0)+X_Margins_BtnA); - rAIconX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gABtnPosX", 0)+X_Margins_BtnA); - } else if (CVarGetInteger("gABtnPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gABtnUseMargins", 0) != 0) {X_Margins_BtnA = Right_HUD_Margin;}; - PosX_BtnA = OTRGetDimensionFromRightEdge(CVarGetInteger("gABtnPosX", 0)+X_Margins_BtnA); - rAIconX= OTRGetDimensionFromRightEdge(CVarGetInteger("gABtnPosX", 0)+X_Margins_BtnA); - } else if (CVarGetInteger("gABtnPosType", 0) == 3) {//Anchor None - PosX_BtnA = CVarGetInteger("gABtnPosX", 0); - rAIconX = CVarGetInteger("gABtnPosX", 0); - } else if (CVarGetInteger("gABtnPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Left_HUD_Margin;}; + PosX_BtnA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); + rAIconX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); + } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Right_HUD_Margin;}; + PosX_BtnA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); + rAIconX= OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); + } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 3) {//Anchor None + PosX_BtnA = CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0); + rAIconX = CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 4) {//Hidden PosX_BtnA = -9999; rAIconX = -9999; } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 8bcb6ec7c..c38dc8ca8 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1068,14 +1068,14 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL Color_RGB8 sTemp; color = &sTunicColors[tunic]; - if (tunic == PLAYER_TUNIC_KOKIRI && CVarGetInteger("gCosmetics.Link_KokiriTunic.Changed", 0)) { - sTemp = CVarGetColor24("gCosmetics.Link_KokiriTunic.Value", sTunicColors[PLAYER_TUNIC_KOKIRI]); + if (tunic == PLAYER_TUNIC_KOKIRI && CVarGetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 0)) { + sTemp = CVarGetColor24(CVAR_COSMETIC("Link.KokiriTunic.Value"), sTunicColors[PLAYER_TUNIC_KOKIRI]); color = &sTemp; - } else if (tunic == PLAYER_TUNIC_GORON && CVarGetInteger("gCosmetics.Link_GoronTunic.Changed", 0)) { - sTemp = CVarGetColor24("gCosmetics.Link_GoronTunic.Value", sTunicColors[PLAYER_TUNIC_GORON]); + } else if (tunic == PLAYER_TUNIC_GORON && CVarGetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 0)) { + sTemp = CVarGetColor24(CVAR_COSMETIC("Link.GoronTunic.Value"), sTunicColors[PLAYER_TUNIC_GORON]); color = &sTemp; - } else if (tunic == PLAYER_TUNIC_ZORA && CVarGetInteger("gCosmetics.Link_ZoraTunic.Changed", 0)) { - sTemp = CVarGetColor24("gCosmetics.Link_ZoraTunic.Value", sTunicColors[PLAYER_TUNIC_ZORA]); + } else if (tunic == PLAYER_TUNIC_ZORA && CVarGetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 0)) { + sTemp = CVarGetColor24(CVAR_COSMETIC("Link.ZoraTunic.Value"), sTunicColors[PLAYER_TUNIC_ZORA]); color = &sTemp; } @@ -1100,11 +1100,11 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL gDPPipeSync(POLY_OPA_DISP++); color = &sGauntletColors[strengthUpgrade - 2]; - if (strengthUpgrade == PLAYER_STR_SILVER_G && CVarGetInteger("gCosmetics.Gloves_SilverGauntlets.Changed", 0)) { - sTemp = CVarGetColor24("gCosmetics.Gloves_SilverGauntlets.Value", sGauntletColors[PLAYER_STR_SILVER_G - 2]); + if (strengthUpgrade == PLAYER_STR_SILVER_G && CVarGetInteger(CVAR_COSMETIC("Gloves.SilverGauntlets.Changed"), 0)) { + sTemp = CVarGetColor24(CVAR_COSMETIC("Gloves.SilverGauntlets.Value"), sGauntletColors[PLAYER_STR_SILVER_G - 2]); color = &sTemp; - } else if (strengthUpgrade == PLAYER_STR_GOLD_G && CVarGetInteger("gCosmetics.Gloves_GoldenGauntlets.Changed", 0)) { - sTemp = CVarGetColor24("gCosmetics.Gloves_GoldenGauntlets.Value", sGauntletColors[PLAYER_STR_GOLD_G - 2]); + } else if (strengthUpgrade == PLAYER_STR_GOLD_G && CVarGetInteger(CVAR_COSMETIC("Gloves.GoldenGauntlets.Changed"), 0)) { + sTemp = CVarGetColor24(CVAR_COSMETIC("Gloves.GoldenGauntlets.Value"), sGauntletColors[PLAYER_STR_GOLD_G - 2]); color = &sTemp; } gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0); @@ -1310,8 +1310,8 @@ s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** } if (limbIndex == PLAYER_LIMB_HEAD) { - if (CVarGetInteger("gCosmetics.Link_HeadScale.Changed", 0)) { - f32 scale = CVarGetFloat("gCosmetics.Link_HeadScale.Value", 1.0f); + if (CVarGetInteger(CVAR_COSMETIC("Link.HeadScale.Changed"), 0)) { + f32 scale = CVarGetFloat(CVAR_COSMETIC("Link.HeadScale.Value"), 1.0f); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); if (scale > 1.2f) { Matrix_Translate(-((LINK_IS_ADULT ? 320.0f : 200.0f) * scale), 0.0f, 0.0f, MTXMODE_APPLY); @@ -1323,8 +1323,8 @@ s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** rot->y -= this->unk_6B8; rot->z += this->unk_6B6; } else if (limbIndex == PLAYER_LIMB_L_HAND) { - if (CVarGetInteger("gCosmetics.Link_SwordScale.Changed", 0)) { - f32 scale = CVarGetFloat("gCosmetics.Link_SwordScale.Value", 1.0f); + if (CVarGetInteger(CVAR_COSMETIC("Link.SwordScale.Changed"), 0)) { + f32 scale = CVarGetFloat(CVAR_COSMETIC("Link.SwordScale.Value"), 1.0f); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); Matrix_Translate(-((LINK_IS_ADULT ? 320.0f : 200.0f) * scale), 0.0f, 0.0f, MTXMODE_APPLY); } @@ -1684,11 +1684,11 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && CVarGetInteger(CVAR_ENHANCEMENT("HookshotableReticle"), false)) { const Color_RGBA8 defaultColor = { .r = 0, .g = 255, .b = 0, .a = 255 }; - const Color_RGBA8 color = CVarGetColor("gCosmetics.HookshotReticle_Target.Value", defaultColor); + const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.Target.Value"), defaultColor); gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a); } else { const Color_RGBA8 defaultColor = { .r = 255, .g = 0, .b = 0, .a = 255 }; - const Color_RGBA8 color = CVarGetColor("gCosmetics.HookshotReticle_NonTarget.Value", defaultColor); + const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.NonTarget.Value"), defaultColor); gDPSetPrimColor(WORLD_OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a); } gSPVertex(WORLD_OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0); diff --git a/soh/src/overlays/actors/ovl_Arrow_Fire/z_arrow_fire.c b/soh/src/overlays/actors/ovl_Arrow_Fire/z_arrow_fire.c index d257a7fd9..984bf8ecd 100644 --- a/soh/src/overlays/actors/ovl_Arrow_Fire/z_arrow_fire.c +++ b/soh/src/overlays/actors/ovl_Arrow_Fire/z_arrow_fire.c @@ -196,12 +196,12 @@ void ArrowFire_Draw(Actor* thisx, PlayState* play2) { Actor* tranform; Color_RGB8 primaryColor = {255, 200, 0}; - if (CVarGetInteger("gCosmetics.Arrows_FirePrimary.Changed", 0)) { - primaryColor = CVarGetColor24("gCosmetics.Arrows_FirePrimary.Value", primaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.FirePrimary.Changed"), 0)) { + primaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.FirePrimary.Value"), primaryColor); } Color_RGB8 secondaryColor = {255, 0, 0}; - if (CVarGetInteger("gCosmetics.Arrows_FireSecondary.Changed", 0)) { - secondaryColor = CVarGetColor24("gCosmetics.Arrows_FireSecondary.Value", secondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.FireSecondary.Changed"), 0)) { + secondaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.FireSecondary.Value"), secondaryColor); } stateFrames = play->state.frames; diff --git a/soh/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c b/soh/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c index 94d7ecabc..64ea63131 100644 --- a/soh/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c +++ b/soh/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c @@ -197,12 +197,12 @@ void ArrowIce_Draw(Actor* thisx, PlayState* play) { EnArrow* arrow = (EnArrow*)this->actor.parent; Color_RGB8 primaryColor = {170, 255, 255}; - if (CVarGetInteger("gCosmetics.Arrows_IcePrimary.Changed", 0)) { - primaryColor = CVarGetColor24("gCosmetics.Arrows_IcePrimary.Value", primaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.IcePrimary.Changed"), 0)) { + primaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.IcePrimary.Value"), primaryColor); } Color_RGB8 secondaryColor = {0, 0, 255}; - if (CVarGetInteger("gCosmetics.Arrows_IceSecondary.Changed", 0)) { - secondaryColor = CVarGetColor24("gCosmetics.Arrows_IceSecondary.Value", secondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.IceSecondary.Changed"), 0)) { + secondaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.IceSecondary.Value"), secondaryColor); } if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) { diff --git a/soh/src/overlays/actors/ovl_Arrow_Light/z_arrow_light.c b/soh/src/overlays/actors/ovl_Arrow_Light/z_arrow_light.c index 9ddfb96a6..f42a0bcef 100644 --- a/soh/src/overlays/actors/ovl_Arrow_Light/z_arrow_light.c +++ b/soh/src/overlays/actors/ovl_Arrow_Light/z_arrow_light.c @@ -195,12 +195,12 @@ void ArrowLight_Draw(Actor* thisx, PlayState* play) { Actor* tranform; Color_RGB8 primaryColor = {255, 255, 170}; - if (CVarGetInteger("gCosmetics.Arrows_LightPrimary.Changed", 0)) { - primaryColor = CVarGetColor24("gCosmetics.Arrows_LightPrimary.Value", primaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.LightPrimary.Changed"), 0)) { + primaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.LightPrimary.Value"), primaryColor); } Color_RGB8 secondaryColor = {255, 255, 0}; - if (CVarGetInteger("gCosmetics.Arrows_LightSecondary.Changed", 0)) { - secondaryColor = CVarGetColor24("gCosmetics.Arrows_LightSecondary.Value", secondaryColor); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.LightSecondary.Changed"), 0)) { + secondaryColor = CVarGetColor24(CVAR_COSMETIC("Arrows.LightSecondary.Value"), secondaryColor); } if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) { diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c index 2b2e1c0f7..4d0353fcf 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Shelter/z_bg_ice_shelter.c @@ -461,8 +461,8 @@ void BgIceShelter_Draw(Actor* thisx, PlayState* play2) { break; } - if (CVarGetInteger("gCosmetics.World_RedIce.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.World_RedIce.Value", (Color_RGB8){ 255, 0, 0}); + if (CVarGetInteger(CVAR_COSMETIC("World.RedIce.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("World.RedIce.Value"), (Color_RGB8){ 255, 0, 0}); gDPSetEnvColor(POLY_XLU_DISP++, color.r, color.g, color.b, this->alpha); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, this->alpha); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot01_Fusya/z_bg_spot01_fusya.c b/soh/src/overlays/actors/ovl_Bg_Spot01_Fusya/z_bg_spot01_fusya.c index a697bd666..3a18e3650 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot01_Fusya/z_bg_spot01_fusya.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot01_Fusya/z_bg_spot01_fusya.c @@ -60,8 +60,8 @@ void func_808AAA50(BgSpot01Fusya* this, PlayState* play) { f32 temp; Actor* thisx = &this->actor; - if (CVarGetInteger("gCosmetics.Kak_Windmill_Speed.Changed", 0)) { - this->unk_158 = CVarGetFloat("gCosmetics.Kak_Windmill_Speed.Value", 100.0f); + if (CVarGetInteger(CVAR_COSMETIC("Kak.Windmill_Speed.Changed"), 0)) { + this->unk_158 = CVarGetFloat(CVAR_COSMETIC("Kak.Windmill_Speed.Value"), 100.0f); } else { this->unk_158 = 100.0f; } diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index 8b1d191a6..c13833d6d 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -84,46 +84,46 @@ void EnArrow_Init(Actor* thisx, PlayState* play) { }; EnArrow* this = (EnArrow*)thisx; - if (CVarGetInteger("gCosmetics.Arrows_NormalPrimary.Changed", 0)) { - blureNormal.altEnvColor = CVarGetColor("gCosmetics.Arrows_NormalPrimary.Value", (Color_RGBA8){ 0, 150, 0, 0 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.NormalPrimary.Changed"), 0)) { + blureNormal.altEnvColor = CVarGetColor(CVAR_COSMETIC("Arrows.NormalPrimary.Value"), (Color_RGBA8){ 0, 150, 0, 0 }); } else { blureNormal.altEnvColor = (Color_RGBA8){ 0, 150, 0, 0 }; } - if (CVarGetInteger("gCosmetics.Arrows_NormalSecondary.Changed", 0)) { - blureNormal.altPrimColor = CVarGetColor("gCosmetics.Arrows_NormalSecondary.Value", (Color_RGBA8){ 255, 255, 170, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.NormalSecondary.Changed"), 0)) { + blureNormal.altPrimColor = CVarGetColor(CVAR_COSMETIC("Arrows.NormalSecondary.Value"), (Color_RGBA8){ 255, 255, 170, 255 }); } else { blureNormal.altPrimColor = (Color_RGBA8){ 255, 255, 170, 255 }; } - if (CVarGetInteger("gCosmetics.Arrows_FirePrimary.Changed", 0)) { - blureFire.altEnvColor = CVarGetColor("gCosmetics.Arrows_FirePrimary.Value", (Color_RGBA8){ 255, 200, 0, 0 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.FirePrimary.Changed"), 0)) { + blureFire.altEnvColor = CVarGetColor(CVAR_COSMETIC("Arrows.FirePrimary.Value"), (Color_RGBA8){ 255, 200, 0, 0 }); } else { blureFire.altEnvColor = (Color_RGBA8){ 255, 200, 0, 0 }; } - if (CVarGetInteger("gCosmetics.Arrows_FireSecondary.Changed", 0)) { - blureFire.altPrimColor = CVarGetColor("gCosmetics.Arrows_FireSecondary.Value", (Color_RGBA8){ 255, 0, 0, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.FireSecondary.Changed"), 0)) { + blureFire.altPrimColor = CVarGetColor(CVAR_COSMETIC("Arrows.FireSecondary.Value"), (Color_RGBA8){ 255, 0, 0, 255 }); } else { blureFire.altPrimColor = (Color_RGBA8){ 255, 0, 0, 255 }; } - if (CVarGetInteger("gCosmetics.Arrows_IcePrimary.Changed", 0)) { - blureIce.altEnvColor = CVarGetColor("gCosmetics.Arrows_IcePrimary.Value", (Color_RGBA8){ 0, 0, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.IcePrimary.Changed"), 0)) { + blureIce.altEnvColor = CVarGetColor(CVAR_COSMETIC("Arrows.IcePrimary.Value"), (Color_RGBA8){ 0, 0, 255, 255 }); } else { blureIce.altEnvColor = (Color_RGBA8){ 0, 0, 255, 255 }; } - if (CVarGetInteger("gCosmetics.Arrows_IceSecondary.Changed", 0)) { - blureIce.altPrimColor = CVarGetColor("gCosmetics.Arrows_IceSecondary.Value", (Color_RGBA8){ 170, 255, 255, 0 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.IceSecondary.Changed"), 0)) { + blureIce.altPrimColor = CVarGetColor(CVAR_COSMETIC("Arrows.IceSecondary.Value"), (Color_RGBA8){ 170, 255, 255, 0 }); } else { blureIce.altPrimColor = (Color_RGBA8){ 170, 255, 255, 0 }; } - if (CVarGetInteger("gCosmetics.Arrows_LightPrimary.Changed", 0)) { - blureLight.altEnvColor = CVarGetColor("gCosmetics.Arrows_LightPrimary.Value", (Color_RGBA8){ 255, 255, 0, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.LightPrimary.Changed"), 0)) { + blureLight.altEnvColor = CVarGetColor(CVAR_COSMETIC("Arrows.LightPrimary.Value"), (Color_RGBA8){ 255, 255, 0, 255 }); } else { blureLight.altEnvColor = (Color_RGBA8){ 255, 255, 0, 255 }; } - if (CVarGetInteger("gCosmetics.Arrows_LightSecondary.Changed", 0)) { - blureLight.altPrimColor = CVarGetColor("gCosmetics.Arrows_LightSecondary.Value", (Color_RGBA8){ 255, 255, 170, 0 }); + if (CVarGetInteger(CVAR_COSMETIC("Arrows.LightSecondary.Changed"), 0)) { + blureLight.altPrimColor = CVarGetColor(CVAR_COSMETIC("Arrows.LightSecondary.Value"), (Color_RGBA8){ 255, 255, 170, 0 }); } else { blureLight.altPrimColor = (Color_RGBA8){ 255, 255, 170, 0 }; } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index 4fcaa88e2..40ba64503 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -515,8 +515,8 @@ void EnBomChu_Draw(Actor* thisx, PlayState* play) { colorIntensity = blinkTime / (f32)blinkHalfPeriod; - if (CVarGetInteger("gCosmetics.Equipment_ChuBody.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.Equipment_ChuBody.Value", (Color_RGB8){ 209.0f, 34.0f, -35.0f }); + if (CVarGetInteger(CVAR_COSMETIC("Equipment.ChuBody.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("Equipment.ChuBody.Value"), (Color_RGB8){ 209.0f, 34.0f, -35.0f }); gDPSetEnvColor(POLY_OPA_DISP++, (colorIntensity * color.r), (colorIntensity * color.g), (colorIntensity * color.b), 255); } else { diff --git a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c index 2c49accfe..b226d00f2 100644 --- a/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c +++ b/soh/src/overlays/actors/ovl_En_Dog/z_en_dog.c @@ -500,11 +500,11 @@ void EnDog_Draw(Actor* thisx, PlayState* play) { EnDog* this = (EnDog*)thisx; Color_RGB8 colors[] = { { 255, 255, 200 }, { 150, 100, 50 } }; - if (CVarGetInteger("gCosmetics.NPC_Dog1.Changed", 0)) { - colors[0] = CVarGetColor24("gCosmetics.NPC_Dog1.Value", colors[0]); + if (CVarGetInteger(CVAR_COSMETIC("NPC.Dog1.Changed"), 0)) { + colors[0] = CVarGetColor24(CVAR_COSMETIC("NPC.Dog1.Value"), colors[0]); } - if (CVarGetInteger("gCosmetics.NPC_Dog2.Changed", 0)) { - colors[1] = CVarGetColor24("gCosmetics.NPC_Dog2.Value", colors[1]); + if (CVarGetInteger(CVAR_COSMETIC("NPC.Dog2.Changed"), 0)) { + colors[1] = CVarGetColor24(CVAR_COSMETIC("NPC.Dog2.Value"), colors[1]); } OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index eba2799b7..3c3e7c462 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1486,7 +1486,7 @@ s32 EnElf_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p if (this->fairyFlags & FAIRY_FLAG_BIG) { scale *= 2.0f; } - scale *= CVarGetFloat("gCosmetics.Fairies_Size", 1.0f); + scale *= CVarGetFloat(CVAR_COSMETIC("Fairies.Size"), 1.0f); scale *= (this->actor.scale.x * 124.99999f); Matrix_MultVec3f(&zeroVec, &mtxMult); diff --git a/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c b/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c index 37ceedb87..120461f8f 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.c @@ -398,24 +398,24 @@ void EnExRuppy_Draw(Actor* thisx, PlayState* play) { u8 shouldColor = 0; switch (this->colorIdx) { case 0: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0); break; case 1: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_BlueRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_BlueRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0); break; case 2: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_RedRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_RedRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0); break; case 4: // orange rupee texture corresponds to the purple rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_PurpleRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_PurpleRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0); break; case 3: // pink rupee texture corresponds to the gold rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GoldRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GoldRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GoldRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GoldRupee.Changed"), 0); break; } diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index 3f8fd104c..6c8afb6d7 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -742,10 +742,10 @@ void EnFirefly_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* static Color_RGBA8 fireAuraEnvColor = { 255, 50, 0, 0 }; static Color_RGBA8 iceAuraPrimColor = { 100, 200, 255, 255 }; static Color_RGBA8 iceAuraEnvColor = { 0, 0, 255, 0 }; - Color_RGBA8 customFireAuraPrimColor = CVarGetColor("gCosmetics.NPC_FireKeesePrimary.Value", fireAuraPrimColor); - Color_RGBA8 customFireAuraEnvColor = CVarGetColor("gCosmetics.NPC_FireKeeseSecondary.Value", fireAuraEnvColor); - Color_RGBA8 customIceAuraPrimColor = CVarGetColor("gCosmetics.NPC_IceKeesePrimary.Value", iceAuraPrimColor); - Color_RGBA8 customIceAuraEnvColor = CVarGetColor("gCosmetics.NPC_IceKeeseSecondary.Value", iceAuraEnvColor); + Color_RGBA8 customFireAuraPrimColor = CVarGetColor(CVAR_COSMETIC("NPC.FireKeesePrimary.Value"), fireAuraPrimColor); + Color_RGBA8 customFireAuraEnvColor = CVarGetColor(CVAR_COSMETIC("NPC.FireKeeseSecondary.Value"), fireAuraEnvColor); + Color_RGBA8 customIceAuraPrimColor = CVarGetColor(CVAR_COSMETIC("NPC.IceKeesePrimary.Value"), iceAuraPrimColor); + Color_RGBA8 customIceAuraEnvColor = CVarGetColor(CVAR_COSMETIC("NPC.IceKeeseSecondary.Value"), iceAuraEnvColor); static Vec3f effVelocity = { 0.0f, 0.5f, 0.0f }; static Vec3f effAccel = { 0.0f, 0.5f, 0.0f }; static Vec3f limbSrc = { 0.0f, 0.0f, 0.0f }; @@ -785,23 +785,23 @@ void EnFirefly_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* } if (this->auraType == KEESE_AURA_FIRE) { - if (CVarGetInteger("gCosmetics.NPC_FireKeesePrimary.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("NPC.FireKeesePrimary.Changed"), 0)) { effPrimColor = &customFireAuraPrimColor; } else { effPrimColor = &fireAuraPrimColor; } - if (CVarGetInteger("gCosmetics.NPC_FireKeeseSecondary.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("NPC.FireKeeseSecondary.Changed"), 0)) { effEnvColor = &customFireAuraEnvColor; } else { effEnvColor = &fireAuraEnvColor; } } else { - if (CVarGetInteger("gCosmetics.NPC_IceKeesePrimary.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("NPC.IceKeesePrimary.Changed"), 0)) { effPrimColor = &customIceAuraPrimColor; } else { effPrimColor = &iceAuraPrimColor; } - if (CVarGetInteger("gCosmetics.NPC_IceKeeseSecondary.Changed", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("NPC.IceKeeseSecondary.Changed"), 0)) { effEnvColor = &customIceAuraEnvColor; } else { effEnvColor = &iceAuraEnvColor; diff --git a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c index ce0d39ded..eaaa7c800 100644 --- a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c +++ b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c @@ -488,7 +488,7 @@ void EnGSwitch_DrawRupee(Actor* thisx, PlayState* play) { if (this->type == ENGSWITCH_TARGET_RUPEE) { GetItem_Draw(play, sRupeeTexturesNew[this->colorIdx]); } else { - Color_RGB8 silverRupeeColor = CVarGetColor24("gCosmetics.Consumable_SilverRupee.Value", (Color_RGB8){ 255, 255, 255 }); + Color_RGB8 silverRupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.SilverRupee.Value"), (Color_RGB8){ 255, 255, 255 }); Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); @@ -507,28 +507,28 @@ void EnGSwitch_DrawRupee(Actor* thisx, PlayState* play) { u8 shouldColor = 0; switch (this->colorIdx) { case 0: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0); break; case 1: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_BlueRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_BlueRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0); break; case 2: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_RedRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_RedRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0); break; case 4: // orange rupee texture corresponds to the purple rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_PurpleRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_PurpleRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0); break; case 3: // pink rupee texture corresponds to the gold rupee (authentic bug) - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GoldRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GoldRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GoldRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GoldRupee.Changed"), 0); break; case 5: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_SilverRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_SilverRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.SilverRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.SilverRupee.Changed"), 0); break; } @@ -635,28 +635,28 @@ void EnGSwitch_DrawEffects(EnGSwitch* this, PlayState* play) { u8 shouldColor = 0; switch (effect->colorIdx) { case 0: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GreenRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GreenRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0); break; case 1: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_BlueRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_BlueRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0); break; case 2: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_RedRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_RedRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0); break; case 3: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_PurpleRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_PurpleRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0); break; case 4: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_GoldRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_GoldRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GoldRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.GoldRupee.Changed"), 0); break; case 5: - rupeeColor = CVarGetColor24("gCosmetics.Consumable_SilverRupee.Value", (Color_RGB8){ 255, 255, 255 }); - shouldColor = CVarGetInteger("gCosmetics.Consumable_SilverRupee.Changed", 0); + rupeeColor = CVarGetColor24(CVAR_COSMETIC("Consumable.SilverRupee.Value"), (Color_RGB8){ 255, 255, 255 }); + shouldColor = CVarGetInteger(CVAR_COSMETIC("Consumable.SilverRupee.Changed"), 0); break; } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 5f1c8fa03..d8155e2da 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -2134,7 +2134,7 @@ s32 EnGo2_OverrideLimbDraw(PlayState* play, s32 limb, Gfx** dList, Vec3f* pos, V f32 float1; if (limb == 17) { - Matrix_Translate(2800.0f + CVarGetFloat("gCosmetics.Goron_NeckLength", 0.0f), 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Translate(2800.0f + CVarGetFloat(CVAR_COSMETIC("Goron.NeckLength"), 0.0f), 0.0f, 0.0f, MTXMODE_APPLY); vec1 = this->interactInfo.headRot; float1 = (vec1.y / (f32)0x8000) * M_PI; Matrix_RotateX(float1, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c index 159774406..64329bb04 100644 --- a/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c +++ b/soh/src/overlays/actors/ovl_En_Gs/z_en_gs.c @@ -594,8 +594,8 @@ void EnGs_Draw(Actor* thisx, PlayState* play) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->flashColor.r, this->flashColor.g, this->flashColor.b, this->flashColor.a); } else { - if (CVarGetInteger("gCosmetics.World_GossipStone.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.World_GossipStone.Value", (Color_RGB8){255, 255, 255}); + if (CVarGetInteger(CVAR_COSMETIC("World.GossipStone.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("World.GossipStone.Value"), (Color_RGB8){255, 255, 255}); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, color.r, color.g, color.b, 255); } else { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index ac8c0b7bd..b3f1219ad 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -810,8 +810,8 @@ Gfx* func_80A761B0(GraphicsContext* gfxCtx, u8 primR, u8 primG, u8 primB, u8 env displayListHead = displayList; gDPPipeSync(displayListHead++); - if (CVarGetInteger("gCosmetics.NPC_IronKnuckles.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.NPC_IronKnuckles.Value", (Color_RGB8){primR, primG, primB}); + if (CVarGetInteger(CVAR_COSMETIC("NPC.IronKnuckles.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("NPC.IronKnuckles.Value"), (Color_RGB8){primR, primG, primB}); gDPSetPrimColor(displayListHead++, 0, 0, color.r, color.g, color.b, 255); } else { gDPSetPrimColor(displayListHead++, 0, 0, primR, primG, primB, 255); diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 1f813c2d6..5733e8ca7 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1379,9 +1379,9 @@ void EnKo_Draw(Actor* thisx, PlayState* play) { Color_RGBA8 tunicColor = sModelInfo[ENKO_TYPE].tunicColor; Color_RGBA8 bootsColor = sModelInfo[ENKO_TYPE].bootsColor; - if (CVarGetInteger("gCosmetics.NPC_Kokiri.Changed", 0)) { - tunicColor = CVarGetColor("gCosmetics.NPC_Kokiri.Value", sModelInfo[ENKO_TYPE].tunicColor); - bootsColor = CVarGetColor("gCosmetics.NPC_Kokiri.Value", sModelInfo[ENKO_TYPE].bootsColor); + if (CVarGetInteger(CVAR_COSMETIC("NPC.Kokiri.Changed"), 0)) { + tunicColor = CVarGetColor(CVAR_COSMETIC("NPC.Kokiri.Value"), sModelInfo[ENKO_TYPE].tunicColor); + bootsColor = CVarGetColor(CVAR_COSMETIC("NPC.Kokiri.Value"), sModelInfo[ENKO_TYPE].bootsColor); } this->actor.shape.shadowAlpha = this->modelAlpha; diff --git a/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c index 00cfb3555..2143aa6e6 100644 --- a/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c +++ b/soh/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c @@ -340,8 +340,8 @@ void EnMThunder_Draw(Actor* thisx, PlayState* play2) { switch (this->unk_1C6) { case 0: - if (CVarGetInteger("gCosmetics.SpinAttack_Level2Primary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level2Primary.Value", (Color_RGB8){255, 255, 170}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level2Primary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level2Primary.Value"), (Color_RGB8){255, 255, 170}); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, color.r, color.g, color.b, (u8)(this->unk_1B0 * 255)); } else { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, (u8)(this->unk_1B0 * 255)); @@ -350,8 +350,8 @@ void EnMThunder_Draw(Actor* thisx, PlayState* play2) { gSPDisplayList(POLY_XLU_DISP++, gSpinAttack4DL); break; case 1: - if (CVarGetInteger("gCosmetics.SpinAttack_Level1Primary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level1Primary.Value", (Color_RGB8){170, 255, 255}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level1Primary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level1Primary.Value"), (Color_RGB8){170, 255, 255}); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, color.r, color.g, color.b, (u8)(this->unk_1B0 * 255)); } else { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u8)(this->unk_1B0 * 255)); @@ -383,14 +383,14 @@ void EnMThunder_Draw(Actor* thisx, PlayState* play2) { if (this->unk_1B8 >= 0.85f) { phi_f14 = (D_80AA046C[(play->gameplayFrames & 7)] * 6.0f) + 1.0f; - if (CVarGetInteger("gCosmetics.SpinAttack_Level2Primary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level2Primary.Value", (Color_RGB8){255, 255, 170}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level2Primary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level2Primary.Value"), (Color_RGB8){255, 255, 170}); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, color.r, color.g, color.b, this->unk_1C8); } else { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, this->unk_1C8); } - if (CVarGetInteger("gCosmetics.SpinAttack_Level2Secondary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level2Secondary.Value", (Color_RGB8){255, 100, 0}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level2Secondary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level2Secondary.Value"), (Color_RGB8){255, 100, 0}); gDPSetEnvColor(POLY_XLU_DISP++, color.r, color.g, color.b, 128); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 100, 0, 128); @@ -398,14 +398,14 @@ void EnMThunder_Draw(Actor* thisx, PlayState* play2) { phi_t1 = 0x28; } else { phi_f14 = (D_80AA046C[play->gameplayFrames & 7] * 2.0f) + 1.0f; - if (CVarGetInteger("gCosmetics.SpinAttack_Level1Primary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level1Primary.Value", (Color_RGB8){170, 255, 255}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level1Primary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level1Primary.Value"), (Color_RGB8){170, 255, 255}); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, color.r, color.g, color.b, this->unk_1C8); } else { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, this->unk_1C8); } - if (CVarGetInteger("gCosmetics.SpinAttack_Level1Secondary.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.SpinAttack_Level1Secondary.Value", (Color_RGB8){0, 100, 255}); + if (CVarGetInteger(CVAR_COSMETIC("SpinAttack.Level1Secondary.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("SpinAttack.Level1Secondary.Value"), (Color_RGB8){0, 100, 255}); gDPSetEnvColor(POLY_XLU_DISP++, color.r, color.g, color.b, 128); } else { gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 34ef24e40..c538e568e 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -1976,9 +1976,9 @@ void EnOssan_UpdateItemSelectedProperty(EnOssan* this) { void EnOssan_UpdateCursorAnim(EnOssan* this) { Color_RGB8 aButtonColor = { 0, 80, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 0, 255, 80 }; } f32 t; @@ -2535,7 +2535,7 @@ s32 EnGo2_OverrideLimbDrawGoronShopkeeper (PlayState* play, s32 limb, Gfx** dLis EnOssan* this = (EnOssan*)thisx; if (limb == 17) { - Matrix_Translate(CVarGetFloat("gCosmetics.Goron_NeckLength", 0.0f), 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_Translate(CVarGetFloat(CVAR_COSMETIC("Goron.NeckLength"), 0.0f), 0.0f, 0.0f, MTXMODE_APPLY); } return 0; } diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index 6a001d07b..901191d0d 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -745,8 +745,8 @@ void EnPartner_Update(Actor* thisx, PlayState* play) { CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); } - if (CVarGetInteger("gCosmetics.Ivan_IdlePrimary.Changed", 0)) { - Color_RGB8 ivanColor1 = CVarGetColor24("gCosmetics.Ivan_IdlePrimary.Value", (Color_RGB8){ 255, 255, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Ivan.IdlePrimary.Changed"), 0)) { + Color_RGB8 ivanColor1 = CVarGetColor24(CVAR_COSMETIC("Ivan.IdlePrimary.Value"), (Color_RGB8){ 255, 255, 255 }); this->innerColor.r = ivanColor1.r; this->innerColor.g = ivanColor1.g; this->innerColor.b = ivanColor1.b; @@ -756,8 +756,8 @@ void EnPartner_Update(Actor* thisx, PlayState* play) { this->innerColor.b = 255; } - if (CVarGetInteger("gCosmetics.Ivan_IdleSecondary.Changed", 0)) { - Color_RGB8 ivanColor2 = CVarGetColor24("gCosmetics.Ivan_IdleSecondary.Value", (Color_RGB8){ 0, 255, 0 }); + if (CVarGetInteger(CVAR_COSMETIC("Ivan.IdleSecondary.Changed"), 0)) { + Color_RGB8 ivanColor2 = CVarGetColor24(CVAR_COSMETIC("Ivan.IdleSecondary.Value"), (Color_RGB8){ 0, 255, 0 }); this->outerColor.r = ivanColor2.r; this->outerColor.g = ivanColor2.g; this->outerColor.b = ivanColor2.b; diff --git a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c index b0c7b44fc..cf8c28165 100644 --- a/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c +++ b/soh/src/overlays/actors/ovl_Obj_Timeblock/z_obj_timeblock.c @@ -340,8 +340,8 @@ void ObjTimeblock_Draw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - if (CVarGetInteger("gCosmetics.World_BlockOfTime.Changed", 0)) { - Color_RGB8 color = CVarGetColor24("gCosmetics.World_BlockOfTime.Value", *primColor); + if (CVarGetInteger(CVAR_COSMETIC("World.BlockOfTime.Changed"), 0)) { + Color_RGB8 color = CVarGetColor24(CVAR_COSMETIC("World.BlockOfTime.Value"), *primColor); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, color.r, color.g, color.b, 255); } else { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, primColor->r, primColor->g, primColor->b, 255); diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index b90681120..cef3f2d3f 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11070,8 +11070,8 @@ void func_80848EF8(Player* this, PlayState* play) { /*Prevent it on horse, while jumping and on title screen. If you fly around no stone of agony for you! */ Color_RGB8 stoneOfAgonyColor = { 255, 255, 255 }; - if (CVarGetInteger("gCosmetics.Hud_StoneOfAgony.Changed", 0)) { - stoneOfAgonyColor = CVarGetColor24("gCosmetics.Hud_StoneOfAgony.Value", stoneOfAgonyColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.StoneOfAgony.Changed"), 0)) { + stoneOfAgonyColor = CVarGetColor24(CVAR_COSMETIC("HUD.StoneOfAgony.Value"), stoneOfAgonyColor); } if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"), 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { s16 Top_Margins = (CVarGetInteger("gHUDMargin_T", 0) * -1); @@ -11079,8 +11079,8 @@ void func_80848EF8(Player* this, PlayState* play) { s16 Right_Margins = CVarGetInteger("gHUDMargin_R", 0); s16 X_Margins_VSOA; s16 Y_Margins_VSOA; - if (CVarGetInteger("gVSOAUseMargins", 0) != 0) { - if (CVarGetInteger("gVSOAPosType", 0) == 0) { + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 0) { X_Margins_VSOA = Left_Margins; }; Y_Margins_VSOA = Top_Margins; @@ -11092,21 +11092,21 @@ void func_80848EF8(Player* this, PlayState* play) { s16 PosY_VSOA_ori = 60 + Y_Margins_VSOA; s16 PosX_VSOA; s16 PosY_VSOA; - if (CVarGetInteger("gVSOAPosType", 0) != 0) { - PosY_VSOA = CVarGetInteger("gVSOAPosY", 0) + Y_Margins_VSOA; - if (CVarGetInteger("gVSOAPosType", 0) == 1) { // Anchor Left - if (CVarGetInteger("gVSOAUseMargins", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) != 0) { + PosY_VSOA = CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosY"), 0) + Y_Margins_VSOA; + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 1) { // Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { X_Margins_VSOA = Left_Margins; }; - PosX_VSOA = OTRGetDimensionFromLeftEdge(CVarGetInteger("gVSOAPosX", 0) + X_Margins_VSOA); - } else if (CVarGetInteger("gVSOAPosType", 0) == 2) { // Anchor Right - if (CVarGetInteger("gVSOAUseMargins", 0) != 0) { + PosX_VSOA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0) + X_Margins_VSOA); + } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 2) { // Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { X_Margins_VSOA = Right_Margins; }; - PosX_VSOA = OTRGetDimensionFromRightEdge(CVarGetInteger("gVSOAPosX", 0) + X_Margins_VSOA); - } else if (CVarGetInteger("gVSOAPosType", 0) == 3) { // Anchor None - PosX_VSOA = CVarGetInteger("gVSOAPosX", 0); - } else if (CVarGetInteger("gVSOAPosType", 0) == 4) { // Hidden + PosX_VSOA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0) + X_Margins_VSOA); + } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 3) { // Anchor None + PosX_VSOA = CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 4) { // Hidden PosX_VSOA = -9999; } } else { @@ -11787,14 +11787,14 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, earRot.x = sBunnyEarKinematics.rot.y + 0x3E2; earRot.y = sBunnyEarKinematics.rot.z + 0xDBE; earRot.z = sBunnyEarKinematics.rot.x - 0x348A; - Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat("gCosmetics.BunnyHood_EarLength", 0.0f), -240.0f - CVarGetFloat("gCosmetics.BunnyHood_EarSpread", 0.0f), &earRot); + Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat(CVAR_COSMETIC("BunnyHood.EarLength"), 0.0f), -240.0f - CVarGetFloat(CVAR_COSMETIC("BunnyHood.EarSpread"), 0.0f), &earRot); MATRIX_TOMTX(bunnyEarMtx++); // Left ear earRot.x = sBunnyEarKinematics.rot.y - 0x3E2; earRot.y = -0xDBE - sBunnyEarKinematics.rot.z; earRot.z = sBunnyEarKinematics.rot.x - 0x348A; - Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat("gCosmetics.BunnyHood_EarLength", 0.0f), 240.0f + CVarGetFloat("gCosmetics.BunnyHood_EarSpread", 0.0f), &earRot); + Matrix_SetTranslateRotateYXZ(97.0f, -1203.0f - CVarGetFloat(CVAR_COSMETIC("BunnyHood.EarLength"), 0.0f), 240.0f + CVarGetFloat(CVAR_COSMETIC("BunnyHood.EarSpread"), 0.0f), &earRot); MATRIX_TOMTX(bunnyEarMtx); } diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 0517bfab6..f43cf7a74 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1959,20 +1959,20 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) { s16 deathCountSplit[3]; Color_RGB8 heartColor = {HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_Hearts.Changed", 0)) { - heartColor = CVarGetColor24("gCosmetics.Consumable_Hearts.Value", heartColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { + heartColor = CVarGetColor24(CVAR_COSMETIC("Consumable.Hearts.Value"), heartColor); } Color_RGB8 heartBorder = {HEARTS_ENV_R, HEARTS_ENV_G, HEARTS_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_HeartBorder.Changed", 0)) { - heartBorder = CVarGetColor24("gCosmetics.Consumable_HeartBorder.Value", heartBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.HeartBorder.Changed"), 0)) { + heartBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.HeartBorder.Value"), heartBorder); } Color_RGB8 ddColor = {HEARTS_DD_ENV_R, HEARTS_DD_ENV_G, HEARTS_DD_ENV_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHearts.Changed", 0)) { - ddColor = CVarGetColor24("gCosmetics.Consumable_DDHearts.Value", ddColor); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHearts.Changed"), 0)) { + ddColor = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHearts.Value"), ddColor); } Color_RGB8 ddBorder = {HEARTS_DD_PRIM_R, HEARTS_DD_PRIM_G, HEARTS_DD_PRIM_B}; - if (CVarGetInteger("gCosmetics.Consumable_DDHeartBorder.Changed", 0)) { - ddBorder = CVarGetColor24("gCosmetics.Consumable_DDHeartBorder.Value", ddBorder); + if (CVarGetInteger(CVAR_COSMETIC("Consumable.DDHeartBorder.Changed"), 0)) { + ddBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.DDHeartBorder.Value"), ddBorder); } OPEN_DISPS(this->state.gfxCtx); @@ -3256,8 +3256,8 @@ void FileChoose_Main(GameState* thisx) { Input* input = &this->state.input[0]; Color_RGB8 helpTextColor = { 100, 255, 255 }; - if (CVarGetInteger("gCosmetics.Title_FileChoose.Changed", 0)) { - Color_RGB8 backgroundColor = CVarGetColor24("gCosmetics.Title_FileChoose.Value", (Color_RGB8){ 100, 150, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Title.FileChoose.Changed"), 0)) { + Color_RGB8 backgroundColor = CVarGetColor24(CVAR_COSMETIC("Title.FileChoose.Value"), (Color_RGB8){ 100, 150, 255 }); this->windowColor[0] = backgroundColor.r; this->windowColor[1] = backgroundColor.g; this->windowColor[2] = backgroundColor.b; diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c index 1682de47d..525f5ac28 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c @@ -911,8 +911,8 @@ void FileChoose_DrawOptionsImpl(GameState* thisx) { { 0, 150, 150 }, }; - if (CVarGetInteger("gCosmetics.Title_FileChoose.Changed", 0)) { - Color_RGB8 backgroundColor = CVarGetColor24("gCosmetics.Title_FileChoose.Value", (Color_RGB8){ 100, 150, 255 }); + if (CVarGetInteger(CVAR_COSMETIC("Title.FileChoose.Changed"), 0)) { + Color_RGB8 backgroundColor = CVarGetColor24(CVAR_COSMETIC("Title.FileChoose.Value"), (Color_RGB8){ 100, 150, 255 }); cursorPrimColors[1][0] = MIN(backgroundColor.r + 100, 255); cursorPrimColors[1][1] = MIN(backgroundColor.g + 100, 255); cursorPrimColors[1][2] = MIN(backgroundColor.b + 100, 255); diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index f74c0298d..617edba1b 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -178,8 +178,8 @@ void Title_Draw(TitleContext* this) { gDPSetRenderMode(POLY_OPA_DISP++, G_RM_XLU_SURF2, G_RM_OPA_CI | CVG_DST_WRAP); gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0); - if (CVarGetInteger("gCosmetics.Title_NintendoLogo.Changed", 0)) { - Color_RGB8 nintendoLogoColor = CVarGetColor24("gCosmetics.Title_NintendoLogo.Value", (Color_RGB8){0, 0, 255}); + if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) { + Color_RGB8 nintendoLogoColor = CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), (Color_RGB8){0, 0, 255}); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128); } else { @@ -221,7 +221,7 @@ void Title_Draw(TitleContext* this) { Environment_FillScreen(this->state.gfxCtx, 0, 0, 0, (s16)this->coverAlpha, FILL_SCREEN_XLU); - sTitleRotY += (300 * CVarGetFloat("gCosmetics.N64Logo_SpinSpeed", 1.0f)); + sTitleRotY += (300 * CVarGetFloat(CVAR_COSMETIC("N64Logo.SpinSpeed"), 1.0f)); CLOSE_DISPS(this->state.gfxCtx); } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 987c004a0..80d47ea4f 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -7,31 +7,31 @@ extern const char* digitTextures[]; void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { Color_RGB8 aButtonColor = { 80, 150, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 80, 255, 150 }; } Color_RGB8 cButtonsColor = {255, 255, 50}; - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - cButtonsColor = CVarGetColor24("gCosmetics.Hud_CButtons.Value", cButtonsColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); } Color_RGB8 cUpButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); } Color_RGB8 cDownButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); } Color_RGB8 cLeftButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); } Color_RGB8 cRightButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); } static s16 D_8082A070[][4] = { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index a67530f50..9d699db90 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -108,9 +108,9 @@ void KaleidoScope_DrawAButton(PlayState* play, Vtx* vtx, int16_t xTranslate, int Matrix_Translate(xTranslate, yTranslate, 0, MTXMODE_APPLY); gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); Color_RGB8 aButtonColor = { 0, 100, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 0, 255, 100 }; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 004686a4e..40d00a1a4 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -193,9 +193,9 @@ void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 canCycle, u8 if (!isCycling && sSlotCycleActiveAnimTimer[slot] == 0 && pauseCtx->cursorSlot[PAUSE_ITEM] == slot && pauseCtx->cursorSpecialPos == 0) { Color_RGB8 aButtonColor = { 0, 100, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 0, 255, 100 }; } @@ -873,29 +873,29 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger("gBBtnUseMargins", 0) != 0) { - if (CVarGetInteger("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnLPosType", 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnRPosType", 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) { - if (CVarGetInteger("gCBtnDPosType", 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -959,48 +959,48 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { sCButtonPosY[6] = ItemIconPos_ori[6][1]; } //C button Left - if (CVarGetInteger("gCBtnLPosType", 0) != 0) { - sCButtonPosY[0] = CVarGetInteger("gCBtnLPosY", 0)+Y_Margins_CL; - if (CVarGetInteger("gCBtnLPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - sCButtonPosX[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnLUseMargins", 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - sCButtonPosX[0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnLPosX", 0)+X_Margins_CL); - } else if (CVarGetInteger("gCBtnLPosType", 0) == 3) {//Anchor None - sCButtonPosX[0] = CVarGetInteger("gCBtnLPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + sCButtonPosY[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + sCButtonPosX[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + sCButtonPosX[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); } } else { sCButtonPosX[0] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[0][0]); sCButtonPosY[0] = ItemIconPos_ori[0][1]; } //C Button down - if (CVarGetInteger("gCBtnDPosType", 0) != 0) { - sCButtonPosY[1] = CVarGetInteger("gCBtnDPosY", 0)+Y_Margins_CD; - if (CVarGetInteger("gCBtnDPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - sCButtonPosX[1] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnDUseMargins", 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - sCButtonPosX[1] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnDPosX", 0)+X_Margins_CD); - } else if (CVarGetInteger("gCBtnDPosType", 0) == 3) {//Anchor None - sCButtonPosX[1] = CVarGetInteger("gCBtnDPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { + sCButtonPosY[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + sCButtonPosX[1] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + sCButtonPosX[1] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); } } else { sCButtonPosX[1] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[1][0]); sCButtonPosY[1] = ItemIconPos_ori[1][1]; } //C button Right - if (CVarGetInteger("gCBtnRPosType", 0) != 0) { - sCButtonPosY[2] = CVarGetInteger("gCBtnRPosY", 0)+Y_Margins_CR; - if (CVarGetInteger("gCBtnRPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - sCButtonPosX[2] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCBtnRUseMargins", 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - sCButtonPosX[2] = OTRGetDimensionFromRightEdge(CVarGetInteger("gCBtnRPosX", 0)+X_Margins_CR); - } else if (CVarGetInteger("gCBtnRPosType", 0) == 3) {//Anchor None - sCButtonPosX[2] = CVarGetInteger("gCBtnRPosX", 0); + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + sCButtonPosY[2] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + sCButtonPosX[2] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + sCButtonPosX[2] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[2] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); } } else { sCButtonPosX[2] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[2][0]); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 131fb7339..8939b0c61 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -1129,14 +1129,14 @@ void KaleidoScope_DrawCursor(PlayState* play, u16 pageIndex) { temp = pauseCtx->unk_1E4; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - sCursorColors[2] = CVarGetColor24("gCosmetics.Hud_AButton.Value", sCursorColors[2]); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + sCursorColors[2] = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), sCursorColors[2]); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { sCursorColors[2] = (Color_RGB8){ 0, 255, 50 }; } - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - sCursorColors[1] = CVarGetColor24("gCosmetics.Hud_CButtons.Value", sCursorColors[1]); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + sCursorColors[1] = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), sCursorColors[1]); } if ((((pauseCtx->unk_1E4 == 0) || (temp == 8)) && (pauseCtx->state == 6)) || @@ -1210,19 +1210,19 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { { 0, 0, 0 }, { 255, 255, 0 }, { 0, 50, 255 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 50, 255 }, }; Color_RGB8 aButtonColor = { 100, 100, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - D_8082ACF4[8] = CVarGetColor24("gCosmetics.Hud_AButton.Value", D_8082ACF4[8]); - D_8082ACF4[11] = CVarGetColor24("gCosmetics.Hud_AButton.Value", D_8082ACF4[11]); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + D_8082ACF4[8] = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), D_8082ACF4[8]); + D_8082ACF4[11] = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), D_8082ACF4[11]); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 100, 255, 100 }; D_8082ACF4[8] = (Color_RGB8){ 0, 255, 50 }; D_8082ACF4[11] = (Color_RGB8){ 0, 255, 50 }; } - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - D_8082ACF4[4] = CVarGetColor24("gCosmetics.Hud_CButtons.Value", D_8082ACF4[4]); - D_8082ACF4[7] = CVarGetColor24("gCosmetics.Hud_CButtons.Value", D_8082ACF4[7]); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + D_8082ACF4[4] = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), D_8082ACF4[4]); + D_8082ACF4[7] = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), D_8082ACF4[7]); } static s16 D_8082AD3C = 20; @@ -1670,31 +1670,31 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { void KaleidoScope_DrawInfoPanel(PlayState* play) { Color_RGB8 aButtonColor = { 0, 100, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = (Color_RGB8){ 0, 255, 100 }; } Color_RGB8 cButtonsColor = {255, 160, 0}; - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - cButtonsColor = CVarGetColor24("gCosmetics.Hud_CButtons.Value", cButtonsColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); } Color_RGB8 cUpButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); } Color_RGB8 cDownButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); } Color_RGB8 cLeftButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); } Color_RGB8 cRightButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); } static const void* sToEquipTextures[3] = { @@ -1883,7 +1883,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - const Color_RGBA8 namePanelColor = CVarGetColor("gCosmetics.Kal_NamePanel.Value", (Color_RGBA8){90,100,130,255}); + const Color_RGBA8 namePanelColor = CVarGetColor(CVAR_COSMETIC("Kaleido.NamePanel.Value"), (Color_RGBA8){90,100,130,255}); gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, namePanelColor.r, namePanelColor.g, namePanelColor.b, namePanelColor.a); gSPVertex(POLY_KAL_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0); @@ -2450,40 +2450,40 @@ static s16 D_8082B0E4[] = { static const char* gPageVtxColorCvars[][4] = { { - "gCosmetics.Kal_ItemSelA.Value", - "gCosmetics.Kal_ItemSelB.Value", - "gCosmetics.Kal_ItemSelC.Value", - "gCosmetics.Kal_ItemSelD.Value", + CVAR_COSMETIC("Kaleido.ItemSelA.Value"), + CVAR_COSMETIC("Kaleido.ItemSelB.Value"), + CVAR_COSMETIC("Kaleido.ItemSelC.Value"), + CVAR_COSMETIC("Kaleido.ItemSelD.Value"), }, { - "gCosmetics.Kal_EquipSelA.Value", - "gCosmetics.Kal_EquipSelB.Value", - "gCosmetics.Kal_EquipSelC.Value", - "gCosmetics.Kal_EquipSelD.Value", + CVAR_COSMETIC("Kaleido.EquipSelA.Value"), + CVAR_COSMETIC("Kaleido.EquipSelB.Value"), + CVAR_COSMETIC("Kaleido.EquipSelC.Value"), + CVAR_COSMETIC("Kaleido.EquipSelD.Value"), }, { - "gCosmetics.Kal_MapSelDunA.Value", - "gCosmetics.Kal_MapSelDunB.Value", - "gCosmetics.Kal_MapSelDunC.Value", - "gCosmetics.Kal_MapSelDunD.Value", + CVAR_COSMETIC("Kaleido.MapSelDunA.Value"), + CVAR_COSMETIC("Kaleido.MapSelDunB.Value"), + CVAR_COSMETIC("Kaleido.MapSelDunC.Value"), + CVAR_COSMETIC("Kaleido.MapSelDunD.Value"), }, { - "gCosmetics.Kal_QuestStatusA.Value", - "gCosmetics.Kal_QuestStatusB.Value", - "gCosmetics.Kal_QuestStatusC.Value", - "gCosmetics.Kal_QuestStatusD.Value", + CVAR_COSMETIC("Kaleido.QuestStatusA.Value"), + CVAR_COSMETIC("Kaleido.QuestStatusB.Value"), + CVAR_COSMETIC("Kaleido.QuestStatusC.Value"), + CVAR_COSMETIC("Kaleido.QuestStatusD.Value"), }, { - "gCosmetics.Kal_MapSelectA.Value", - "gCosmetics.Kal_MapSelectB.Value", - "gCosmetics.Kal_MapSelectC.Value", - "gCosmetics.Kal_MapSelectD.Value", + CVAR_COSMETIC("Kaleido.MapSelectA.Value"), + CVAR_COSMETIC("Kaleido.MapSelectB.Value"), + CVAR_COSMETIC("Kaleido.MapSelectC.Value"), + CVAR_COSMETIC("Kaleido.MapSelectD.Value"), }, { - "gCosmetics.Kal_SaveA.Value", - "gCosmetics.Kal_SaveB.Value", - "gCosmetics.Kal_SaveC.Value", - "gCosmetics.Kal_SaveD.Value", + CVAR_COSMETIC("Kaleido.SaveA.Value"), + CVAR_COSMETIC("Kaleido.SaveB.Value"), + CVAR_COSMETIC("Kaleido.SaveC.Value"), + CVAR_COSMETIC("Kaleido.SaveD.Value"), }, }; From 92467b87b5c8f691874dbd59e03e64b0d4d061f6 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Mon, 29 Apr 2024 02:58:12 +0200 Subject: [PATCH 196/300] Add scene command XML parsers (#4054) * Add scene command parsers * Move logging & add logging cvar * Use new CVAR_DEVELOPER_TOOLS macro * Update soh/soh/resource/logging/SceneCommandLoggers.h --------- Co-authored-by: Garrett Cox --- soh/soh/OTRGlobals.cpp | 1 + soh/soh/SohMenuBar.cpp | 2 + soh/soh/resource/importer/SceneFactory.cpp | 123 ++++ soh/soh/resource/importer/SceneFactory.h | 17 + .../scenecommand/EndMarkerFactory.cpp | 14 + .../importer/scenecommand/EndMarkerFactory.h | 6 + .../scenecommand/SceneCommandFactory.h | 9 + .../scenecommand/SetActorListFactory.cpp | 36 ++ .../scenecommand/SetActorListFactory.h | 6 + .../SetAlternateHeadersFactory.cpp | 34 + .../scenecommand/SetAlternateHeadersFactory.h | 6 + .../scenecommand/SetCameraSettingsFactory.cpp | 17 + .../scenecommand/SetCameraSettingsFactory.h | 6 + .../SetCollisionHeaderFactory.cpp | 17 + .../scenecommand/SetCollisionHeaderFactory.h | 6 + .../scenecommand/SetCsCameraFactory.cpp | 14 + .../scenecommand/SetCsCameraFactory.h | 6 + .../scenecommand/SetCutscenesFactory.cpp | 17 + .../scenecommand/SetCutscenesFactory.h | 6 + .../scenecommand/SetEchoSettingsFactory.cpp | 16 + .../scenecommand/SetEchoSettingsFactory.h | 6 + .../scenecommand/SetEntranceListFactory.cpp | 30 + .../scenecommand/SetEntranceListFactory.h | 6 + .../scenecommand/SetExitListFactory.cpp | 27 + .../scenecommand/SetExitListFactory.h | 6 + .../scenecommand/SetLightListFactory.cpp | 46 ++ .../scenecommand/SetLightListFactory.h | 6 + .../SetLightingSettingsFactory.cpp | 49 ++ .../scenecommand/SetLightingSettingsFactory.h | 6 + .../importer/scenecommand/SetMeshFactory.cpp | 176 +++++ .../importer/scenecommand/SetMeshFactory.h | 6 + .../scenecommand/SetObjectListFactory.cpp | 27 + .../scenecommand/SetObjectListFactory.h | 6 + .../scenecommand/SetPathwaysFactory.cpp | 30 + .../scenecommand/SetPathwaysFactory.h | 6 + .../scenecommand/SetRoomBehaviorFactory.cpp | 17 + .../scenecommand/SetRoomBehaviorFactory.h | 6 + .../scenecommand/SetRoomListFactory.cpp | 35 + .../scenecommand/SetRoomListFactory.h | 6 + .../scenecommand/SetSkyboxModifierFactory.cpp | 17 + .../scenecommand/SetSkyboxModifierFactory.h | 6 + .../scenecommand/SetSkyboxSettingsFactory.cpp | 19 + .../scenecommand/SetSkyboxSettingsFactory.h | 6 + .../scenecommand/SetSoundSettingsFactory.cpp | 18 + .../scenecommand/SetSoundSettingsFactory.h | 6 + .../scenecommand/SetSpecialObjectsFactory.cpp | 17 + .../scenecommand/SetSpecialObjectsFactory.h | 6 + .../SetStartPositionListFactory.cpp | 36 ++ .../SetStartPositionListFactory.h | 6 + .../scenecommand/SetTimeSettingsFactory.cpp | 18 + .../scenecommand/SetTimeSettingsFactory.h | 6 + .../SetTransitionActorListFactory.cpp | 38 ++ .../SetTransitionActorListFactory.h | 6 + .../scenecommand/SetWindSettingsFactory.cpp | 19 + .../scenecommand/SetWindSettingsFactory.h | 6 + .../resource/logging/SceneCommandLoggers.cpp | 603 ++++++++++++++++++ .../resource/logging/SceneCommandLoggers.h | 32 + soh/soh/resource/type/scenecommand/SetMesh.h | 2 + .../resource/type/scenecommand/SetPathways.h | 1 + 59 files changed, 1724 insertions(+) create mode 100644 soh/soh/resource/logging/SceneCommandLoggers.cpp create mode 100644 soh/soh/resource/logging/SceneCommandLoggers.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 71b738b96..b79b1f9f3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -334,6 +334,7 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Animation", static_cast(SOH::ResourceType::SOH_Animation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast(SOH::ResourceType::SOH_PlayerAnimation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "CollisionHeader", static_cast(SOH::ResourceType::SOH_CollisionHeader), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "CollisionHeader", static_cast(SOH::ResourceType::SOH_CollisionHeader), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Skeleton", static_cast(SOH::ResourceType::SOH_Skeleton), 0); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index b577caee5..20bcc43b8 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1652,6 +1652,8 @@ void DrawDeveloperToolsMenu() { UIWidgets::Tooltip("Optimized debug warp screen, with the added ability to chose entrances and time of day"); UIWidgets::PaddedEnhancementCheckbox("Debug Warp Screen Translation", CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Translate the Debug Warp Screen based on the game language"); + UIWidgets::PaddedEnhancementCheckbox("Resource logging", CVAR_DEVELOPER_TOOLS("ResourceLogging"), true, false); + UIWidgets::Tooltip("Logs some resources as XML when they're loaded in binary format"); if (gPlayState != NULL) { UIWidgets::PaddedSeparator(); ImGui::Checkbox("Frame Advance##frameAdvance", (bool*)&gPlayState->frameAdvCtx.enabled); diff --git a/soh/soh/resource/importer/SceneFactory.cpp b/soh/soh/resource/importer/SceneFactory.cpp index 679d574cb..c537cb312 100644 --- a/soh/soh/resource/importer/SceneFactory.cpp +++ b/soh/soh/resource/importer/SceneFactory.cpp @@ -105,4 +105,127 @@ std::shared_ptr ResourceFactoryBinarySceneV0::ReadResource(std:: return scene; }; + +ResourceFactoryXMLSceneV0::ResourceFactoryXMLSceneV0() { + sceneCommandFactories[SceneCommandID::SetLightingSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetWind] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetExitList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetTimeSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSkyboxModifier] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetEchoSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSoundSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSkyboxSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetRoomBehavior] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCsCamera] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCameraSettings] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetRoomList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCollisionHeader] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetEntranceList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetSpecialObjects] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetObjectList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetStartPositionList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetActorList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetTransitionActorList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::EndMarker] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetAlternateHeaders] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetPathways] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetCutscenes] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetLightList] = std::make_shared(); + sceneCommandFactories[SceneCommandID::SetMesh] = std::make_shared(); +} + +std::vector commandNames = { + "SetStartPositionList", + "SetActorList", + "SetCsCamera", + "SetCollisionHeader", + "SetRoomList", + "SetWind", + "SetEntranceList", + "SetSpecialObjects", + "SetRoomBehavior", + "Unused09", + "SetMesh", + "SetObjectList", + "SetLightList", + "SetPathways", + "SetTransitionActorList", + "SetLightingSettings", + "SetTimeSettings", + "SetSkyboxSettings", + "SetSkyboxModifier", + "SetExitList", + "EndMarker", + "SetSoundSettings", + "SetEchoSettings", + "SetCutscenes", + "SetAlternateHeaders", + "SetCameraSettings", +}; + +SceneCommandID GetCommandID(std::string commandName) { + for (int i = 0; i < commandNames.size(); i++) { + if (commandNames[i] == commandName) { + return (SceneCommandID)i; + } + } + + return SceneCommandID::Error; +} + +void ResourceFactoryXMLSceneV0::ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader) { + auto child = reader->RootElement()->FirstChildElement(); + + int i = 0; + + while (child != nullptr) { + scene->commands.push_back(ParseSceneCommand(scene, child, i)); + + child = child->NextSiblingElement(); + i += 1; + } +} + +std::shared_ptr ResourceFactoryXMLSceneV0::ParseSceneCommand(std::shared_ptr scene, + tinyxml2::XMLElement* child, uint32_t index) { + std::string commandName = child->Name(); + SceneCommandID cmdID = GetCommandID(commandName); + + if (cmdID == SceneCommandID::Error) { + SPDLOG_ERROR("Failed to load scene command with name {} in scene {}", commandName, scene->GetInitData()->Path); + return nullptr; + } + + std::shared_ptr result = nullptr; + auto commandFactory = ResourceFactoryXMLSceneV0::sceneCommandFactories[cmdID]; + + if (commandFactory != nullptr) { + auto initData = std::make_shared(); + initData->Id = scene->GetInitData()->Id; + initData->Type = static_cast(ResourceType::SOH_SceneCommand); + initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index); + initData->ResourceVersion = scene->GetInitData()->ResourceVersion; + result = std::static_pointer_cast(commandFactory->ReadResource(initData, child)); + // Cache the resource? + } + + if (result == nullptr) { + SPDLOG_ERROR("Failed to load scene command of type {} in scene {}", (uint32_t)cmdID, scene->GetInitData()->Path); + } + + return result; +} + +std::shared_ptr ResourceFactoryXMLSceneV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto scene = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + ParseSceneCommands(scene, reader); + + return scene; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/SceneFactory.h b/soh/soh/resource/importer/SceneFactory.h index 5dfed2739..a1b345f7d 100644 --- a/soh/soh/resource/importer/SceneFactory.h +++ b/soh/soh/resource/importer/SceneFactory.h @@ -5,6 +5,7 @@ #include "soh/resource/importer/scenecommand/SceneCommandFactory.h" #include "Resource.h" #include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" namespace SOH { class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary { @@ -22,4 +23,20 @@ class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary { protected: std::shared_ptr ParseSceneCommand(std::shared_ptr scene, std::shared_ptr reader, uint32_t index); }; + +class ResourceFactoryXMLSceneV0 : public LUS::ResourceFactoryXML { + public: + ResourceFactoryXMLSceneV0(); + + std::shared_ptr ReadResource(std::shared_ptr file) override; + void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); + + // Doing something very similar to what we do on the ResourceLoader. + // Eventually, scene commands should be moved up to the ResourceLoader as well. + // They can not right now because the exporter does not give them a proper resource type enum value, + // and the exporter does not export the commands with a proper OTR header. + static inline std::unordered_map> sceneCommandFactories; +protected: + std::shared_ptr ParseSceneCommand(std::shared_ptr scene, tinyxml2::XMLElement* child, uint32_t index); +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp index ffcf17410..debcf7ab1 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/EndMarkerFactory.h" #include "soh/resource/type/scenecommand/EndMarker.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -9,6 +10,19 @@ EndMarkerFactory::ReadResource(std::shared_ptr initData, ReadCommandId(endMarker, reader); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogEndMarkerAsXML(endMarker); + } + + return endMarker; +} + +std::shared_ptr EndMarkerFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto endMarker = std::make_shared(initData); + + endMarker->cmdId = SceneCommandID::EndMarker; + return endMarker; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h index 486aaa2fb..8e3875ef2 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h @@ -7,4 +7,10 @@ class EndMarkerFactory : public SceneCommandFactoryBinaryV0 { public: std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class EndMarkerFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h index 4cebc4a64..73e5a2e06 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h @@ -4,6 +4,7 @@ #include "Resource.h" #include "ResourceFactory.h" #include "soh/resource/type/scenecommand/SceneCommand.h" +#include "public/bridge/consolevariablebridge.h" namespace SOH { class SceneCommandFactoryBinaryV0 { @@ -13,4 +14,12 @@ class SceneCommandFactoryBinaryV0 { protected: void ReadCommandId(std::shared_ptr command, std::shared_ptr reader); }; + +class SceneCommandFactoryXMLV0 { + public: + virtual std::shared_ptr ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) = 0; + + protected: + void ReadCommandId(std::shared_ptr command, tinyxml2::XMLElement* reader); +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp index 86deea193..cf397fcd3 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetActorListFactory.h" #include "soh/resource/type/scenecommand/SetActorList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -26,6 +27,41 @@ SetActorListFactory::ReadResource(std::shared_ptr initDat setActorList->actorList.push_back(entry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogActorListAsXML(setActorList); + } + + return setActorList; +} + +std::shared_ptr SetActorListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setActorList = std::make_shared(initData); + + setActorList->cmdId = SceneCommandID::SetActorList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "ActorEntry") { + ActorEntry entry; + entry.id = child->IntAttribute("Id"); + entry.pos.x = child->IntAttribute("PosX"); + entry.pos.y = child->IntAttribute("PosY"); + entry.pos.z = child->IntAttribute("PosZ"); + entry.rot.x = child->IntAttribute("RotX"); + entry.rot.y = child->IntAttribute("RotY"); + entry.rot.z = child->IntAttribute("RotZ"); + entry.params = child->IntAttribute("Params"); + setActorList->actorList.push_back(entry); + } + + child = child->NextSiblingElement(); + } + + setActorList->numActors = setActorList->actorList.size(); + return setActorList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h index 49a269cfe..5dd872f8a 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h @@ -8,4 +8,10 @@ class SetActorListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetActorListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp index 833d0af8c..40e31f0f2 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h" #include "soh/resource/type/scenecommand/SetAlternateHeaders.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" @@ -21,6 +22,39 @@ std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::sh } } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogAlternateHeadersAsXML(setAlternateHeaders); + } + + return setAlternateHeaders; +} + +std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setAlternateHeaders = std::make_shared(initData); + + setAlternateHeaders->cmdId = SceneCommandID::SetAlternateHeaders; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "AlternateHeader") { + for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { + auto headerName = std::string(child->Attribute("HeaderName")); + if (!headerName.empty()) { + setAlternateHeaders->headers.push_back(std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + } else { + setAlternateHeaders->headers.push_back(nullptr); + } + } + } + + child = child->NextSiblingElement(); + } + + setAlternateHeaders->numHeaders = setAlternateHeaders->headers.size(); + return setAlternateHeaders; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h index 2bc430c0b..84e730905 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h @@ -8,4 +8,10 @@ class SetAlternateHeadersFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetAlternateHeadersFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp index 7e2911a17..521586262 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetCameraSettingsFactory.h" #include "soh/resource/type/scenecommand/SetCameraSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -12,6 +13,22 @@ std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shar setCameraSettings->settings.cameraMovement = reader->ReadInt8(); setCameraSettings->settings.worldMapArea = reader->ReadInt32(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogCameraSettingsAsXML(setCameraSettings); + } + + return setCameraSettings; +} + +std::shared_ptr SetCameraSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setCameraSettings = std::make_shared(initData); + + setCameraSettings->cmdId = SceneCommandID::SetCameraSettings; + + setCameraSettings->settings.cameraMovement = reader->IntAttribute("CameraMovement"); + setCameraSettings->settings.worldMapArea = reader->IntAttribute("WorldMapArea"); + return setCameraSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h index 2f1db272f..a03287b35 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h @@ -8,4 +8,10 @@ class SetCameraSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetCameraSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp index bb83dc57b..f50ee3790 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h" #include "soh/resource/type/scenecommand/SetCollisionHeader.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "libultraship/libultraship.h" #include "spdlog/spdlog.h" @@ -13,6 +14,22 @@ std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::sha setCollisionHeader->fileName = reader->ReadString(); setCollisionHeader->collisionHeader = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogSetCollisionHeaderAsXML(setCollisionHeader); + } + + return setCollisionHeader; +} + +std::shared_ptr SetCollisionHeaderFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setCollisionHeader = std::make_shared(initData); + + setCollisionHeader->cmdId = SceneCommandID::SetCollisionHeader; + + setCollisionHeader->fileName = reader->Attribute("FileName"); + setCollisionHeader->collisionHeader = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); + return setCollisionHeader; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h index b80ee34b4..12b872f3c 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h @@ -8,4 +8,10 @@ class SetCollisionHeaderFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetCollisionHeaderFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp index 84c277989..569b8b1d9 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetCsCameraFactory.h" #include "soh/resource/type/scenecommand/SetCsCamera.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -14,6 +15,19 @@ SetCsCameraFactory::ReadResource(std::shared_ptr initData // OTRTODO: FINISH! + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogCsCameraAsXML(setCsCamera); + } + + return setCsCamera; +} + +std::shared_ptr SetCsCameraFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setCsCamera = std::make_shared(initData); + + setCsCamera->cmdId = SceneCommandID::SetCsCamera; + return setCsCamera; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h index 08dc8e3c3..89c92a699 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h @@ -8,4 +8,10 @@ class SetCsCameraFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetCsCameraFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp index 30f72d168..7aea7c70d 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetCutscenesFactory.h" #include "soh/resource/type/scenecommand/SetCutscenes.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include #include "spdlog/spdlog.h" @@ -13,6 +14,22 @@ SetCutscenesFactory::ReadResource(std::shared_ptr initDat setCutscenes->fileName = reader->ReadString(); setCutscenes->cutscene = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogCutscenesAsXML(setCutscenes); + } + + return setCutscenes; +} + +std::shared_ptr SetCutscenesFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setCutscenes = std::make_shared(initData); + + setCutscenes->cmdId = SceneCommandID::SetCutscenes; + + setCutscenes->fileName = reader->Attribute("FileName"); + setCutscenes->cutscene = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); + return setCutscenes; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h index bbbe38c98..c78bf621c 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h @@ -8,4 +8,10 @@ class SetCutscenesFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetCutscenesFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp index e9c3381cb..d4c6e9a50 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetEchoSettingsFactory.h" #include "soh/resource/type/scenecommand/SetEchoSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -11,6 +12,21 @@ SetEchoSettingsFactory::ReadResource(std::shared_ptr init setEchoSettings->settings.echo = reader->ReadInt8(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogEchoSettingsAsXML(setEchoSettings); + } + + return setEchoSettings; +} + +std::shared_ptr SetEchoSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setEchoSettings = std::make_shared(initData); + + setEchoSettings->cmdId = SceneCommandID::SetEchoSettings; + + setEchoSettings->settings.echo = reader->IntAttribute("Echo"); + return setEchoSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h index 99bda6eae..4be1fe399 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h @@ -8,4 +8,10 @@ class SetEchoSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetEchoSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp index 766bb82da..f3817c39c 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetEntranceListFactory.h" #include "soh/resource/type/scenecommand/SetEntranceList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -20,6 +21,35 @@ SetEntranceListFactory::ReadResource(std::shared_ptr init setEntranceList->entrances.push_back(entranceEntry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogEntranceListAsXML(setEntranceList); + } + + return setEntranceList; +} + +std::shared_ptr SetEntranceListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setEntranceList = std::make_shared(initData); + + setEntranceList->cmdId = SceneCommandID::SetEntranceList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "EntranceEntry") { + EntranceEntry entry; + entry.spawn = child->IntAttribute("Spawn"); + entry.room = child->IntAttribute("Room"); + setEntranceList->entrances.push_back(entry); + } + + child = child->NextSiblingElement(); + } + + setEntranceList->numEntrances = setEntranceList->entrances.size(); + return setEntranceList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h index 35b7fba62..a5349cf83 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h @@ -8,4 +8,10 @@ class SetEntranceListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetEntranceListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp index 5fef9d096..b6078199b 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetExitListFactory.h" #include "soh/resource/type/scenecommand/SetExitList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -15,6 +16,32 @@ SetExitListFactory::ReadResource(std::shared_ptr initData setExitList->exits.push_back(reader->ReadUInt16()); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogExitListAsXML(setExitList); + } + + return setExitList; +} + +std::shared_ptr SetExitListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setExitList = std::make_shared(initData); + + setExitList->cmdId = SceneCommandID::SetExitList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "ExitEntry") { + setExitList->exits.push_back(child->IntAttribute("Id")); + } + + child = child->NextSiblingElement(); + } + + setExitList->numExits = setExitList->exits.size(); + return setExitList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h index d82e8f04a..fc47b88d0 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h @@ -8,4 +8,10 @@ class SetExitListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetExitListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp index 2d05631cd..af7f1bb3c 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetLightListFactory.h" #include "soh/resource/type/scenecommand/SetLightList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -30,6 +31,51 @@ SetLightListFactory::ReadResource(std::shared_ptr initDat setLightList->lightList.push_back(light); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogLightListAsXML(setLightList); + } + + return setLightList; +} + +std::shared_ptr SetLightListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setLightList = std::make_shared(initData); + + setLightList->cmdId = SceneCommandID::SetLightList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "LightInfo") { + LightInfo light; + light.type = child->IntAttribute("Type"); + if (false/*light.type == LIGHT_DIRECTIONAL*/) { + light.params.dir.x = child->IntAttribute("X"); + light.params.dir.y = child->IntAttribute("Y"); + light.params.dir.z = child->IntAttribute("Z"); + light.params.dir.color[0] = child->IntAttribute("ColorR"); + light.params.dir.color[1] = child->IntAttribute("ColorG"); + light.params.dir.color[2] = child->IntAttribute("ColorB"); + } else { + light.params.point.x = child->IntAttribute("X"); + light.params.point.y = child->IntAttribute("Y"); + light.params.point.z = child->IntAttribute("Z"); + light.params.point.color[0] = child->IntAttribute("ColorR"); + light.params.point.color[1] = child->IntAttribute("ColorG"); + light.params.point.color[2] = child->IntAttribute("ColorB"); + light.params.point.drawGlow = child->IntAttribute("DrawGlow"); + light.params.point.radius = child->IntAttribute("Radius"); + } + setLightList->lightList.push_back(light); + } + + child = child->NextSiblingElement(); + } + + setLightList->numLights = setLightList->lightList.size(); + return setLightList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h index 1c4a6e9dc..aae5c8e4a 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h @@ -8,4 +8,10 @@ class SetLightListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetLightListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp index d0a7b89d5..573998cfa 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetLightingSettingsFactory.h" #include "soh/resource/type/scenecommand/SetLightingSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -43,6 +44,54 @@ std::shared_ptr SetLightingSettingsFactory::ReadResource(std::sh setLightingSettings->settings.push_back(lightSettings); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogLightingSettingsAsXML(setLightingSettings); + } + + return setLightingSettings; +} + +std::shared_ptr SetLightingSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setLightingSettings = std::make_shared(initData); + + setLightingSettings->cmdId = SceneCommandID::SetLightingSettings; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "LightingSetting") { + EnvLightSettings lightSettings; + lightSettings.ambientColor[0] = child->IntAttribute("AmbientColorR"); + lightSettings.ambientColor[1] = child->IntAttribute("AmbientColorG"); + lightSettings.ambientColor[2] = child->IntAttribute("AmbientColorB"); + + lightSettings.light1Dir[0] = child->IntAttribute("Light1DirX"); + lightSettings.light1Dir[1] = child->IntAttribute("Light1DirY"); + lightSettings.light1Dir[2] = child->IntAttribute("Light1DirZ"); + lightSettings.light1Color[0] = child->IntAttribute("Light1ColorR"); + lightSettings.light1Color[1] = child->IntAttribute("Light1ColorG"); + lightSettings.light1Color[2] = child->IntAttribute("Light1ColorB"); + + lightSettings.light2Dir[0] = child->IntAttribute("Light2DirX"); + lightSettings.light2Dir[1] = child->IntAttribute("Light2DirY"); + lightSettings.light2Dir[2] = child->IntAttribute("Light2DirZ"); + lightSettings.light2Color[0] = child->IntAttribute("Light2ColorR"); + lightSettings.light2Color[1] = child->IntAttribute("Light2ColorG"); + lightSettings.light2Color[2] = child->IntAttribute("Light2ColorB"); + + lightSettings.fogColor[0] = child->IntAttribute("FogColorR"); + lightSettings.fogColor[1] = child->IntAttribute("FogColorG"); + lightSettings.fogColor[2] = child->IntAttribute("FogColorB"); + lightSettings.fogNear = child->IntAttribute("FogNear"); + lightSettings.fogFar = child->IntAttribute("FogFar"); + setLightingSettings->settings.push_back(lightSettings); + } + + child = child->NextSiblingElement(); + } + return setLightingSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h index df25600e2..39ae6934d 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h @@ -8,4 +8,10 @@ class SetLightingSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetLightingSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp index 8c17ecc07..8c4109c5a 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetMeshFactory.h" #include "soh/resource/type/scenecommand/SetMesh.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" #include "libultraship/libultraship.h" @@ -45,6 +46,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(dlist); } else if (setMesh->meshHeader.base.type == 1) { PolygonDlist pType; @@ -106,6 +109,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); setMesh->dlists.push_back(pType); } else if (setMesh->meshHeader.base.type == 2) { PolygonDlist2 dlist; @@ -124,6 +129,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st dlist.opa = (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr); dlist.xlu = (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr); + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); setMesh->dlists2.push_back(dlist); } else { SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); @@ -141,6 +148,175 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogMeshAsXML(setMesh); + } + + return setMesh; +} + +std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setMesh = std::make_shared(initData); + + setMesh->cmdId = SceneCommandID::SetMesh; + + setMesh->data = reader->IntAttribute("Data"); + + setMesh->meshHeader.base.type = reader->IntAttribute("MeshHeaderType"); + int32_t polyNum = 1; + + if (setMesh->meshHeader.base.type != 1) { + polyNum = reader->IntAttribute("PolyNum"); + if (setMesh->meshHeader.base.type == 0) { + setMesh->meshHeader.polygon0.num = polyNum; + } else if (setMesh->meshHeader.base.type == 2) { + setMesh->meshHeader.polygon2.num = polyNum; + } else { + SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); + } + } + + if (setMesh->meshHeader.base.type == 2) { + setMesh->dlists2.reserve(polyNum); + } else { + setMesh->dlists.reserve(setMesh->meshHeader.polygon0.num); + } + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName != "Polygon") { + child = child->NextSiblingElement(); + continue; + } + + if (setMesh->meshHeader.base.type == 0) { + PolygonDlist dlist; + + int32_t polyType = child->IntAttribute("PolyType"); // Unused + std::string meshOpa = child->Attribute("MeshOpa"); + std::string meshXlu = child->Attribute("MeshXlu"); + + auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; + dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); + setMesh->dlists.push_back(dlist); + } else if (setMesh->meshHeader.base.type == 1) { + PolygonDlist pType; + + setMesh->meshHeader.polygon1.format = child->IntAttribute("Format"); + std::string imgOpa = child->Attribute("ImgOpa"); + std::string imgXlu = child->Attribute("ImgXlu"); + + auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); + auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); + pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; + pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + + int32_t bgImageCount = child->IntAttribute("BgImageCount"); + setMesh->images.reserve(bgImageCount); + + auto grandChild = child->FirstChildElement(); + + while (grandChild != nullptr) { + std::string grandChildName = grandChild->Name(); + if (grandChildName != "BgImage") { + grandChild = grandChild->NextSiblingElement(); + continue; + } + BgImage image; + image.unk_00 = grandChild->IntAttribute("Unknown_00"); + image.id = grandChild->IntAttribute("Id"); + std::string imagePath = "__OTR__" + std::string(grandChild->Attribute("ImagePath")); + setMesh->imagePaths.push_back(imagePath); + image.source = (void*)setMesh->imagePaths.back().c_str(); + image.unk_0C = grandChild->IntAttribute("Unknown_0C"); + image.tlut = grandChild->IntAttribute("TLUT"); + image.width = grandChild->IntAttribute("Width"); + image.height = grandChild->IntAttribute("Height"); + image.fmt = grandChild->IntAttribute("Fmt"); + image.siz = grandChild->IntAttribute("Siz"); + image.mode0 = grandChild->IntAttribute("Mode0"); + image.tlutCount = grandChild->IntAttribute("TLUTCount"); + + if (setMesh->meshHeader.polygon1.format == 1) { + setMesh->meshHeader.polygon1.single.source = image.source; + setMesh->meshHeader.polygon1.single.unk_0C = image.unk_0C; + setMesh->meshHeader.polygon1.single.tlut = (void*)image.tlut; // OTRTODO: type of bgimage.tlut should be uintptr_t + setMesh->meshHeader.polygon1.single.width = image.width; + setMesh->meshHeader.polygon1.single.height = image.height; + setMesh->meshHeader.polygon1.single.fmt = image.fmt; + setMesh->meshHeader.polygon1.single.siz = image.siz; + setMesh->meshHeader.polygon1.single.mode0 = image.mode0; + setMesh->meshHeader.polygon1.single.tlutCount = image.tlutCount; + } else { + setMesh->images.push_back(image); + } + + grandChild = grandChild->NextSiblingElement(); + } + + if (setMesh->meshHeader.polygon1.format != 1) { + setMesh->meshHeader.polygon1.multi.count = bgImageCount; + } + + int32_t polyType = child->IntAttribute("PolyType"); // Unused?? + + std::string meshOpa = child->Attribute("MeshOpa"); + std::string meshXlu = child->Attribute("MeshXlu"); + + opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; + pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); + setMesh->dlists.push_back(pType); + } else if (setMesh->meshHeader.base.type == 2) { + PolygonDlist2 dlist; + + int32_t polyType = child->IntAttribute("PolyType"); // Unused + dlist.pos.x = child->IntAttribute("PosX"); + dlist.pos.y = child->IntAttribute("PosY"); + dlist.pos.z = child->IntAttribute("PosZ"); + dlist.unk_06 = child->IntAttribute("Unknown"); + + std::string meshOpa = child->Attribute("MeshOpa"); + std::string meshXlu = child->Attribute("MeshXlu"); + + auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; + dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; + + setMesh->opaPaths.push_back(meshOpa); + setMesh->xluPaths.push_back(meshXlu); + setMesh->dlists2.push_back(dlist); + } else { + SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); + } + + child = child->NextSiblingElement(); + } + + if (setMesh->meshHeader.base.type == 2) { + setMesh->meshHeader.polygon2.start = setMesh->dlists2.data(); + } else if (setMesh->meshHeader.base.type == 0) { + setMesh->meshHeader.polygon0.start = setMesh->dlists.data(); + } else if (setMesh->meshHeader.base.type == 1) { + setMesh->meshHeader.polygon1.multi.list = setMesh->images.data(); + setMesh->meshHeader.polygon1.dlist = (Gfx*)setMesh->dlists.data(); + } else { + SPDLOG_ERROR("Tried to load mesh in SetMesh scene header with type that doesn't exist: {}", setMesh->meshHeader.base.type); + } + return setMesh; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h index a912bdd37..f64b55d72 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h @@ -8,4 +8,10 @@ class SetMeshFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetMeshFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp index b84befb3b..1d64a9aec 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetObjectListFactory.h" #include "soh/resource/type/scenecommand/SetObjectList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -15,6 +16,32 @@ SetObjectListFactory::ReadResource(std::shared_ptr initDa setObjectList->objects.push_back(reader->ReadUInt16()); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogObjectListAsXML(setObjectList); + } + + return setObjectList; +} + +std::shared_ptr SetObjectListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setObjectList = std::make_shared(initData); + + setObjectList->cmdId = SceneCommandID::SetObjectList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "ObjectEntry") { + setObjectList->objects.push_back(child->IntAttribute("Id")); + } + + child = child->NextSiblingElement(); + } + + setObjectList->numObjects = setObjectList->objects.size(); + return setObjectList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h index 4c2f002c0..094c30a92 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h @@ -8,4 +8,10 @@ class SetObjectListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetObjectListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp index 61534ba48..0e26e96e4 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetPathwaysFactory.h" #include "soh/resource/type/scenecommand/SetPathways.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" #include @@ -18,6 +19,35 @@ SetPathwaysFactory::ReadResource(std::shared_ptr initData setPathways->paths.push_back(path->GetPointer()); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogPathwaysAsXML(setPathways); + } + + return setPathways; +} + +std::shared_ptr SetPathwaysFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setPathways = std::make_shared(initData); + + setPathways->cmdId = SceneCommandID::SetPathways; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "Pathway") { + std::string pathFileName = child->Attribute("FilePath"); + auto path = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); + setPathways->paths.push_back(path->GetPointer()); + setPathways->pathFileNames.push_back(pathFileName); + } + + child = child->NextSiblingElement(); + } + + setPathways->numPaths = setPathways->paths.size(); + return setPathways; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h index c622c820d..2e334c7a5 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h @@ -8,4 +8,10 @@ class SetPathwaysFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetPathwaysFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp index e4601e59c..25a3bf931 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h" #include "soh/resource/type/scenecommand/SetRoomBehavior.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -12,6 +13,22 @@ SetRoomBehaviorFactory::ReadResource(std::shared_ptr init setRoomBehavior->roomBehavior.gameplayFlags = reader->ReadInt8(); setRoomBehavior->roomBehavior.gameplayFlags2 = reader->ReadInt32(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogRoomBehaviorAsXML(setRoomBehavior); + } + + return setRoomBehavior; +} + +std::shared_ptr SetRoomBehaviorFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setRoomBehavior = std::make_shared(initData); + + setRoomBehavior->cmdId = SceneCommandID::SetRoomBehavior; + + setRoomBehavior->roomBehavior.gameplayFlags = reader->IntAttribute("GameplayFlags1"); + setRoomBehavior->roomBehavior.gameplayFlags2 = reader->IntAttribute("GameplayFlags2"); + return setRoomBehavior; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h index 70a53ba1e..97c5c7bb4 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h @@ -8,4 +8,10 @@ class SetRoomBehaviorFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetRoomBehaviorFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp index 7726877a1..67c3afd0f 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetRoomListFactory.h" #include "soh/resource/type/scenecommand/SetRoomList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -23,6 +24,40 @@ SetRoomListFactory::ReadResource(std::shared_ptr initData setRoomList->rooms.push_back(room); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogRoomListAsXML(setRoomList); + } + + return setRoomList; +} + +std::shared_ptr SetRoomListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setRoomList = std::make_shared(initData); + + setRoomList->cmdId = SceneCommandID::SetRoomList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "RoomEntry") { + RomFile room; + + setRoomList->fileNames.push_back(child->Attribute("Path")); + + room.fileName = (char*)setRoomList->fileNames.back().c_str(); + room.vromStart = child->IntAttribute("VromStart"); + room.vromEnd = child->IntAttribute("VromEnd"); + + setRoomList->rooms.push_back(room); + } + + child = child->NextSiblingElement(); + } + + setRoomList->numRooms = setRoomList->rooms.size(); + return setRoomList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h index 6bf9eaa5c..c6e82dfa9 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h @@ -8,4 +8,10 @@ class SetRoomListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetRoomListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp index 291ae578c..9147989dd 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h" #include "soh/resource/type/scenecommand/SetSkyboxModifier.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -12,6 +13,22 @@ std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shar setSkyboxModifier->modifier.skyboxDisabled = reader->ReadInt8(); setSkyboxModifier->modifier.sunMoonDisabled = reader->ReadInt8(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogSkyboxModifierAsXML(setSkyboxModifier); + } + + return setSkyboxModifier; +} + +std::shared_ptr SetSkyboxModifierFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setSkyboxModifier = std::make_shared(initData); + + setSkyboxModifier->cmdId = SceneCommandID::SetSkyboxModifier; + + setSkyboxModifier->modifier.skyboxDisabled = reader->IntAttribute("SkyboxDisabled"); + setSkyboxModifier->modifier.sunMoonDisabled = reader->IntAttribute("SunMoonDisabled"); + return setSkyboxModifier; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h index d467cc73d..cbd260ecc 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h @@ -8,4 +8,10 @@ class SetSkyboxModifierFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetSkyboxModifierFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp index f3e726b07..7f9f4d3d0 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h" #include "soh/resource/type/scenecommand/SetSkyboxSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -14,6 +15,24 @@ std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shar setSkyboxSettings->settings.weather = reader->ReadInt8(); setSkyboxSettings->settings.indoors = reader->ReadInt8(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogSkyboxSettingsAsXML(setSkyboxSettings); + } + + return setSkyboxSettings; +} + +std::shared_ptr SetSkyboxSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setSkyboxSettings = std::make_shared(initData); + + setSkyboxSettings->cmdId = SceneCommandID::SetSkyboxSettings; + + setSkyboxSettings->settings.unk = reader->IntAttribute("Unknown"); + setSkyboxSettings->settings.skyboxId = reader->IntAttribute("SkyboxId"); + setSkyboxSettings->settings.weather = reader->IntAttribute("Weather"); + setSkyboxSettings->settings.indoors = reader->IntAttribute("Indoors"); + return setSkyboxSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h index 581e56122..6bc668667 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h @@ -8,4 +8,10 @@ class SetSkyboxSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetSkyboxSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp index f85178e22..46d81c074 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetSoundSettingsFactory.h" #include "soh/resource/type/scenecommand/SetSoundSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -13,6 +14,23 @@ std::shared_ptr SetSoundSettingsFactory::ReadResource(std::share setSoundSettings->settings.natureAmbienceId = reader->ReadInt8(); setSoundSettings->settings.seqId = reader->ReadInt8(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogSoundSettingsAsXML(setSoundSettings); + } + + return setSoundSettings; +} + +std::shared_ptr SetSoundSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setSoundSettings = std::make_shared(initData); + + setSoundSettings->cmdId = SceneCommandID::SetSoundSettings; + + setSoundSettings->settings.reverb = reader->IntAttribute("Reverb"); + setSoundSettings->settings.natureAmbienceId = reader->IntAttribute("NatureAmbienceId"); + setSoundSettings->settings.seqId = reader->IntAttribute("SeqId"); + return setSoundSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h index e1c4efb03..fa6f0ac2f 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h @@ -8,4 +8,10 @@ class SetSoundSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetSoundSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp index b7fd21aa4..b90aa9c9d 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h" #include "soh/resource/type/scenecommand/SetSpecialObjects.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -12,6 +13,22 @@ std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shar setSpecialObjects->specialObjects.elfMessage = reader->ReadInt8(); setSpecialObjects->specialObjects.globalObject = reader->ReadInt16(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogSpecialObjectsAsXML(setSpecialObjects); + } + + return setSpecialObjects; +} + +std::shared_ptr SetSpecialObjectsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setSpecialObjects = std::make_shared(initData); + + setSpecialObjects->cmdId = SceneCommandID::SetSpecialObjects; + + setSpecialObjects->specialObjects.elfMessage = reader->IntAttribute("ElfMessage"); + setSpecialObjects->specialObjects.globalObject = reader->IntAttribute("GlobalObject"); + return setSpecialObjects; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h index 503cfb61f..47b30bafc 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h @@ -8,4 +8,10 @@ class SetSpecialObjectsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetSpecialObjectsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp index 3165b4361..abfa6f807 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetStartPositionListFactory.h" #include "soh/resource/type/scenecommand/SetStartPositionList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -26,6 +27,41 @@ std::shared_ptr SetStartPositionListFactory::ReadResource(std::s setStartPositionList->startPositions.push_back(entry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogStartPositionListAsXML(setStartPositionList); + } + + return setStartPositionList; +} + +std::shared_ptr SetStartPositionListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setStartPositionList = std::make_shared(initData); + + setStartPositionList->cmdId = SceneCommandID::SetStartPositionList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "StartPositionEntry") { + ActorEntry entry; + entry.id = child->IntAttribute("Id"); + entry.pos.x = child->IntAttribute("PosX"); + entry.pos.y = child->IntAttribute("PosY"); + entry.pos.z = child->IntAttribute("PosZ"); + entry.rot.x = child->IntAttribute("RotX"); + entry.rot.y = child->IntAttribute("RotY"); + entry.rot.z = child->IntAttribute("RotZ"); + entry.params = child->IntAttribute("Params"); + setStartPositionList->startPositions.push_back(entry); + } + + child = child->NextSiblingElement(); + } + + setStartPositionList->numStartPositions = setStartPositionList->startPositions.size(); + return setStartPositionList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h index b07901f05..4e381036a 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h @@ -8,4 +8,10 @@ class SetStartPositionListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetStartPositionListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp index d83b24583..8e54e4573 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetTimeSettingsFactory.h" #include "soh/resource/type/scenecommand/SetTimeSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -13,6 +14,23 @@ SetTimeSettingsFactory::ReadResource(std::shared_ptr init setTimeSettings->settings.minute = reader->ReadInt8(); setTimeSettings->settings.timeIncrement = reader->ReadInt8(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogTimeSettingsAsXML(setTimeSettings); + } + + return setTimeSettings; +} + +std::shared_ptr SetTimeSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setTimeSettings = std::make_shared(initData); + + setTimeSettings->cmdId = SceneCommandID::SetTimeSettings; + + setTimeSettings->settings.hour = reader->IntAttribute("Hour"); + setTimeSettings->settings.minute = reader->IntAttribute("Minute"); + setTimeSettings->settings.timeIncrement = reader->IntAttribute("TimeIncrement"); + return setTimeSettings; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h index d1336f788..ff3fdda37 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h @@ -8,4 +8,10 @@ class SetTimeSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetTimeSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp index c751ad611..5bf1a114d 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetTransitionActorListFactory.h" #include "soh/resource/type/scenecommand/SetTransitionActorList.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -28,6 +29,43 @@ std::shared_ptr SetTransitionActorListFactory::ReadResource(std: setTransitionActorList->transitionActorList.push_back(entry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogTransitionActorListAsXML(setTransitionActorList); + } + + return setTransitionActorList; +} + +std::shared_ptr SetTransitionActorListFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setTransitionActorList = std::make_shared(initData); + + setTransitionActorList->cmdId = SceneCommandID::SetTransitionActorList; + + auto child = reader->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "TransitionActorEntry") { + TransitionActorEntry entry; + entry.sides[0].room = child->IntAttribute("FrontSideRoom"); + entry.sides[0].effects = child->IntAttribute("FrontSideEffects"); + entry.sides[1].room = child->IntAttribute("BackSideRoom"); + entry.sides[1].effects = child->IntAttribute("BackSideEffects"); + entry.id = child->IntAttribute("Id"); + entry.pos.x = child->IntAttribute("PosX"); + entry.pos.y = child->IntAttribute("PosY"); + entry.pos.z = child->IntAttribute("PosZ"); + entry.rotY = child->IntAttribute("RotY"); + entry.params = child->IntAttribute("Params"); + setTransitionActorList->transitionActorList.push_back(entry); + } + + child = child->NextSiblingElement(); + } + + setTransitionActorList->numTransitionActors = setTransitionActorList->transitionActorList.size(); + return setTransitionActorList; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h index c8fb65f9a..eaeb2b5ec 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h @@ -8,4 +8,10 @@ class SetTransitionActorListFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetTransitionActorListFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp index 3208004ce..77991b12c 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/scenecommand/SetWindSettingsFactory.h" #include "soh/resource/type/scenecommand/SetWindSettings.h" +#include "soh/resource/logging/SceneCommandLoggers.h" #include "spdlog/spdlog.h" namespace SOH { @@ -14,6 +15,24 @@ SetWindSettingsFactory::ReadResource(std::shared_ptr init setWind->settings.windSouth = reader->ReadInt8(); setWind->settings.windSpeed = reader->ReadUByte(); + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogWindSettingsAsXML(setWind); + } + + return setWind; +} + +std::shared_ptr SetWindSettingsFactoryXML::ReadResource(std::shared_ptr initData, + tinyxml2::XMLElement* reader) { + auto setWind = std::make_shared(initData); + + setWind->cmdId = SceneCommandID::SetWind; + + setWind->settings.windWest = reader->IntAttribute("WindWest"); + setWind->settings.windVertical = reader->IntAttribute("WindVertical"); + setWind->settings.windSouth = reader->IntAttribute("WindSouth"); + setWind->settings.windSpeed = reader->IntAttribute("WindSpeed"); + return setWind; } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h index 6cc9fbc1b..bab55dbd9 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h @@ -8,4 +8,10 @@ class SetWindSettingsFactory : public SceneCommandFactoryBinaryV0 { std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; + +class SetWindSettingsFactoryXML : public SceneCommandFactoryXMLV0 { + public: + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; +}; } // namespace SOH diff --git a/soh/soh/resource/logging/SceneCommandLoggers.cpp b/soh/soh/resource/logging/SceneCommandLoggers.cpp new file mode 100644 index 000000000..b1eeb554d --- /dev/null +++ b/soh/soh/resource/logging/SceneCommandLoggers.cpp @@ -0,0 +1,603 @@ +#include "soh/resource/type/scenecommand/EndMarker.h" +#include "soh/resource/type/scenecommand/SetActorList.h" +#include "soh/resource/type/scenecommand/SetAlternateHeaders.h" +#include "soh/resource/type/scenecommand/SetCameraSettings.h" +#include "soh/resource/type/scenecommand/SetCollisionHeader.h" +#include "soh/resource/type/scenecommand/SetCsCamera.h" +#include "soh/resource/type/scenecommand/SetCutscenes.h" +#include "soh/resource/type/scenecommand/SetEchoSettings.h" +#include "soh/resource/type/scenecommand/SetEntranceList.h" +#include "soh/resource/type/scenecommand/SetExitList.h" +#include "soh/resource/type/scenecommand/SetLightingSettings.h" +#include "soh/resource/type/scenecommand/SetLightList.h" +#include "soh/resource/type/scenecommand/SetMesh.h" +#include "soh/resource/type/scenecommand/SetObjectList.h" +#include "soh/resource/type/scenecommand/SetPathways.h" +#include "soh/resource/type/scenecommand/SetRoomBehavior.h" +#include "soh/resource/type/scenecommand/SetRoomList.h" +#include "soh/resource/type/scenecommand/SetSkyboxModifier.h" +#include "soh/resource/type/scenecommand/SetSkyboxSettings.h" +#include "soh/resource/type/scenecommand/SetSoundSettings.h" +#include "soh/resource/type/scenecommand/SetSpecialObjects.h" +#include "soh/resource/type/scenecommand/SetStartPositionList.h" +#include "soh/resource/type/scenecommand/SetTimeSettings.h" +#include "soh/resource/type/scenecommand/SetTransitionActorList.h" +#include "soh/resource/type/scenecommand/SetWindSettings.h" +#include "spdlog/spdlog.h" + +namespace SOH { + +void LogEndMarkerAsXML(std::shared_ptr resource) { + std::shared_ptr endMarker = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("EndMarker"); + doc.InsertFirstChild(root); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogActorListAsXML(std::shared_ptr resource) { + std::shared_ptr setActorList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetActorList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setActorList->numActors; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("ActorEntry"); + entry->SetAttribute("Id", setActorList->actorList[i].id); + entry->SetAttribute("PosX", setActorList->actorList[i].pos.x); + entry->SetAttribute("PosY", setActorList->actorList[i].pos.y); + entry->SetAttribute("PosZ", setActorList->actorList[i].pos.z); + entry->SetAttribute("RotX", setActorList->actorList[i].rot.x); + entry->SetAttribute("RotY", setActorList->actorList[i].rot.y); + entry->SetAttribute("RotZ", setActorList->actorList[i].rot.z); + entry->SetAttribute("Params", setActorList->actorList[i].params); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogAlternateHeadersAsXML(std::shared_ptr resource) { + std::shared_ptr setAlternateHeaders = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetAlternateHeaders"); + doc.InsertFirstChild(root); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogCameraSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setCameraSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetCameraSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("CameraMovement", setCameraSettings->settings.cameraMovement); + root->SetAttribute("WorldMapArea", setCameraSettings->settings.worldMapArea); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogSetCollisionHeaderAsXML(std::shared_ptr resource) { + std::shared_ptr setCollisionHeader = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetCollisionHeader"); + doc.InsertFirstChild(root); + + root->SetAttribute("FileName", setCollisionHeader->fileName.c_str()); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogCsCameraAsXML(std::shared_ptr resource) { + std::shared_ptr setCsCamera = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetCsCamera"); + doc.InsertFirstChild(root); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogCutscenesAsXML(std::shared_ptr resource) { + std::shared_ptr setCutscenes = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetCutscenes"); + doc.InsertFirstChild(root); + + root->SetAttribute("FileName", setCutscenes->fileName.c_str()); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogEchoSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setEchoSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetEchoSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("Echo", setEchoSettings->settings.echo); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogEntranceListAsXML(std::shared_ptr resource) { + std::shared_ptr setEntranceList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetEntranceList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setEntranceList->numEntrances; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("EntranceEntry"); + entry->SetAttribute("Spawn", setEntranceList->entrances[i].spawn); + entry->SetAttribute("Room", setEntranceList->entrances[i].room); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogExitListAsXML(std::shared_ptr resource) { + std::shared_ptr setExitList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetExitList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setExitList->numExits; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("ExitEntry"); + entry->SetAttribute("Id", setExitList->exits[i]); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogLightingSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setLightingSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetLightingSettings"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setLightingSettings->settings.size(); i++) { + tinyxml2::XMLElement* entry = doc.NewElement("LightingSetting"); + entry->SetAttribute("AmbientColorR", setLightingSettings->settings[i].ambientColor[0]); + entry->SetAttribute("AmbientColorG", setLightingSettings->settings[i].ambientColor[1]); + entry->SetAttribute("AmbientColorB", setLightingSettings->settings[i].ambientColor[2]); + + entry->SetAttribute("Light1DirX", setLightingSettings->settings[i].light1Dir[0]); + entry->SetAttribute("Light1DirY", setLightingSettings->settings[i].light1Dir[1]); + entry->SetAttribute("Light1DirZ", setLightingSettings->settings[i].light1Dir[2]); + entry->SetAttribute("Light1ColorR", setLightingSettings->settings[i].light1Color[0]); + entry->SetAttribute("Light1ColorG", setLightingSettings->settings[i].light1Color[1]); + entry->SetAttribute("Light1ColorB", setLightingSettings->settings[i].light1Color[2]); + + entry->SetAttribute("Light2DirX", setLightingSettings->settings[i].light2Dir[0]); + entry->SetAttribute("Light2DirY", setLightingSettings->settings[i].light2Dir[1]); + entry->SetAttribute("Light2DirZ", setLightingSettings->settings[i].light2Dir[2]); + entry->SetAttribute("Light2ColorR", setLightingSettings->settings[i].light2Color[0]); + entry->SetAttribute("Light2ColorG", setLightingSettings->settings[i].light2Color[1]); + entry->SetAttribute("Light2ColorB", setLightingSettings->settings[i].light2Color[2]); + + entry->SetAttribute("FogColorR", setLightingSettings->settings[i].fogColor[0]); + entry->SetAttribute("FogColorG", setLightingSettings->settings[i].fogColor[1]); + entry->SetAttribute("FogColorB", setLightingSettings->settings[i].fogColor[2]); + entry->SetAttribute("FogNear", setLightingSettings->settings[i].fogNear); + entry->SetAttribute("FogFar", setLightingSettings->settings[i].fogFar); + + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogLightListAsXML(std::shared_ptr resource) { + std::shared_ptr setLightList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetLightList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setLightList->numLights; i++) { + tinyxml2::XMLElement* light = doc.NewElement("LightInfo"); + light->SetAttribute("Type", setLightList->lightList[i].type); + if (false/*setLightList->lightList[i].type == LIGHT_DIRECTIONAL*/) { + light->SetAttribute("X", setLightList->lightList[i].params.dir.x); + light->SetAttribute("Y", setLightList->lightList[i].params.dir.y); + light->SetAttribute("Z", setLightList->lightList[i].params.dir.z); + light->SetAttribute("ColorR", setLightList->lightList[i].params.dir.color[0]); + light->SetAttribute("ColorG", setLightList->lightList[i].params.dir.color[1]); + light->SetAttribute("ColorB", setLightList->lightList[i].params.dir.color[2]); + } else { + light->SetAttribute("X", setLightList->lightList[i].params.point.x); + light->SetAttribute("Y", setLightList->lightList[i].params.point.y); + light->SetAttribute("Z", setLightList->lightList[i].params.point.z); + light->SetAttribute("ColorR", setLightList->lightList[i].params.point.color[0]); + light->SetAttribute("ColorG", setLightList->lightList[i].params.point.color[1]); + light->SetAttribute("ColorB", setLightList->lightList[i].params.point.color[2]); + light->SetAttribute("DrawGlow", setLightList->lightList[i].params.point.drawGlow); + light->SetAttribute("Radius", setLightList->lightList[i].params.point.radius); + } + root->InsertEndChild(light); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogMeshAsXML(std::shared_ptr resource) { + std::shared_ptr setMesh = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetMesh"); + doc.InsertFirstChild(root); + + root->SetAttribute("Data", setMesh->data); + root->SetAttribute("MeshHeaderType", setMesh->meshHeader.base.type); + + if (setMesh->meshHeader.base.type == 0) { + root->SetAttribute("PolyNum", setMesh->meshHeader.polygon0.num); + PolygonDlist* dlist = (PolygonDlist*)setMesh->meshHeader.polygon0.start; + for (int i = 0; i < setMesh->meshHeader.polygon0.num; i += 1) { + tinyxml2::XMLElement* polygon = doc.NewElement("Polygon"); + polygon->SetAttribute("PolyType", "0"); + polygon->SetAttribute("MeshOpa", setMesh->opaPaths[i].c_str()); + polygon->SetAttribute("MeshXlu", setMesh->xluPaths[i].c_str()); + + root->InsertEndChild(polygon); + } + dlist += 1; + } else if (setMesh->meshHeader.base.type == 1) { + root->SetAttribute("PolyNum", "1"); + tinyxml2::XMLElement* polygon = doc.NewElement("Polygon"); + polygon->SetAttribute("Format", setMesh->meshHeader.polygon1.format); + polygon->SetAttribute("ImgOpa", ""); + polygon->SetAttribute("ImgXlu", ""); + + if (setMesh->meshHeader.polygon1.format == 1) { + polygon->SetAttribute("BgImageCount", "0"); + } else { + polygon->SetAttribute("BgImageCount", setMesh->meshHeader.polygon1.multi.count); + } + + polygon->SetAttribute("PolyType", "0"); + + polygon->SetAttribute("MeshOpa", setMesh->opaPaths[0].c_str()); + polygon->SetAttribute("MeshXlu", setMesh->xluPaths[0].c_str()); + + root->InsertEndChild(polygon); + + BgImage* image = setMesh->meshHeader.polygon1.multi.list; + int count = setMesh->meshHeader.polygon1.format == 1 ? 1 : setMesh->meshHeader.polygon1.multi.count; + for (int i = 0; i < count; i += 1) { + tinyxml2::XMLElement* bgImage = doc.NewElement("BgImage"); + if (setMesh->meshHeader.polygon1.format == 1) { + bgImage->SetAttribute("Unknown_00", image->unk_00); + bgImage->SetAttribute("Id", image->id); + bgImage->SetAttribute("ImagePath", setMesh->imagePaths[i].c_str()); + bgImage->SetAttribute("Unknown_0C", setMesh->meshHeader.polygon1.single.unk_0C); + bgImage->SetAttribute("TLUT", setMesh->meshHeader.polygon1.single.tlut); + bgImage->SetAttribute("Width", setMesh->meshHeader.polygon1.single.width); + bgImage->SetAttribute("Height", setMesh->meshHeader.polygon1.single.height); + bgImage->SetAttribute("Fmt", setMesh->meshHeader.polygon1.single.fmt); + bgImage->SetAttribute("Siz", setMesh->meshHeader.polygon1.single.siz); + bgImage->SetAttribute("Mode0", setMesh->meshHeader.polygon1.single.mode0); + bgImage->SetAttribute("TLUTCount", setMesh->meshHeader.polygon1.single.tlutCount); + } else { + bgImage->SetAttribute("Unknown_00", image->unk_00); + bgImage->SetAttribute("Id", image->id); + bgImage->SetAttribute("ImagePath", setMesh->imagePaths[i].c_str()); + bgImage->SetAttribute("Unknown_0C", image->unk_0C); + bgImage->SetAttribute("TLUT", image->tlut); + bgImage->SetAttribute("Width", image->width); + bgImage->SetAttribute("Height", image->height); + bgImage->SetAttribute("Fmt", image->fmt); + bgImage->SetAttribute("Siz", image->siz); + bgImage->SetAttribute("Mode0", image->mode0); + bgImage->SetAttribute("TLUTCount", image->tlutCount); + } + polygon->InsertEndChild(bgImage); + + image += 1; + } + } else if (setMesh->meshHeader.base.type == 2) { + root->SetAttribute("PolyNum", setMesh->meshHeader.polygon2.num); + PolygonDlist2* dlist = (PolygonDlist2*)setMesh->meshHeader.polygon2.start; + for (int i = 0; i < setMesh->meshHeader.polygon2.num; i += 1) { + tinyxml2::XMLElement* polygon = doc.NewElement("Polygon"); + polygon->SetAttribute("PolyType", "0"); + + polygon->SetAttribute("PosX", dlist->pos.x); + polygon->SetAttribute("PosY", dlist->pos.y); + polygon->SetAttribute("PosZ", dlist->pos.z); + polygon->SetAttribute("Unknown", dlist->unk_06); + + polygon->SetAttribute("MeshOpa", setMesh->opaPaths[i].c_str()); + polygon->SetAttribute("MeshXlu", setMesh->xluPaths[i].c_str()); + + root->InsertEndChild(polygon); + dlist += 1; + } + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogObjectListAsXML(std::shared_ptr resource) { + std::shared_ptr setObjectList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetObjectList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setObjectList->numObjects; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("ObjectEntry"); + entry->SetAttribute("Id", setObjectList->objects[i]); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogPathwaysAsXML(std::shared_ptr resource) { + std::shared_ptr setPathways = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetPathways"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setPathways->pathFileNames.size(); i++) { + tinyxml2::XMLElement* pathway = doc.NewElement("Pathway"); + pathway->SetAttribute("FilePath", setPathways->pathFileNames[i].c_str()); + root->InsertEndChild(pathway); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogRoomBehaviorAsXML(std::shared_ptr resource) { + std::shared_ptr setRoomBehavior = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetRoomBehavior"); + doc.InsertFirstChild(root); + + root->SetAttribute("GameplayFlags1", setRoomBehavior->roomBehavior.gameplayFlags); + root->SetAttribute("GameplayFlags2", setRoomBehavior->roomBehavior.gameplayFlags2); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogRoomListAsXML(std::shared_ptr resource) { + std::shared_ptr setRoomList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetRoomList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setRoomList->numRooms; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("RoomEntry"); + entry->SetAttribute("Path", setRoomList->fileNames[i].c_str()); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogSkyboxModifierAsXML(std::shared_ptr resource) { + std::shared_ptr setSkyboxModifier = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetSkyboxModifier"); + doc.InsertFirstChild(root); + + root->SetAttribute("SkyboxDisabled", setSkyboxModifier->modifier.skyboxDisabled); + root->SetAttribute("SunMoonDisabled", setSkyboxModifier->modifier.sunMoonDisabled); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogSkyboxSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setSkyboxSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetSkyboxSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("Unknown", setSkyboxSettings->settings.unk); + root->SetAttribute("SkyboxId", setSkyboxSettings->settings.skyboxId); + root->SetAttribute("Weather", setSkyboxSettings->settings.weather); + root->SetAttribute("Indoors", setSkyboxSettings->settings.indoors); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogSoundSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setSoundSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetSoundSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("Reverb", setSoundSettings->settings.reverb); + root->SetAttribute("NatureAmbienceId", setSoundSettings->settings.natureAmbienceId); + root->SetAttribute("SeqId", setSoundSettings->settings.seqId); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogSpecialObjectsAsXML(std::shared_ptr resource) { + std::shared_ptr setSpecialObjects = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetSpecialObjects"); + doc.InsertFirstChild(root); + + root->SetAttribute("ElfMessage", setSpecialObjects->specialObjects.elfMessage); + root->SetAttribute("GlobalObject", setSpecialObjects->specialObjects.globalObject); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogStartPositionListAsXML(std::shared_ptr resource) { + std::shared_ptr setStartPositionList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetStartPositionList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setStartPositionList->numStartPositions; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("StartPositionEntry"); + entry->SetAttribute("Id", setStartPositionList->startPositions[i].id); + entry->SetAttribute("PosX", setStartPositionList->startPositions[i].pos.x); + entry->SetAttribute("PosY", setStartPositionList->startPositions[i].pos.y); + entry->SetAttribute("PosZ", setStartPositionList->startPositions[i].pos.z); + entry->SetAttribute("RotX", setStartPositionList->startPositions[i].rot.x); + entry->SetAttribute("RotY", setStartPositionList->startPositions[i].rot.y); + entry->SetAttribute("RotZ", setStartPositionList->startPositions[i].rot.z); + entry->SetAttribute("Params", setStartPositionList->startPositions[i].params); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogTimeSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setTimeSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetTimeSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("Hour", setTimeSettings->settings.hour); + root->SetAttribute("Minute", setTimeSettings->settings.minute); + root->SetAttribute("TimeIncrement", setTimeSettings->settings.timeIncrement); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogTransitionActorListAsXML(std::shared_ptr resource) { + std::shared_ptr setTransitionActorList = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetTransitionActorList"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < setTransitionActorList->numTransitionActors; i++) { + tinyxml2::XMLElement* entry = doc.NewElement("TransitionActorEntry"); + entry->SetAttribute("FrontSideRoom", setTransitionActorList->transitionActorList[i].sides[0].room); + entry->SetAttribute("FrontSideEffects", setTransitionActorList->transitionActorList[i].sides[0].effects); + entry->SetAttribute("BackSideRoom", setTransitionActorList->transitionActorList[i].sides[1].room); + entry->SetAttribute("BackSideEffects", setTransitionActorList->transitionActorList[i].sides[1].effects); + entry->SetAttribute("Id", setTransitionActorList->transitionActorList[i].id); + entry->SetAttribute("PosX", setTransitionActorList->transitionActorList[i].pos.x); + entry->SetAttribute("PosY", setTransitionActorList->transitionActorList[i].pos.y); + entry->SetAttribute("PosZ", setTransitionActorList->transitionActorList[i].pos.z); + entry->SetAttribute("RotY", setTransitionActorList->transitionActorList[i].rotY); + entry->SetAttribute("Params", setTransitionActorList->transitionActorList[i].params); + root->InsertEndChild(entry); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +void LogWindSettingsAsXML(std::shared_ptr resource) { + std::shared_ptr setWindSettings = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("SetWindSettings"); + doc.InsertFirstChild(root); + + root->SetAttribute("WindWest", setWindSettings->settings.windWest); + root->SetAttribute("WindVertical", setWindSettings->settings.windVertical); + root->SetAttribute("WindSouth", setWindSettings->settings.windSouth); + root->SetAttribute("WindSpeed", setWindSettings->settings.windSpeed); + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); +} + +} //namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/logging/SceneCommandLoggers.h b/soh/soh/resource/logging/SceneCommandLoggers.h new file mode 100644 index 000000000..1351a5c77 --- /dev/null +++ b/soh/soh/resource/logging/SceneCommandLoggers.h @@ -0,0 +1,32 @@ +#include "Resource.h" +#include "soh/OTRGlobals.h" + +namespace SOH { + +void LogEndMarkerAsXML(std::shared_ptr resource); +void LogActorListAsXML(std::shared_ptr resource); +void LogAlternateHeadersAsXML(std::shared_ptr resource); +void LogCameraSettingsAsXML(std::shared_ptr resource); +void LogSetCollisionHeaderAsXML(std::shared_ptr resource); +void LogCsCameraAsXML(std::shared_ptr resource); +void LogCutscenesAsXML(std::shared_ptr resource); +void LogEchoSettingsAsXML(std::shared_ptr resource); +void LogEntranceListAsXML(std::shared_ptr resource); +void LogExitListAsXML(std::shared_ptr resource); +void LogLightingSettingsAsXML(std::shared_ptr resource); +void LogLightListAsXML(std::shared_ptr resource); +void LogMeshAsXML(std::shared_ptr resource); +void LogObjectListAsXML(std::shared_ptr resource); +void LogPathwaysAsXML(std::shared_ptr resource); +void LogRoomBehaviorAsXML(std::shared_ptr resource); +void LogRoomListAsXML(std::shared_ptr resource); +void LogSkyboxModifierAsXML(std::shared_ptr resource); +void LogSkyboxSettingsAsXML(std::shared_ptr resource); +void LogSoundSettingsAsXML(std::shared_ptr resource); +void LogSpecialObjectsAsXML(std::shared_ptr resource); +void LogStartPositionListAsXML(std::shared_ptr resource); +void LogTimeSettingsAsXML(std::shared_ptr resource); +void LogTransitionActorListAsXML(std::shared_ptr resource); +void LogWindSettingsAsXML(std::shared_ptr resource); + +} //namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/scenecommand/SetMesh.h b/soh/soh/resource/type/scenecommand/SetMesh.h index 33ab24202..5d4f99c6b 100644 --- a/soh/soh/resource/type/scenecommand/SetMesh.h +++ b/soh/soh/resource/type/scenecommand/SetMesh.h @@ -94,6 +94,8 @@ class SetMesh : public SceneCommand { uint8_t data; uint8_t meshHeaderType; + std::vector opaPaths; + std::vector xluPaths; std::vector dlists; std::vector dlists2; std::vector imagePaths; diff --git a/soh/soh/resource/type/scenecommand/SetPathways.h b/soh/soh/resource/type/scenecommand/SetPathways.h index cf875cf5e..9f22130a6 100644 --- a/soh/soh/resource/type/scenecommand/SetPathways.h +++ b/soh/soh/resource/type/scenecommand/SetPathways.h @@ -18,6 +18,7 @@ class SetPathways : public SceneCommand { size_t GetPointerSize(); uint32_t numPaths; + std::vector pathFileNames; std::vector paths; }; }; // namespace LUS From 552bb2886f79aa602250a947b52b1d56c3b33262 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:36:44 -0400 Subject: [PATCH 197/300] support lus renamespacing (#4075) --- libultraship | 2 +- .../Enhancements/audio/AudioCollection.cpp | 4 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 30 +- soh/soh/Enhancements/audio/AudioEditor.h | 4 +- soh/soh/Enhancements/controls/InputViewer.cpp | 84 ++--- soh/soh/Enhancements/controls/InputViewer.h | 8 +- .../controls/SohInputEditorWindow.cpp | 322 +++++++++--------- .../controls/SohInputEditorWindow.h | 16 +- .../cosmetics/CosmeticsEditor.cpp | 46 +-- .../Enhancements/cosmetics/CosmeticsEditor.h | 2 +- soh/soh/Enhancements/debugconsole.cpp | 218 ++++++------ soh/soh/Enhancements/debugger/MessageViewer.h | 2 +- soh/soh/Enhancements/debugger/actorViewer.h | 2 +- soh/soh/Enhancements/debugger/colViewer.h | 2 +- .../Enhancements/debugger/debugSaveEditor.cpp | 46 +-- .../Enhancements/debugger/debugSaveEditor.h | 2 +- soh/soh/Enhancements/debugger/dlViewer.cpp | 4 +- soh/soh/Enhancements/debugger/dlViewer.h | 2 +- soh/soh/Enhancements/debugger/valueViewer.h | 2 +- .../GameInteractor_RawAction.cpp | 2 +- .../game-interactor/GameInteractor_Sail.cpp | 4 +- soh/soh/Enhancements/gameplaystatswindow.h | 2 +- soh/soh/Enhancements/mods.cpp | 2 +- soh/soh/Enhancements/presets.cpp | 2 +- .../randomizer/3drando/rando_main.cpp | 2 +- .../randomizer/3drando/spoiler_log.cpp | 6 +- .../Enhancements/randomizer/randomizer.cpp | 16 +- .../randomizer/randomizer_check_tracker.cpp | 2 +- .../randomizer/randomizer_check_tracker.h | 8 +- .../randomizer/randomizer_entrance_tracker.h | 2 +- .../randomizer/randomizer_item_tracker.cpp | 18 +- .../randomizer/randomizer_item_tracker.h | 4 +- .../randomizer/randomizer_settings_window.h | 2 +- .../resolution-editor/ResolutionEditor.cpp | 4 +- .../resolution-editor/ResolutionEditor.h | 4 +- soh/soh/Enhancements/savestates.cpp | 10 +- soh/soh/Enhancements/tts/tts.cpp | 20 +- soh/soh/OTRGlobals.cpp | 140 ++++---- soh/soh/OTRGlobals.h | 2 +- soh/soh/SaveManager.cpp | 14 +- soh/soh/SohGui.cpp | 10 +- soh/soh/SohMenuBar.cpp | 126 +++---- soh/soh/SohMenuBar.h | 4 +- soh/soh/SohModals.h | 4 +- soh/soh/UIWidgets.cpp | 20 +- soh/soh/config/ConfigUpdaters.cpp | 10 +- soh/soh/config/ConfigUpdaters.h | 10 +- .../resource/importer/AnimationFactory.cpp | 4 +- soh/soh/resource/importer/AnimationFactory.h | 4 +- .../resource/importer/AudioSampleFactory.cpp | 6 +- .../resource/importer/AudioSampleFactory.h | 4 +- .../importer/AudioSequenceFactory.cpp | 4 +- .../resource/importer/AudioSequenceFactory.h | 4 +- .../importer/AudioSoundFontFactory.cpp | 14 +- .../resource/importer/AudioSoundFontFactory.h | 4 +- .../resource/importer/BackgroundFactory.cpp | 4 +- soh/soh/resource/importer/BackgroundFactory.h | 4 +- .../importer/CollisionHeaderFactory.cpp | 6 +- .../importer/CollisionHeaderFactory.h | 8 +- soh/soh/resource/importer/CutsceneFactory.cpp | 18 +- soh/soh/resource/importer/CutsceneFactory.h | 4 +- soh/soh/resource/importer/PathFactory.cpp | 4 +- soh/soh/resource/importer/PathFactory.h | 4 +- .../importer/PlayerAnimationFactory.cpp | 4 +- .../importer/PlayerAnimationFactory.h | 4 +- soh/soh/resource/importer/SceneFactory.cpp | 16 +- soh/soh/resource/importer/SceneFactory.h | 12 +- soh/soh/resource/importer/SkeletonFactory.cpp | 10 +- soh/soh/resource/importer/SkeletonFactory.h | 8 +- .../resource/importer/SkeletonLimbFactory.cpp | 6 +- .../resource/importer/SkeletonLimbFactory.h | 8 +- soh/soh/resource/importer/TextFactory.cpp | 6 +- soh/soh/resource/importer/TextFactory.h | 8 +- .../scenecommand/EndMarkerFactory.cpp | 6 +- .../importer/scenecommand/EndMarkerFactory.h | 6 +- .../scenecommand/SceneCommandFactory.cpp | 2 +- .../scenecommand/SceneCommandFactory.h | 6 +- .../scenecommand/SetActorListFactory.cpp | 6 +- .../scenecommand/SetActorListFactory.h | 8 +- .../SetAlternateHeadersFactory.cpp | 10 +- .../scenecommand/SetAlternateHeadersFactory.h | 8 +- .../scenecommand/SetCameraSettingsFactory.cpp | 6 +- .../scenecommand/SetCameraSettingsFactory.h | 8 +- .../SetCollisionHeaderFactory.cpp | 10 +- .../scenecommand/SetCollisionHeaderFactory.h | 8 +- .../scenecommand/SetCsCameraFactory.cpp | 6 +- .../scenecommand/SetCsCameraFactory.h | 8 +- .../scenecommand/SetCutscenesFactory.cpp | 10 +- .../scenecommand/SetCutscenesFactory.h | 8 +- .../scenecommand/SetEchoSettingsFactory.cpp | 6 +- .../scenecommand/SetEchoSettingsFactory.h | 8 +- .../scenecommand/SetEntranceListFactory.cpp | 6 +- .../scenecommand/SetEntranceListFactory.h | 8 +- .../scenecommand/SetExitListFactory.cpp | 6 +- .../scenecommand/SetExitListFactory.h | 8 +- .../scenecommand/SetLightListFactory.cpp | 6 +- .../scenecommand/SetLightListFactory.h | 8 +- .../SetLightingSettingsFactory.cpp | 6 +- .../scenecommand/SetLightingSettingsFactory.h | 8 +- .../importer/scenecommand/SetMeshFactory.cpp | 38 +-- .../importer/scenecommand/SetMeshFactory.h | 8 +- .../scenecommand/SetObjectListFactory.cpp | 6 +- .../scenecommand/SetObjectListFactory.h | 8 +- .../scenecommand/SetPathwaysFactory.cpp | 10 +- .../scenecommand/SetPathwaysFactory.h | 8 +- .../scenecommand/SetRoomBehaviorFactory.cpp | 6 +- .../scenecommand/SetRoomBehaviorFactory.h | 8 +- .../scenecommand/SetRoomListFactory.cpp | 6 +- .../scenecommand/SetRoomListFactory.h | 8 +- .../scenecommand/SetSkyboxModifierFactory.cpp | 6 +- .../scenecommand/SetSkyboxModifierFactory.h | 8 +- .../scenecommand/SetSkyboxSettingsFactory.cpp | 6 +- .../scenecommand/SetSkyboxSettingsFactory.h | 8 +- .../scenecommand/SetSoundSettingsFactory.cpp | 6 +- .../scenecommand/SetSoundSettingsFactory.h | 8 +- .../scenecommand/SetSpecialObjectsFactory.cpp | 6 +- .../scenecommand/SetSpecialObjectsFactory.h | 8 +- .../SetStartPositionListFactory.cpp | 6 +- .../SetStartPositionListFactory.h | 8 +- .../scenecommand/SetTimeSettingsFactory.cpp | 6 +- .../scenecommand/SetTimeSettingsFactory.h | 8 +- .../SetTransitionActorListFactory.cpp | 6 +- .../SetTransitionActorListFactory.h | 8 +- .../scenecommand/SetWindSettingsFactory.cpp | 6 +- .../scenecommand/SetWindSettingsFactory.h | 8 +- .../resource/logging/SceneCommandLoggers.cpp | 50 +-- .../resource/logging/SceneCommandLoggers.h | 50 +-- soh/soh/resource/type/Animation.h | 4 +- soh/soh/resource/type/AudioSample.h | 4 +- soh/soh/resource/type/AudioSequence.h | 4 +- soh/soh/resource/type/AudioSoundFont.h | 4 +- soh/soh/resource/type/Background.h | 4 +- soh/soh/resource/type/CollisionHeader.h | 4 +- soh/soh/resource/type/Cutscene.h | 4 +- soh/soh/resource/type/Path.h | 4 +- soh/soh/resource/type/PlayerAnimation.h | 4 +- soh/soh/resource/type/Scene.h | 4 +- soh/soh/resource/type/Skeleton.cpp | 10 +- soh/soh/resource/type/Skeleton.h | 4 +- soh/soh/resource/type/SkeletonLimb.h | 4 +- soh/soh/resource/type/Text.h | 4 +- .../resource/type/scenecommand/SceneCommand.h | 4 +- soh/soh/z_message_OTR.cpp | 8 +- soh/soh/z_play_otr.cpp | 6 +- soh/soh/z_scene_otr.cpp | 4 +- 145 files changed, 1007 insertions(+), 1007 deletions(-) diff --git a/libultraship b/libultraship index 85f6de497..6f978e0d2 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 85f6de497f6d375390cc3b4ba55eae5ef9c1b153 +Subproject commit 6f978e0d237530f304ba2018bbdc539b175c184a diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index d637758a8..8f9c01d0a 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -388,7 +388,7 @@ void AudioCollection::RemoveFromShufflePool(SequenceInfo* seqInfo) { excludedSequences.insert(seqInfo); includedSequences.erase(seqInfo); CVarSetInteger(cvarKey.c_str(), 1); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) { @@ -396,7 +396,7 @@ void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) { includedSequences.insert(seqInfo); excludedSequences.erase(seqInfo); CVarClear(cvarKey.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } void AudioCollection::InitializeShufflePool() { diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index e27de6b56..f33f73b3d 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -203,7 +203,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); ResetGroup(map, type); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { ReplayCurrentBGM(); @@ -214,7 +214,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); RandomizeGroup(type); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { ReplayCurrentBGM(); @@ -225,7 +225,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); LockGroup(map, type); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { ReplayCurrentBGM(); @@ -236,7 +236,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN); auto prevReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); UnlockGroup(map, type); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); auto curReplacement = AudioCollection::Instance->GetReplacementSequence(currentBGM); if (type == SEQ_BGM_WORLD && prevReplacement != curReplacement) { ReplayCurrentBGM(); @@ -281,7 +281,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { if (ImGui::Selectable(seqData.label.c_str())) { CVarSetInteger(cvarKey.c_str(), value); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); UpdateCurrentBGM(defaultValue, type); } @@ -301,7 +301,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { if (ImGui::Button(resetButton.c_str())) { CVarClear(cvarKey.c_str()); CVarClear(cvarLockKey.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); UpdateCurrentBGM(defaultValue, seqData.category); } UIWidgets::Tooltip("Reset to default"); @@ -322,7 +322,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { if (locked) { CVarClear(cvarLockKey.c_str()); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); UpdateCurrentBGM(defaultValue, type); } } @@ -335,7 +335,7 @@ void Draw_SfxTab(const std::string& tabId, SeqType type) { } else { CVarSetInteger(cvarLockKey.c_str(), 1); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } UIWidgets::Tooltip(locked ? "Sound locked" : "Sound unlocked"); } @@ -521,7 +521,7 @@ void AudioEditor::DrawElement() { const std::string resetButton = "Reset##linkVoiceFreqMultiplier"; if (ImGui::Button(resetButton.c_str())) { CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); @@ -710,14 +710,14 @@ void AudioEditor_RandomizeAll() { RandomizeGroup(type); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ReplayCurrentBGM(); } void AudioEditor_RandomizeGroup(SeqType group) { RandomizeGroup(group); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ReplayCurrentBGM(); } @@ -726,14 +726,14 @@ void AudioEditor_ResetAll() { ResetGroup(AudioCollection::Instance->GetAllSequences(), type); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ReplayCurrentBGM(); } void AudioEditor_ResetGroup(SeqType group) { ResetGroup(AudioCollection::Instance->GetAllSequences(), group); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ReplayCurrentBGM(); } @@ -742,7 +742,7 @@ void AudioEditor_LockAll() { LockGroup(AudioCollection::Instance->GetAllSequences(), type); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } void AudioEditor_UnlockAll() { @@ -750,5 +750,5 @@ void AudioEditor_UnlockAll() { UnlockGroup(AudioCollection::Instance->GetAllSequences(), type); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } diff --git a/soh/soh/Enhancements/audio/AudioEditor.h b/soh/soh/Enhancements/audio/AudioEditor.h index 38a681539..45c2654e5 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.h +++ b/soh/soh/Enhancements/audio/AudioEditor.h @@ -10,9 +10,9 @@ #include #include "AudioCollection.h" -class AudioEditor : public LUS::GuiWindow { +class AudioEditor : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; void DrawElement() override; void InitElement() override; diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index fb476e9aa..52b3527cc 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -47,14 +47,14 @@ void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTex // Render Outline based on settings if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) || (outlineMode == BUTTON_OUTLINE_PRESSED && state)) { - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size, + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } // Render button if pressed if (state) { ImGui::SetCursorPos(pos); ImGui::SetNextItemAllowOverlap(); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size, + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } } @@ -63,61 +63,61 @@ void InputViewer::DrawElement() { if (CVarGetInteger(CVAR_WINDOW("InputViewer"), 0)) { static bool sButtonTexturesLoaded = false; if (!sButtonTexturesLoaded) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( "Input-Viewer-Background", "textures/buttons/InputViewerBackground.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/StartBtn.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", "textures/buttons/AnalogStick.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/DPadLeft.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/DPadRight.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", "textures/buttons/ABtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", "textures/buttons/BBtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", "textures/buttons/LBtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", "textures/buttons/RBtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", "textures/buttons/ZBtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", "textures/buttons/StartBtnOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", "textures/buttons/CLeftOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", "textures/buttons/CRightOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", "textures/buttons/CUpOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", "textures/buttons/CDownOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", "textures/buttons/DPadRightOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", "textures/buttons/DPadUpOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); sButtonTexturesLoaded = true; } @@ -133,7 +133,7 @@ void InputViewer::DrawElement() { const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0); const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED); - ImVec2 bgSize = LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); + ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); ImGui::SetNextWindowSize(ImVec2( @@ -150,7 +150,7 @@ void InputViewer::DrawElement() { ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); - OSContPad* pads = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); + OSContPad* pads = Ship::Context::GetInstance()->GetControlDeck()->GetPads(); ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | @@ -168,7 +168,7 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); // Background ImGui::Image( - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"), + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"), scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } @@ -263,7 +263,7 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); ImGui::Image( - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"), + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"), scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } const int analogStickMode = @@ -274,7 +274,7 @@ void InputViewer::DrawElement() { ImGui::SetCursorPos( ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } @@ -287,7 +287,7 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); ImGui::Image( - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"), + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"), scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } const int rightStickMode = @@ -298,7 +298,7 @@ void InputViewer::DrawElement() { ImGui::SetCursorPos( ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } diff --git a/soh/soh/Enhancements/controls/InputViewer.h b/soh/soh/Enhancements/controls/InputViewer.h index 6f2e2c587..4d528ead4 100644 --- a/soh/soh/Enhancements/controls/InputViewer.h +++ b/soh/soh/Enhancements/controls/InputViewer.h @@ -15,9 +15,9 @@ typedef enum { STICK_MODE_ALWAYS_HIDDEN, } StickMode; -class InputViewer : public LUS::GuiWindow { +class InputViewer : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; void InitElement() override {}; void DrawElement() override; @@ -32,9 +32,9 @@ public: void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode); }; -class InputViewerSettingsWindow : public LUS::GuiWindow { +class InputViewerSettingsWindow : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; void InitElement() override {}; void DrawElement() override; diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 02781bf04..be71c7de1 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -57,7 +57,7 @@ void SohInputEditorWindow::UpdateElement() { } if (mInputEditorPopupOpen && ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopupId)) { - LUS::Context::GetInstance()->GetControlDeck()->BlockGameInput(INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID); + Ship::Context::GetInstance()->GetControlDeck()->BlockGameInput(INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID); // continue to block input for a third of a second after getting the mapping mGameInputBlockTimer = ImGui::GetIO().Framerate / 3; @@ -69,24 +69,24 @@ void SohInputEditorWindow::UpdateElement() { } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->BlockImGuiGamepadNavigation(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->BlockImGuiGamepadNavigation(); } else { if (mGameInputBlockTimer != INT32_MAX) { mGameInputBlockTimer--; if (mGameInputBlockTimer <= 0) { - LUS::Context::GetInstance()->GetControlDeck()->UnblockGameInput( + Ship::Context::GetInstance()->GetControlDeck()->UnblockGameInput( INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID); mGameInputBlockTimer = INT32_MAX; } } - if (LUS::Context::GetInstance()->GetWindow()->GetGui()->ImGuiGamepadNavigationEnabled()) { + if (Ship::Context::GetInstance()->GetWindow()->GetGui()->ImGuiGamepadNavigationEnabled()) { mMappingInputBlockTimer = ImGui::GetIO().Framerate / 3; } else { mMappingInputBlockTimer = INT32_MAX; } - LUS::Context::GetInstance()->GetWindow()->GetGui()->UnblockImGuiGamepadNavigation(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->UnblockImGuiGamepadNavigation(); } } @@ -176,26 +176,26 @@ void SohInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, fl #define BUTTON_COLOR_GAMEPAD_PURPLE ImVec4(0.431f, 0.369f, 0.706f, 0.5f) #define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f) -void SohInputEditorWindow::GetButtonColorsForLUSDeviceIndex(LUS::LUSDeviceIndex lusIndex, ImVec4& buttonColor, +void SohInputEditorWindow::GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor, ImVec4& buttonHoveredColor) { switch (lusIndex) { - case LUS::LUSDeviceIndex::Keyboard: + case Ship::ShipDeviceIndex::Keyboard: buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE; buttonHoveredColor = BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED; break; - case LUS::LUSDeviceIndex::Blue: + case Ship::ShipDeviceIndex::Blue: buttonColor = BUTTON_COLOR_GAMEPAD_BLUE; buttonHoveredColor = BUTTON_COLOR_GAMEPAD_BLUE_HOVERED; break; - case LUS::LUSDeviceIndex::Red: + case Ship::ShipDeviceIndex::Red: buttonColor = BUTTON_COLOR_GAMEPAD_RED; buttonHoveredColor = BUTTON_COLOR_GAMEPAD_RED_HOVERED; break; - case LUS::LUSDeviceIndex::Orange: + case Ship::ShipDeviceIndex::Orange: buttonColor = BUTTON_COLOR_GAMEPAD_ORANGE; buttonHoveredColor = BUTTON_COLOR_GAMEPAD_ORANGE_HOVERED; break; - case LUS::LUSDeviceIndex::Green: + case Ship::ShipDeviceIndex::Green: buttonColor = BUTTON_COLOR_GAMEPAD_GREEN; buttonHoveredColor = BUTTON_COLOR_GAMEPAD_GREEN_HOVERED; break; @@ -230,7 +230,7 @@ void SohInputEditorWindow::DrawButtonLineAddMappingButton(uint8_t port, uint16_t ImGui::CloseCurrentPopup(); } // todo: figure out why optional params (using id = "" in the definition) wasn't working - if (mMappingInputBlockTimer == INT32_MAX && LUS::Context::GetInstance() + if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetButton(bitmask) @@ -243,7 +243,7 @@ void SohInputEditorWindow::DrawButtonLineAddMappingButton(uint8_t port, uint16_t } void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_t bitmask, std::string id) { - auto mapping = LUS::Context::GetInstance() + auto mapping = Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetButton(bitmask) @@ -269,7 +269,7 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); auto physicalInputDisplayName = StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str()); - GetButtonColorsForLUSDeviceIndex(mapping->GetLUSDeviceIndex(), buttonColor, buttonHoveredColor); + GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); auto popupId = StringHelper::Sprintf("editButtonMappingPopup##%s", id.c_str()); @@ -292,7 +292,7 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ mInputEditorPopupOpen = false; ImGui::CloseCurrentPopup(); } - if (mMappingInputBlockTimer == INT32_MAX && LUS::Context::GetInstance() + if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetButton(bitmask) @@ -307,18 +307,18 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ ImGui::SameLine(0, 0); #ifndef __WIIU__ - auto sdlAxisDirectionToButtonMapping = std::dynamic_pointer_cast(mapping); - auto indexMapping = LUS::Context::GetInstance() + auto sdlAxisDirectionToButtonMapping = std::dynamic_pointer_cast(mapping); + auto indexMapping = Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() - ->GetDeviceIndexMappingFromLUSDeviceIndex(mapping->GetLUSDeviceIndex()); - auto sdlIndexMapping = std::dynamic_pointer_cast(indexMapping); + ->GetDeviceIndexMappingFromShipDeviceIndex(mapping->GetShipDeviceIndex()); + auto sdlIndexMapping = std::dynamic_pointer_cast(indexMapping); if (sdlIndexMapping != nullptr && sdlAxisDirectionToButtonMapping != nullptr) { ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(mapping->GetLUSDeviceIndex(), buttonColor, buttonHoveredColor); + GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); @@ -433,7 +433,7 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); if (ImGui::Button(StringHelper::Sprintf("%s###removeButtonMappingButton%s", ICON_FA_TIMES, id.c_str()).c_str(), ImVec2(ImGui::CalcTextSize(ICON_FA_TIMES).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) { - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetButton(bitmask) @@ -459,7 +459,7 @@ void SohInputEditorWindow::DrawButtonLine(const char* buttonName, uint8_t port, } void SohInputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, - LUS::Direction direction) { + Ship::Direction direction) { ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); auto popupId = StringHelper::Sprintf("addStickDirectionMappingPopup##%d-%d-%d", port, stick, direction); if (ImGui::Button( @@ -477,9 +477,9 @@ void SohInputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, mInputEditorPopupOpen = false; ImGui::CloseCurrentPopup(); } - if (stick == LUS::LEFT) { + if (stick == Ship::LEFT) { if (mMappingInputBlockTimer == INT32_MAX && - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetLeftStick() @@ -489,7 +489,7 @@ void SohInputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, } } else { if (mMappingInputBlockTimer == INT32_MAX && - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRightStick() @@ -502,16 +502,16 @@ void SohInputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, } void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, - LUS::Direction direction, std::string id) { - std::shared_ptr mapping = nullptr; - if (stick == LUS::LEFT) { - mapping = LUS::Context::GetInstance() + Ship::Direction direction, std::string id) { + std::shared_ptr mapping = nullptr; + if (stick == Ship::LEFT) { + mapping = Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetLeftStick() ->GetAxisDirectionMappingById(direction, id); } else { - mapping = LUS::Context::GetInstance() + mapping = Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRightStick() @@ -539,7 +539,7 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); auto physicalInputDisplayName = StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str()); - GetButtonColorsForLUSDeviceIndex(mapping->GetLUSDeviceIndex(), buttonColor, buttonHoveredColor); + GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); auto popupId = StringHelper::Sprintf("editStickDirectionMappingPopup##%s", id.c_str()); @@ -564,9 +564,9 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, ImGui::CloseCurrentPopup(); } - if (stick == LUS::LEFT) { + if (stick == Ship::LEFT) { if (mMappingInputBlockTimer == INT32_MAX && - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetLeftStick() @@ -576,7 +576,7 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, } } else { if (mMappingInputBlockTimer == INT32_MAX && - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRightStick() @@ -595,14 +595,14 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, if (ImGui::Button( StringHelper::Sprintf("%s###removeStickDirectionMappingButton%s", ICON_FA_TIMES, id.c_str()).c_str(), ImVec2(ImGui::CalcTextSize(ICON_FA_TIMES).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) { - if (stick == LUS::LEFT) { - LUS::Context::GetInstance() + if (stick == Ship::LEFT) { + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetLeftStick() ->ClearAxisDirectionMapping(direction, id); } else { - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRightStick() @@ -616,7 +616,7 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, } void SohInputEditorWindow::DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, - LUS::Direction direction, ImVec4 color = CHIP_COLOR_N64_GREY) { + Ship::Direction direction, ImVec4 color = CHIP_COLOR_N64_GREY) { ImGui::NewLine(); ImGui::SameLine(); ImGui::BeginDisabled(); @@ -634,21 +634,21 @@ void SohInputEditorWindow::DrawStickDirectionLine(const char* axisDirectionName, void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color = CHIP_COLOR_N64_GREY) { static int8_t sX, sY; - std::shared_ptr controllerStick = nullptr; - if (stick == LUS::LEFT) { - controllerStick = LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick(); + std::shared_ptr controllerStick = nullptr; + if (stick == Ship::LEFT) { + controllerStick = Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick(); } else { - controllerStick = LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick(); + controllerStick = Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick(); } controllerStick->Process(sX, sY); DrawAnalogPreview(StringHelper::Sprintf("##AnalogPreview%d", id).c_str(), ImVec2(sX, sY)); ImGui::SameLine(); ImGui::BeginGroup(); - DrawStickDirectionLine(ICON_FA_ARROW_UP, port, stick, LUS::UP, color); - DrawStickDirectionLine(ICON_FA_ARROW_DOWN, port, stick, LUS::DOWN, color); - DrawStickDirectionLine(ICON_FA_ARROW_LEFT, port, stick, LUS::LEFT, color); - DrawStickDirectionLine(ICON_FA_ARROW_RIGHT, port, stick, LUS::RIGHT, color); + DrawStickDirectionLine(ICON_FA_ARROW_UP, port, stick, Ship::UP, color); + DrawStickDirectionLine(ICON_FA_ARROW_DOWN, port, stick, Ship::DOWN, color); + DrawStickDirectionLine(ICON_FA_ARROW_LEFT, port, stick, Ship::LEFT, color); + DrawStickDirectionLine(ICON_FA_ARROW_RIGHT, port, stick, Ship::RIGHT, color); ImGui::EndGroup(); ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) { @@ -776,7 +776,7 @@ void SohInputEditorWindow::UpdateBitmaskToMappingIds(uint8_t port) { // todo: do we need this now that ControllerButton exists? for (auto [bitmask, button] : - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetAllButtons()) { + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetAllButtons()) { for (auto [id, mapping] : button->GetAllButtonMappings()) { // using a vector here instead of a set because i want newly added mappings // to go to the end of the list instead of autosorting @@ -791,12 +791,12 @@ void SohInputEditorWindow::UpdateBitmaskToMappingIds(uint8_t port) { void SohInputEditorWindow::UpdateStickDirectionToMappingIds(uint8_t port) { // todo: do we need this? for (auto stick : - { std::make_pair>( - LUS::LEFT, LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick()), - std::make_pair>( - LUS::RIGHT, - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick()) }) { - for (auto direction : { LUS::LEFT, LUS::RIGHT, LUS::UP, LUS::DOWN }) { + { std::make_pair>( + Ship::LEFT, Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLeftStick()), + std::make_pair>( + Ship::RIGHT, + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRightStick()) }) { + for (auto direction : { Ship::LEFT, Ship::RIGHT, Ship::UP, Ship::DOWN }) { for (auto [id, mapping] : stick.second->GetAllAxisDirectionMappingByDirection(direction)) { // using a vector here instead of a set because i want newly added mappings // to go to the end of the list instead of autosorting @@ -815,7 +815,7 @@ void SohInputEditorWindow::DrawRemoveRumbleMappingButton(uint8_t port, std::stri ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); if (ImGui::Button(StringHelper::Sprintf("%s###removeRumbleMapping%s", ICON_FA_TIMES, id.c_str()).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRumble()->ClearRumbleMapping(id); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetRumble()->ClearRumbleMapping(id); } ImGui::PopStyleVar(); } @@ -838,7 +838,7 @@ void SohInputEditorWindow::DrawAddRumbleMappingButton(uint8_t port) { ImGui::CloseCurrentPopup(); } - if (mMappingInputBlockTimer == INT32_MAX && LUS::Context::GetInstance() + if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRumble() @@ -855,7 +855,7 @@ bool SohInputEditorWindow::TestingRumble() { } void SohInputEditorWindow::DrawRumbleSection(uint8_t port) { - for (auto [id, mapping] : LUS::Context::GetInstance() + for (auto [id, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetRumble() @@ -864,7 +864,7 @@ void SohInputEditorWindow::DrawRumbleSection(uint8_t port) { ImGui::SetNextItemOpen(true, ImGuiCond_Once); auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(mapping->GetLUSDeviceIndex(), buttonColor, buttonHoveredColor); + GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor); // begin hackaround https://github.com/ocornut/imgui/issues/282#issuecomment-123763192 // spaces to have background color for text in a tree node std::string spaces = ""; @@ -998,7 +998,7 @@ void SohInputEditorWindow::DrawRemoveLEDMappingButton(uint8_t port, std::string ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); if (ImGui::Button(StringHelper::Sprintf("%s###removeLEDMapping%s", ICON_FA_TIMES, id.c_str()).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->ClearLEDMapping(id); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->ClearLEDMapping(id); } ImGui::PopStyleVar(); } @@ -1021,7 +1021,7 @@ void SohInputEditorWindow::DrawAddLEDMappingButton(uint8_t port) { ImGui::CloseCurrentPopup(); } - if (mMappingInputBlockTimer == INT32_MAX && LUS::Context::GetInstance() + if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetLED() @@ -1035,7 +1035,7 @@ void SohInputEditorWindow::DrawAddLEDMappingButton(uint8_t port) { void SohInputEditorWindow::DrawLEDSection(uint8_t port) { for (auto [id, mapping] : - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) { + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetLED()->GetAllLEDMappings()) { ImGui::AlignTextToFramePadding(); ImGui::SetNextItemOpen(true, ImGuiCond_Once); auto open = ImGui::TreeNode( @@ -1088,7 +1088,7 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { color.b = colorVec.z * 255.0; CVarSetColor24("gLedPort1Color", color); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::Text("Custom Color"); @@ -1116,7 +1116,7 @@ void SohInputEditorWindow::DrawRemoveGyroMappingButton(uint8_t port, std::string ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); if (ImGui::Button(StringHelper::Sprintf("%s###removeGyroMapping%s", ICON_FA_TIMES, id.c_str()).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->ClearGyroMapping(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->ClearGyroMapping(); } ImGui::PopStyleVar(); } @@ -1139,7 +1139,7 @@ void SohInputEditorWindow::DrawAddGyroMappingButton(uint8_t port) { ImGui::CloseCurrentPopup(); } - if (mMappingInputBlockTimer == INT32_MAX && LUS::Context::GetInstance() + if (mMappingInputBlockTimer == INT32_MAX && Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(port) ->GetGyro() @@ -1153,7 +1153,7 @@ void SohInputEditorWindow::DrawAddGyroMappingButton(uint8_t port) { void SohInputEditorWindow::DrawGyroSection(uint8_t port) { auto mapping = - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->GetGyroMapping(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(port)->GetGyro()->GetGyroMapping(); if (mapping != nullptr) { auto id = mapping->GetGyroMappingId(); ImGui::AlignTextToFramePadding(); @@ -1236,28 +1236,28 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) { } void SohInputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set bitmasks) { - std::set allLusDeviceIndices; - allLusDeviceIndices.insert(LUS::LUSDeviceIndex::Keyboard); - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::set allLusDeviceIndices; + allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard); + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { allLusDeviceIndices.insert(lusIndex); } - std::vector> lusDeviceIndiciesWithMappings; + std::vector> lusDeviceIndiciesWithMappings; for (auto lusIndex : allLusDeviceIndices) { for (auto [bitmask, button] : - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetAllButtons()) { + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetAllButtons()) { if (!bitmasks.contains(bitmask)) { continue; } - if (button->HasMappingsForLUSDeviceIndex(lusIndex)) { + if (button->HasMappingsForShipDeviceIndex(lusIndex)) { for (auto [id, mapping] : button->GetAllButtonMappings()) { - if (mapping->GetLUSDeviceIndex() == lusIndex) { + if (mapping->GetShipDeviceIndex() == lusIndex) { lusDeviceIndiciesWithMappings.push_back( - std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); + std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); break; } } @@ -1273,7 +1273,7 @@ void SohInputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set allLusDeviceIndices; - allLusDeviceIndices.insert(LUS::LUSDeviceIndex::Keyboard); - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() +void SohInputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::Stick stick) { + std::set allLusDeviceIndices; + allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard); + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { allLusDeviceIndices.insert(lusIndex); } - std::vector> lusDeviceIndiciesWithMappings; + std::vector> lusDeviceIndiciesWithMappings; for (auto lusIndex : allLusDeviceIndices) { auto controllerStick = - stick == LUS::Stick::LEFT_STICK - ? LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetLeftStick() - : LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetRightStick(); - if (controllerStick->HasMappingsForLUSDeviceIndex(lusIndex)) { + stick == Ship::Stick::LEFT_STICK + ? Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetLeftStick() + : Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetRightStick(); + if (controllerStick->HasMappingsForShipDeviceIndex(lusIndex)) { for (auto [direction, mappings] : controllerStick->GetAllAxisDirectionMappings()) { bool foundMapping = false; for (auto [id, mapping] : mappings) { - if (mapping->GetLUSDeviceIndex() == lusIndex) { + if (mapping->GetShipDeviceIndex() == lusIndex) { foundMapping = true; lusDeviceIndiciesWithMappings.push_back( - std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); + std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); break; } } @@ -1324,7 +1324,7 @@ void SohInputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, LUS::St ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::SameLine(); - if (lusIndex == LUS::LUSDeviceIndex::Keyboard) { + if (lusIndex == Ship::ShipDeviceIndex::Keyboard) { ImGui::SmallButton(ICON_FA_KEYBOARD_O); } else { ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN); @@ -1335,29 +1335,29 @@ void SohInputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, LUS::St } void SohInputEditorWindow::DrawRumbleDeviceIcons(uint8_t portIndex) { - std::set allLusDeviceIndices; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::set allLusDeviceIndices; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { allLusDeviceIndices.insert(lusIndex); } - std::vector> lusDeviceIndiciesWithMappings; + std::vector> lusDeviceIndiciesWithMappings; for (auto lusIndex : allLusDeviceIndices) { - if (LUS::Context::GetInstance() + if (Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->GetRumble() - ->HasMappingsForLUSDeviceIndex(lusIndex)) { - for (auto [id, mapping] : LUS::Context::GetInstance() + ->HasMappingsForShipDeviceIndex(lusIndex)) { + for (auto [id, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->GetRumble() ->GetAllRumbleMappings()) { - if (mapping->GetLUSDeviceIndex() == lusIndex) { + if (mapping->GetShipDeviceIndex() == lusIndex) { lusDeviceIndiciesWithMappings.push_back( - std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); + std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); break; } } @@ -1379,14 +1379,14 @@ void SohInputEditorWindow::DrawRumbleDeviceIcons(uint8_t portIndex) { void SohInputEditorWindow::DrawGyroDeviceIcons(uint8_t portIndex) { auto mapping = - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetGyro()->GetGyroMapping(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetGyro()->GetGyroMapping(); if (mapping == nullptr) { return; } auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(mapping->GetLUSDeviceIndex(), buttonColor, buttonHoveredColor); + GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::SameLine(); @@ -1396,29 +1396,29 @@ void SohInputEditorWindow::DrawGyroDeviceIcons(uint8_t portIndex) { } void SohInputEditorWindow::DrawLEDDeviceIcons(uint8_t portIndex) { - std::set allLusDeviceIndices; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::set allLusDeviceIndices; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { allLusDeviceIndices.insert(lusIndex); } - std::vector> lusDeviceIndiciesWithMappings; + std::vector> lusDeviceIndiciesWithMappings; for (auto lusIndex : allLusDeviceIndices) { - if (LUS::Context::GetInstance() + if (Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->GetRumble() - ->HasMappingsForLUSDeviceIndex(lusIndex)) { - for (auto [id, mapping] : LUS::Context::GetInstance() + ->HasMappingsForShipDeviceIndex(lusIndex)) { + for (auto [id, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->GetLED() ->GetAllLEDMappings()) { - if (mapping->GetLUSDeviceIndex() == lusIndex) { + if (mapping->GetShipDeviceIndex() == lusIndex) { lusDeviceIndiciesWithMappings.push_back( - std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); + std::pair(lusIndex, mapping->PhysicalDeviceIsConnected())); break; } } @@ -1516,7 +1516,7 @@ void SohInputEditorWindow::DrawMapping(CustomButtonMap& mapping, float labelWidt } if (ImGui::Selectable(i->second, i->first == currentButton)) { CVarSetInteger(mapping.cVarName, i->first); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } ImGui::EndCombo(); @@ -1548,7 +1548,7 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { ImGui::TableSetupColumn("Modifiers##CustomOcaranaModifiers", PANEL_TABLE_COLUMN_FLAGS); TableHelper::InitHeader(false); - LUS::GuiWindow::BeginGroupPanel("Notes", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Notes", ImGui::GetContentRegionAvail()); labelWidth = ImGui::CalcTextSize("D5").x + 10; DrawMapping(ocarinaD5, labelWidth, disableMask); DrawMapping(ocarinaB4, labelWidth, disableMask); @@ -1557,16 +1557,16 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { DrawMapping(ocarinaD4, labelWidth, disableMask); ImGui::Dummy(ImVec2(0, 5)); float cursorY = ImGui::GetCursorPosY(); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); TableHelper::NextCol(); - LUS::GuiWindow::BeginGroupPanel("Modifiers", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Modifiers", ImGui::GetContentRegionAvail()); labelWidth = ImGui::CalcTextSize(ocarinaSongDisable.label).x + 10; DrawMapping(ocarinaSongDisable, labelWidth, disableMask); DrawMapping(ocarinaSharp, labelWidth, disableMask); DrawMapping(ocarinaFlat, labelWidth, disableMask); - LUS::GuiWindow::EndGroupPanel(cursorY - ImGui::GetCursorPosY() + 2); + Ship::GuiWindow::EndGroupPanel(cursorY - ImGui::GetCursorPosY() + 2); ImGui::EndTable(); } @@ -1577,7 +1577,7 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { UIWidgets::Spacer(0); } - LUS::GuiWindow::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); if (ImGui::BeginTable("tableOcarinaAlternateControls", 2, ImGuiTableFlags_SizingFixedSame)) { ImGui::TableSetupColumn("D-pad", PANEL_TABLE_COLUMN_FLAGS); ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); @@ -1589,7 +1589,7 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { UIWidgets::Spacer(0); ImGui::EndTable(); } - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); ImGui::EndTable(); } @@ -1597,7 +1597,7 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { void SohInputEditorWindow::DrawCameraControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - LUS::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); UIWidgets::Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"); if (CVarGetInteger("gRightStickAiming", 0)) { @@ -1629,12 +1629,12 @@ void SohInputEditorWindow::DrawCameraControlPanel() { "gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true); } UIWidgets::Spacer(0); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); UIWidgets::Spacer(0); cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - LUS::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera"); UIWidgets::Tooltip("Enables free camera control\nNote: You must remap C buttons off of the right stick in the " @@ -1652,13 +1652,13 @@ void SohInputEditorWindow::DrawCameraControlPanel() { "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed", "gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); } void SohInputEditorWindow::DrawDpadControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - LUS::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause"); UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n" "To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0"); @@ -1667,13 +1667,13 @@ void SohInputEditorWindow::DrawDpadControlPanel() { "To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0"); UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); UIWidgets::Tooltip("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate"); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); } void SohInputEditorWindow::DrawMiscControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - LUS::GuiWindow::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail()); UIWidgets::PaddedText("Allow the cursor to be on any slot"); static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" }; UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY); @@ -1685,24 +1685,24 @@ void SohInputEditorWindow::DrawMiscControlPanel() { UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed"); if (CVarGetInteger("gEnableWalkModify", 0)) { UIWidgets::Spacer(5); - LUS::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); - LUS::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - LUS::GuiWindow::EndGroupPanel(0); - LUS::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); + Ship::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - LUS::GuiWindow::EndGroupPanel(0); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); } ImGui::EndDisabled(); UIWidgets::Spacer(0); UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL"); UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); - LUS::GuiWindow::EndGroupPanel(0); + Ship::GuiWindow::EndGroupPanel(0); } void SohInputEditorWindow::DrawLinkTab() { @@ -1749,17 +1749,17 @@ void SohInputEditorWindow::DrawLinkTab() { } if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); - DrawStickSection(portIndex, LUS::LEFT, 0); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); + DrawStickSection(portIndex, Ship::LEFT, 0); } else { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); } if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { - DrawAnalogStickDeviceIcons(portIndex, LUS::RIGHT_STICK); - DrawStickSection(portIndex, LUS::RIGHT, 1, CHIP_COLOR_N64_YELLOW); + DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK); + DrawStickSection(portIndex, Ship::RIGHT, 1, CHIP_COLOR_N64_YELLOW); } else { - DrawAnalogStickDeviceIcons(portIndex, LUS::RIGHT_STICK); + DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK); } if (ImGui::CollapsingHeader("Rumble")) { @@ -1884,10 +1884,10 @@ void SohInputEditorWindow::DrawIvanTab() { } if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); - DrawStickSection(portIndex, LUS::LEFT, 0); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); + DrawStickSection(portIndex, Ship::LEFT, 0); } else { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); } ImGui::PopStyleColor(); @@ -1942,10 +1942,10 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo } if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); - DrawStickSection(portIndex, LUS::LEFT, 0); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); + DrawStickSection(portIndex, Ship::LEFT, 0); } else { - DrawAnalogStickDeviceIcons(portIndex, LUS::LEFT_STICK); + DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK); } ImGui::PopStyleColor(); @@ -1965,7 +1965,7 @@ void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) { ImGui::CloseCurrentPopup(); } if (ImGui::Button("Clear All")) { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->ClearAllMappings(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->ClearAllMappings(); ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); @@ -1983,12 +1983,12 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::PopStyleVar(); if (ImGui::BeginPopup(popupId.c_str())) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); + auto wiiuIndexMapping = std::static_pointer_cast(mapping); if (wiiuIndexMapping == nullptr) { continue; } @@ -2025,11 +2025,11 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::CloseCurrentPopup(); } if (ImGui::Button("Set defaults")) { - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->ClearAllMappingsForDevice(lusIndex); - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( lusIndex); shouldClose = true; ImGui::CloseCurrentPopup(); @@ -2048,12 +2048,12 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { void SohInputEditorWindow::DrawDevicesTab() { if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); + auto wiiuIndexMapping = std::static_pointer_cast(mapping); if (wiiuIndexMapping == nullptr) { continue; } @@ -2061,11 +2061,11 @@ void SohInputEditorWindow::DrawDevicesTab() { indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), -1 }; } - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); + auto wiiuIndexMapping = std::static_pointer_cast(mapping); if (wiiuIndexMapping == nullptr) { continue; } @@ -2108,12 +2108,12 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { } if (ImGui::BeginPopup(popupId.c_str())) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappings()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); + auto sdlIndexMapping = std::static_pointer_cast(mapping); if (sdlIndexMapping == nullptr) { continue; } @@ -2136,12 +2136,12 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::CloseCurrentPopup(); } if (ImGui::Button("Set defaults")) { - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) - ->ClearAllMappingsForDevice(LUS::LUSDeviceIndex::Keyboard); - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( - LUS::LUSDeviceIndex::Keyboard); + ->ClearAllMappingsForDevice(Ship::ShipDeviceIndex::Keyboard); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( + Ship::ShipDeviceIndex::Keyboard); shouldClose = true; ImGui::CloseCurrentPopup(); } @@ -2171,11 +2171,11 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::CloseCurrentPopup(); } if (ImGui::Button("Set defaults")) { - LUS::Context::GetInstance() + Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(portIndex) ->ClearAllMappingsForDevice(lusIndex); - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( lusIndex); shouldClose = true; ImGui::CloseCurrentPopup(); @@ -2194,12 +2194,12 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { void SohInputEditorWindow::DrawDevicesTab() { if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappingsFromConfig()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); + auto sdlIndexMapping = std::static_pointer_cast(mapping); if (sdlIndexMapping == nullptr) { continue; } @@ -2207,11 +2207,11 @@ void SohInputEditorWindow::DrawDevicesTab() { indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 }; } - for (auto [lusIndex, mapping] : LUS::Context::GetInstance() + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() ->GetAllDeviceIndexMappings()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); + auto sdlIndexMapping = std::static_pointer_cast(mapping); if (sdlIndexMapping == nullptr) { continue; } diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h index e96b5b09a..079aa805b 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h @@ -20,7 +20,7 @@ typedef struct { N64ButtonMask defaultBtn; } CustomButtonMap; -class SohInputEditorWindow : public LUS::GuiWindow { +class SohInputEditorWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; ~SohInputEditorWindow(); @@ -38,14 +38,14 @@ class SohInputEditorWindow : public LUS::GuiWindow { void UpdateElement() override; private: - void DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, LUS::Direction direction, + void DrawStickDirectionLine(const char* axisDirectionName, uint8_t port, uint8_t stick, Ship::Direction direction, ImVec4 color); void DrawButtonLine(const char* buttonName, uint8_t port, uint16_t bitmask, ImVec4 color); void DrawButtonLineEditMappingButton(uint8_t port, uint16_t bitmask, std::string id); void DrawButtonLineAddMappingButton(uint8_t port, uint16_t bitmask); - void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, LUS::Direction direction, std::string id); - void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, LUS::Direction direction); + void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction, std::string id); + void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction); void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color); void DrawRumbleSection(uint8_t port); @@ -74,20 +74,20 @@ class SohInputEditorWindow : public LUS::GuiWindow { int32_t mGameInputBlockTimer; int32_t mMappingInputBlockTimer; int32_t mRumbleTimer; - std::shared_ptr mRumbleMappingToTest; + std::shared_ptr mRumbleMappingToTest; // mBitmaskToMappingIds[port][bitmask] = { id0, id1, ... } std::unordered_map>> mBitmaskToMappingIds; // mStickDirectionToMappingIds[port][stick][direction] = { id0, id1, ... } std::unordered_map>>> + std::unordered_map>>> mStickDirectionToMappingIds; void UpdateBitmaskToMappingIds(uint8_t port); void UpdateStickDirectionToMappingIds(uint8_t port); - void GetButtonColorsForLUSDeviceIndex(LUS::LUSDeviceIndex lusIndex, ImVec4& buttonColor, + void GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor, ImVec4& buttonHoveredColor); void DrawLinkTab(); void DrawIvanTab(); @@ -97,7 +97,7 @@ class SohInputEditorWindow : public LUS::GuiWindow { std::set mDpadBitmasks; std::set mModifierButtonsBitmasks; void DrawButtonDeviceIcons(uint8_t portIndex, std::set bitmasks); - void DrawAnalogStickDeviceIcons(uint8_t portIndex, LUS::Stick stick); + void DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::Stick stick); void DrawRumbleDeviceIcons(uint8_t portIndex); void DrawGyroDeviceIcons(uint8_t portIndex); void DrawLEDDeviceIcons(uint8_t portIndex); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 65659a80f..51eabd08d 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1322,7 +1322,7 @@ void Draw_Placements(){ if (ImGui::Button("Reset##EnemyHealthBarWidth")) { CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value")); CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed")); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); ImGui::EndTable(); @@ -1333,7 +1333,7 @@ void Reset_Option_Single(const char* Button_Title, const char* name) { ImGui::SameLine(); if (ImGui::Button(Button_Title)) { CVarClear(name); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } void Reset_Option_Double(const char* Button_Title, const char* name) { @@ -1341,14 +1341,14 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { if (ImGui::Button(Button_Title)) { CVarClear((std::string(name) + ".Value").c_str()); CVarClear((std::string(name) + ".Changed").c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } void DrawSillyTab() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); if (CVarGetInteger("gLetItSnow", 0)) { if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %.3fx", "##Link_BodyScale", CVAR_COSMETIC("Link.BodyScale.Value"), 0.001f, 0.025f, "", 0.01f, true)) { @@ -1358,7 +1358,7 @@ void DrawSillyTab() { if (ImGui::Button("Reset##Link_BodyScale")) { CVarClear(CVAR_COSMETIC("Link.BodyScale.Value")); CVarClear(CVAR_COSMETIC("Link.BodyScale.Changed")); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); if (gPlayState != nullptr) { static Player* player = GET_PLAYER(gPlayState); player->actor.scale.x = 0.01f; @@ -1612,7 +1612,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { CVarSetInteger((cosmeticOption.changedCvar), 1); ApplySideEffects(cosmeticOption); ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::Text("%s", cosmeticOption.label.c_str()); @@ -1620,7 +1620,7 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { if (ImGui::Button(("Random##" + cosmeticOption.label).c_str())) { RandomizeColor(cosmeticOption); ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (cosmeticOption.supportsRainbow) { ImGui::SameLine(); @@ -1630,21 +1630,21 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { CVarSetInteger((cosmeticOption.changedCvar), 1); ApplySideEffects(cosmeticOption); ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } ImGui::SameLine(); bool isLocked = (bool)CVarGetInteger((cosmeticOption.lockedCvar), 0); if (ImGui::Checkbox(("Locked##" + cosmeticOption.label).c_str(), &isLocked)) { CVarSetInteger((cosmeticOption.lockedCvar), isLocked); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (CVarGetInteger((cosmeticOption.changedCvar), 0)) { ImGui::SameLine(); if (ImGui::Button(("Reset##" + cosmeticOption.label).c_str())) { ResetColor(cosmeticOption); ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } } @@ -1660,7 +1660,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) { } } ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); if (ImGui::Button(("Reset##" + label).c_str())) { @@ -1670,7 +1670,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) { } } ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } for (auto& [id, cosmeticOption] : cosmeticOptions) { if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0))) { @@ -1706,7 +1706,7 @@ void CosmeticsEditorWindow::DrawElement() { CVarSetInteger(cosmeticOption.lockedCvar, 1); } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); if (ImGui::Button("Unlock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { @@ -1715,7 +1715,7 @@ void CosmeticsEditorWindow::DrawElement() { CVarSetInteger(cosmeticOption.lockedCvar, 0); } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } UIWidgets::EnhancementCheckbox("Sync Rainbow colors", CVAR_COSMETIC("RainbowSync")); @@ -1734,7 +1734,7 @@ void CosmeticsEditorWindow::DrawElement() { } } ApplyOrResetCustomGfxPatches(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (ImGui::Button("Lock All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { @@ -1743,7 +1743,7 @@ void CosmeticsEditorWindow::DrawElement() { CVarSetInteger(cosmeticOption.lockedCvar, 1); } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); if (ImGui::Button("Unlock All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { @@ -1752,7 +1752,7 @@ void CosmeticsEditorWindow::DrawElement() { CVarSetInteger(cosmeticOption.lockedCvar, 0); } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (ImGui::BeginTabBar("CosmeticsContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { @@ -1777,7 +1777,7 @@ void CosmeticsEditorWindow::DrawElement() { if (ImGui::Button("Reset##Trails_Duration")) { CVarClear(CVAR_COSMETIC("Trails.Duration.Value")); CVarClear(CVAR_COSMETIC("Trails.Duration.Changed")); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::EndTabItem(); } @@ -1843,7 +1843,7 @@ void CosmeticsEditorWindow::InitElement() { cosmeticOption.currentColor.z = cvarColor.b / 255.0; cosmeticOption.currentColor.w = cvarColor.a / 255.0; } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); ApplyAuthenticGfxPatches(); @@ -1860,7 +1860,7 @@ void CosmeticsEditor_RandomizeAll() { } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } @@ -1873,7 +1873,7 @@ void CosmeticsEditor_RandomizeGroup(CosmeticGroup group) { } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } @@ -1884,7 +1884,7 @@ void CosmeticsEditor_ResetAll() { } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } @@ -1895,6 +1895,6 @@ void CosmeticsEditor_ResetGroup(CosmeticGroup group) { } } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index 9599a521f..88f60c76c 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -54,7 +54,7 @@ void CosmeticsEditor_ResetAll(); void CosmeticsEditor_ResetGroup(CosmeticGroup group); void ApplyOrResetCustomGfxPatches(bool manualChange = true); -class CosmeticsEditorWindow : public LUS::GuiWindow { +class CosmeticsEditorWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index e75450c7c..7c73ea61e 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -36,12 +36,12 @@ extern PlayState* gPlayState; #include #include -#define CMD_REGISTER LUS::Context::GetInstance()->GetConsole()->AddCommand +#define CMD_REGISTER Ship::Context::GetInstance()->GetConsole()->AddCommand // TODO: Commands should be using the output passed in. -#define ERROR_MESSAGE std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendErrorMessage -#define INFO_MESSAGE std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendInfoMessage +#define ERROR_MESSAGE std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendErrorMessage +#define INFO_MESSAGE std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendInfoMessage -static bool ActorSpawnHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool ActorSpawnHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { ERROR_MESSAGE("Not enough arguments passed to actorspawn"); return 1; @@ -101,7 +101,7 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std:: return 0; } -static bool KillPlayerHandler(std::shared_ptr Console, const std::vector&, std::string* output) { +static bool KillPlayerHandler(std::shared_ptr Console, const std::vector&, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth(); dynamic_cast(effect)->parameters[0] = 0; GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -114,7 +114,7 @@ static bool KillPlayerHandler(std::shared_ptr Console, const std:: } } -static bool SetPlayerHealthHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool SetPlayerHealthHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -145,7 +145,7 @@ static bool SetPlayerHealthHandler(std::shared_ptr Console, const } } -static bool LoadSceneHandler(std::shared_ptr Console, const std::vector&, std::string* output) { +static bool LoadSceneHandler(std::shared_ptr Console, const std::vector&, std::string* output) { gSaveContext.respawnFlag = 0; gSaveContext.seqId = 0xFF; gSaveContext.gameMode = 0; @@ -153,7 +153,7 @@ static bool LoadSceneHandler(std::shared_ptr Console, const std::v return 0; } -static bool RupeeHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool RupeeHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { return 1; } @@ -178,7 +178,7 @@ static bool RupeeHandler(std::shared_ptr Console, const std::vecto return 0; } -static bool SetPosHandler(std::shared_ptr Console, const std::vector args, std::string* output) { +static bool SetPosHandler(std::shared_ptr Console, const std::vector args, std::string* output) { if (gPlayState == nullptr) { ERROR_MESSAGE("PlayState == nullptr"); return 1; @@ -205,7 +205,7 @@ static bool SetPosHandler(std::shared_ptr Console, const std::vect return 0; } -static bool ResetHandler(std::shared_ptr Console, std::vector args, std::string* output) { +static bool ResetHandler(std::shared_ptr Console, std::vector args, std::string* output) { if (gPlayState == nullptr) { ERROR_MESSAGE("PlayState == nullptr"); return 1; @@ -225,7 +225,7 @@ const static std::map ammoItems{ { "beans", ITEM_BEAN } }; -static bool AddAmmoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool AddAmmoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 3) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -264,7 +264,7 @@ static bool AddAmmoHandler(std::shared_ptr Console, const std::vec } } -static bool TakeAmmoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool TakeAmmoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 3) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -311,7 +311,7 @@ const static std::map bottleItems{ { "big_poe", ITEM_BIG_POE }, { "blue_fire", ITEM_BLUE_FIRE }, { "rutos_letter", ITEM_LETTER_RUTO }, }; -static bool BottleHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool BottleHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 3) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -343,7 +343,7 @@ static bool BottleHandler(std::shared_ptr Console, const std::vect return 0; } -static bool BHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool BHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -353,7 +353,7 @@ static bool BHandler(std::shared_ptr Console, const std::vector Console, const std::vector& args, std::string* output) { +static bool ItemHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 3) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -364,7 +364,7 @@ static bool ItemHandler(std::shared_ptr Console, const std::vector return 0; } -static bool GiveItemHandler(std::shared_ptr Console, const std::vector args, std::string* output) { +static bool GiveItemHandler(std::shared_ptr Console, const std::vector args, std::string* output) { if (args.size() < 3) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -385,7 +385,7 @@ static bool GiveItemHandler(std::shared_ptr Console, const std::ve return 0; } -static bool EntranceHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool EntranceHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -406,7 +406,7 @@ static bool EntranceHandler(std::shared_ptr Console, const std::ve gSaveContext.nextTransitionType = TRANS_TYPE_INSTANT; } -static bool VoidHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool VoidHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (gPlayState != nullptr) { gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags = gPlayState->actorCtx.flags.tempSwch; gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = gPlayState->actorCtx.flags.tempCollect; @@ -422,7 +422,7 @@ static bool VoidHandler(std::shared_ptr Console, const std::vector return 0; } -static bool ReloadHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool ReloadHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (gPlayState != nullptr) { gPlayState->nextEntranceIndex = gSaveContext.entranceIndex; gPlayState->transitionTrigger = TRANS_TRIGGER_START; @@ -439,7 +439,7 @@ const static std::map fw_options { { "clear", 0}, {"warp", 1}, {"backup", 2} }; -static bool FWHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool FWHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -491,7 +491,7 @@ static bool FWHandler(std::shared_ptr Console, const std::vector Console, const std::vector& args, std::string* output) { +static bool FileSelectHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (gPlayState != nullptr) { SET_NEXT_GAMESTATE(&gPlayState->state, FileChoose_Init, FileChooseContext); gPlayState->state.running = 0; @@ -502,12 +502,12 @@ static bool FileSelectHandler(std::shared_ptr Console, const std:: return 0; } -static bool QuitHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { - LUS::Context::GetInstance()->GetWindow()->Close(); +static bool QuitHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { + Ship::Context::GetInstance()->GetWindow()->Close(); return 0; } -static bool SaveStateHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool SaveStateHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE }); @@ -521,7 +521,7 @@ static bool SaveStateHandler(std::shared_ptr Console, const std::v } } -static bool LoadStateHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool LoadStateHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD }); @@ -542,7 +542,7 @@ static bool LoadStateHandler(std::shared_ptr Console, const std::v } -static bool StateSlotSelectHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool StateSlotSelectHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -567,7 +567,7 @@ static bool StateSlotSelectHandler(std::shared_ptr Console, const return 0; } -static bool InvisibleHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool InvisibleHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -594,7 +594,7 @@ static bool InvisibleHandler(std::shared_ptr Console, const std::v } } -static bool GiantLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool GiantLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -622,7 +622,7 @@ static bool GiantLinkHandler(std::shared_ptr Console, const std::v } } -static bool MinishLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool MinishLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -650,7 +650,7 @@ static bool MinishLinkHandler(std::shared_ptr Console, const std:: } } -static bool AddHeartContainerHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool AddHeartContainerHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -681,7 +681,7 @@ static bool AddHeartContainerHandler(std::shared_ptr Console, cons } } -static bool RemoveHeartContainerHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool RemoveHeartContainerHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -712,7 +712,7 @@ static bool RemoveHeartContainerHandler(std::shared_ptr Console, c } } -static bool GravityHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool GravityHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -721,7 +721,7 @@ static bool GravityHandler(std::shared_ptr Console, const std::vec GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyGravity(); try { - dynamic_cast(effect)->parameters[0] = LUS::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY); + dynamic_cast(effect)->parameters[0] = Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY); } catch (std::invalid_argument const& ex) { ERROR_MESSAGE("[SOH] Gravity value must be a number."); return 1; @@ -737,7 +737,7 @@ static bool GravityHandler(std::shared_ptr Console, const std::vec } } -static bool NoUIHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool NoUIHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -765,7 +765,7 @@ static bool NoUIHandler(std::shared_ptr Console, const std::vector } } -static bool FreezeHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool FreezeHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::FreezePlayer(); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -778,7 +778,7 @@ static bool FreezeHandler(std::shared_ptr Console, const std::vect } } -static bool DefenseModifierHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool DefenseModifierHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -802,7 +802,7 @@ static bool DefenseModifierHandler(std::shared_ptr Console, const } } -static bool DamageHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool DamageHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -832,7 +832,7 @@ static bool DamageHandler(std::shared_ptr Console, const std::vect } } -static bool HealHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool HealHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -862,7 +862,7 @@ static bool HealHandler(std::shared_ptr Console, const std::vector } } -static bool FillMagicHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool FillMagicHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::FillMagic(); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -875,7 +875,7 @@ static bool FillMagicHandler(std::shared_ptr Console, const std::v } } -static bool EmptyMagicHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool EmptyMagicHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::EmptyMagic(); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -888,7 +888,7 @@ static bool EmptyMagicHandler(std::shared_ptr Console, const std:: } } -static bool NoZHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool NoZHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -916,7 +916,7 @@ static bool NoZHandler(std::shared_ptr Console, const std::vector< } } -static bool OneHitKOHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool OneHitKOHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -944,7 +944,7 @@ static bool OneHitKOHandler(std::shared_ptr Console, const std::ve } } -static bool PacifistHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool PacifistHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -972,7 +972,7 @@ static bool PacifistHandler(std::shared_ptr Console, const std::ve } } -static bool PaperLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool PaperLinkHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1001,7 +1001,7 @@ static bool PaperLinkHandler(std::shared_ptr Console, const std::v } } -static bool RainstormHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool RainstormHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1029,7 +1029,7 @@ static bool RainstormHandler(std::shared_ptr Console, const std::v } } -static bool ReverseControlsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool ReverseControlsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1058,7 +1058,7 @@ static bool ReverseControlsHandler(std::shared_ptr Console, const } } -static bool UpdateRupeesHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool UpdateRupeesHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1082,7 +1082,7 @@ static bool UpdateRupeesHandler(std::shared_ptr Console, const std } } -static bool SpeedModifierHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool SpeedModifierHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1112,7 +1112,7 @@ const static std::map boots { { "hover", EQUIP_VALUE_BOOTS_HOVER }, }; -static bool BootsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool BootsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1143,7 +1143,7 @@ const static std::map shields { { "mirror", ITEM_SHIELD_MIRROR }, }; -static bool GiveShieldHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool GiveShieldHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1168,7 +1168,7 @@ static bool GiveShieldHandler(std::shared_ptr Console, const std:: } } -static bool TakeShieldHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool TakeShieldHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1193,7 +1193,7 @@ static bool TakeShieldHandler(std::shared_ptr Console, const std:: } } -static bool KnockbackHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool KnockbackHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1223,7 +1223,7 @@ static bool KnockbackHandler(std::shared_ptr Console, const std::v } } -static bool ElectrocuteHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool ElectrocuteHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::ElectrocutePlayer(); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -1236,7 +1236,7 @@ static bool ElectrocuteHandler(std::shared_ptr Console, const std: } } -static bool BurnHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool BurnHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectBase* effect = new GameInteractionEffect::BurnPlayer(); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); @@ -1249,7 +1249,7 @@ static bool BurnHandler(std::shared_ptr Console, const std::vector } } -static bool CuccoStormHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool CuccoStormHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { GameInteractionEffectQueryResult result = GameInteractor::RawAction::SpawnActor(ACTOR_EN_NIW, 0); if (result == GameInteractionEffectQueryResult::Possible) { @@ -1261,7 +1261,7 @@ static bool CuccoStormHandler(std::shared_ptr Console, const std:: } } -static bool GenerateRandoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool GenerateRandoHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() == 1) { if (GenerateRandomizer()) { return 0; @@ -1309,7 +1309,7 @@ static constexpr std::array, COSMETICS_GRO {"ivan", COSMETICS_GROUP_IVAN}, }}; -static bool CosmeticsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool CosmeticsHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1361,7 +1361,7 @@ static std::map sfx_groups = { {"custom", SEQ_BGM_CUSTOM}, }; -static bool SfxHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { +static bool SfxHandler(std::shared_ptr Console, const std::vector& args, std::string* output) { if (args.size() < 2) { ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; @@ -1411,17 +1411,17 @@ void DebugConsole_Init(void) { CMD_REGISTER("save_state", {SaveStateHandler, "Save a state."}); CMD_REGISTER("load_state", {LoadStateHandler, "Load a state."}); CMD_REGISTER("set_slot", {StateSlotSelectHandler, "Selects a SaveState slot", { - {"Slot number", LUS::ArgumentType::NUMBER,} + {"Slot number", Ship::ArgumentType::NUMBER,} }}); // Map & Location CMD_REGISTER("void", {VoidHandler, "Voids out of the current map."}); CMD_REGISTER("reload", {ReloadHandler, "Reloads the current map."}); CMD_REGISTER("fw", {FWHandler, "Spawns the player where Farore's Wind is set.", { - {"clear|warp|backup", LUS::ArgumentType::TEXT} + {"clear|warp|backup", Ship::ArgumentType::TEXT} }}); CMD_REGISTER("entrance", {EntranceHandler, "Sends player to the entered entrance (hex)", { - {"entrance", LUS::ArgumentType::NUMBER} + {"entrance", Ship::ArgumentType::NUMBER} }}); // Gameplay @@ -1430,64 +1430,64 @@ void DebugConsole_Init(void) { CMD_REGISTER("map", {LoadSceneHandler, "Load up kak?"}); CMD_REGISTER("rupee", {RupeeHandler, "Set your rupee counter.", { - {"amount", LUS::ArgumentType::NUMBER} + {"amount", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("bItem", {BHandler, "Set an item to the B button.", { - {"Item ID", LUS::ArgumentType::NUMBER} + {"Item ID", Ship::ArgumentType::NUMBER} }}); - CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", LUS::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type - {"data", LUS::ArgumentType::NUMBER}, - {"x", LUS::ArgumentType::NUMBER, true}, - {"y", LUS::ArgumentType::NUMBER, true}, - {"z", LUS::ArgumentType::NUMBER, true}, - {"rx", LUS::ArgumentType::NUMBER, true}, - {"ry", LUS::ArgumentType::NUMBER, true}, - {"rz", LUS::ArgumentType::NUMBER, true} + CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", Ship::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type + {"data", Ship::ArgumentType::NUMBER}, + {"x", Ship::ArgumentType::NUMBER, true}, + {"y", Ship::ArgumentType::NUMBER, true}, + {"z", Ship::ArgumentType::NUMBER, true}, + {"rx", Ship::ArgumentType::NUMBER, true}, + {"ry", Ship::ArgumentType::NUMBER, true}, + {"rz", Ship::ArgumentType::NUMBER, true} }}); CMD_REGISTER("pos", {SetPosHandler, "Sets the position of the player.", { - {"x", LUS::ArgumentType::NUMBER, true}, - {"y", LUS::ArgumentType::NUMBER, true}, - {"z", LUS::ArgumentType::NUMBER, true} + {"x", Ship::ArgumentType::NUMBER, true}, + {"y", Ship::ArgumentType::NUMBER, true}, + {"z", Ship::ArgumentType::NUMBER, true} }}); CMD_REGISTER("addammo", {AddAmmoHandler, "Adds ammo of an item.", { - {"sticks|nuts|bombs|seeds|arrows|bombchus|beans", LUS::ArgumentType::TEXT}, - {"count", LUS::ArgumentType::NUMBER} + {"sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT}, + {"count", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("takeammo", {TakeAmmoHandler, "Removes ammo of an item.", { - {"sticks|nuts|bombs|seeds|arrows|bombchus|beans", LUS::ArgumentType::TEXT}, - {"count", LUS::ArgumentType::NUMBER} + {"sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT}, + {"count", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("bottle", {BottleHandler, "Changes item in a bottle slot.", { - {"item", LUS::ArgumentType::TEXT}, - {"slot", LUS::ArgumentType::NUMBER} + {"item", Ship::ArgumentType::TEXT}, + {"slot", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("give_item", {GiveItemHandler, "Gives an item to the player as if it was given from an actor", { - {"vanilla|randomizer", LUS::ArgumentType::TEXT}, - {"giveItemID", LUS::ArgumentType::NUMBER} + {"vanilla|randomizer", Ship::ArgumentType::TEXT}, + {"giveItemID", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("item", {ItemHandler, "Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.", { - {"slot", LUS::ArgumentType::NUMBER}, - {"item id", LUS::ArgumentType::NUMBER} + {"slot", Ship::ArgumentType::NUMBER}, + {"item id", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("invisible", {InvisibleHandler, "Activate Link's Elvish cloak, making him appear invisible.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("giant_link", {GiantLinkHandler, "Turn Link into a giant Lonky boi.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("minish_link", {MinishLinkHandler, "Turn Link into a minish boi.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("add_heart_container", @@ -1497,25 +1497,25 @@ void DebugConsole_Init(void) { {RemoveHeartContainerHandler, "Remove a heart from Link. The minimal amount of hearts is 3."}); CMD_REGISTER("gravity", {GravityHandler, "Set gravity level.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("no_ui", {NoUIHandler, "Disables the UI.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("freeze", {FreezeHandler, "Freezes Link in place"}); CMD_REGISTER("defense_modifier", {DefenseModifierHandler, "Sets the defense modifier.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("damage", {DamageHandler, "Deal damage to Link.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("heal", {HealHandler, "Heals Link.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("fill_magic", {FillMagicHandler, "Fills magic."}); @@ -1523,50 +1523,50 @@ void DebugConsole_Init(void) { CMD_REGISTER("empty_magic", {EmptyMagicHandler, "Empties magic."}); CMD_REGISTER("no_z", {NoZHandler, "Disables Z-button presses.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("ohko", {OneHitKOHandler, "Activates one hit KO. Any damage kills Link and he cannot gain health in this mode.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("pacifist", {PacifistHandler, "Activates pacifist mode. Prevents Link from using his weapon.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("paper_link", {PaperLinkHandler, "Link but made out of paper.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("rainstorm", {RainstormHandler, "Activates rainstorm."}); CMD_REGISTER("reverse_controls", {ReverseControlsHandler, "Reverses the controls.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("update_rupees", {UpdateRupeesHandler, "Adds rupees.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("speed_modifier", {SpeedModifierHandler, "Sets the speed modifier.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("boots", {BootsHandler, "Activates boots.", { - {"kokiri|iron|hover", LUS::ArgumentType::TEXT}, + {"kokiri|iron|hover", Ship::ArgumentType::TEXT}, }}); CMD_REGISTER("giveshield", {GiveShieldHandler, "Gives a shield and equips it when Link is the right age for it.", { - {"deku|hylian|mirror", LUS::ArgumentType::TEXT}, + {"deku|hylian|mirror", Ship::ArgumentType::TEXT}, }}); CMD_REGISTER("takeshield", {TakeShieldHandler, "Takes a shield and unequips it if Link is wearing it.", { - {"deku|hylian|mirror", LUS::ArgumentType::TEXT}, + {"deku|hylian|mirror", Ship::ArgumentType::TEXT}, }}); CMD_REGISTER("knockback", {KnockbackHandler, "Knocks Link back.", { - {"value", LUS::ArgumentType::NUMBER} + {"value", Ship::ArgumentType::NUMBER} }}); CMD_REGISTER("electrocute", {ElectrocuteHandler, "Electrocutes Link."}); @@ -1576,18 +1576,18 @@ void DebugConsole_Init(void) { CMD_REGISTER("cucco_storm", {CuccoStormHandler, "Cucco Storm"}); CMD_REGISTER("gen_rando", {GenerateRandoHandler, "Generate a randomizer seed", { - {"seed|count", LUS::ArgumentType::NUMBER, true}, - {"testing", LUS::ArgumentType::NUMBER, true}, + {"seed|count", Ship::ArgumentType::NUMBER, true}, + {"testing", Ship::ArgumentType::NUMBER, true}, }}); CMD_REGISTER("cosmetics", {CosmeticsHandler, "Change cosmetics.", { - {"reset|randomize", LUS::ArgumentType::TEXT}, - {"group name", LUS::ArgumentType::TEXT, true}, + {"reset|randomize", Ship::ArgumentType::TEXT}, + {"group name", Ship::ArgumentType::TEXT, true}, }}); CMD_REGISTER("sfx", {SfxHandler, "Change SFX.", { - {"reset|randomize", LUS::ArgumentType::TEXT}, - {"group_name", LUS::ArgumentType::TEXT, true}, + {"reset|randomize", Ship::ArgumentType::TEXT}, + {"group_name", Ship::ArgumentType::TEXT, true}, }}); CVarSave(); diff --git a/soh/soh/Enhancements/debugger/MessageViewer.h b/soh/soh/Enhancements/debugger/MessageViewer.h index 702693793..43ae55aa7 100644 --- a/soh/soh/Enhancements/debugger/MessageViewer.h +++ b/soh/soh/Enhancements/debugger/MessageViewer.h @@ -26,7 +26,7 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage); } -class MessageViewer : public LUS::GuiWindow { +class MessageViewer : public Ship::GuiWindow { public: static inline const char* TABLE_ID = "MessageViewer"; using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugger/actorViewer.h b/soh/soh/Enhancements/debugger/actorViewer.h index 6eceaa92d..2f4ca680a 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.h +++ b/soh/soh/Enhancements/debugger/actorViewer.h @@ -2,7 +2,7 @@ #include -class ActorViewerWindow : public LUS::GuiWindow { +class ActorViewerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugger/colViewer.h b/soh/soh/Enhancements/debugger/colViewer.h index 98f0b6f0a..5252bc950 100644 --- a/soh/soh/Enhancements/debugger/colViewer.h +++ b/soh/soh/Enhancements/debugger/colViewer.h @@ -14,7 +14,7 @@ typedef enum { } ColViewerRenderSetting; #ifdef __cplusplus -class ColViewerWindow : public LUS::GuiWindow { +class ColViewerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index f90ab739c..f7b85251c 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -614,7 +614,7 @@ void DrawInfoTab() { void DrawBGSItemFlag(uint8_t itemID) { const ItemMapEntry& slotEntry = itemMapping[itemID]; - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1)); ImGui::SameLine(); int tradeIndex = itemID - ITEM_POCKET_EGG; bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0; @@ -656,7 +656,7 @@ void DrawInventoryTab() { uint8_t item = gSaveContext.inventory.items[index]; if (item != ITEM_NONE) { const ItemMapEntry& slotEntry = itemMapping.find(item)->second; - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { selectedIndex = index; ImGui::OpenPopup(itemPopupPicker); @@ -704,7 +704,7 @@ void DrawInventoryTab() { ImGui::SameLine(); } const ItemMapEntry& slotEntry = possibleItems[pickerIndex]; - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { gSaveContext.inventory.items[selectedIndex] = slotEntry.id; // Set adult trade item flag if you're playing adult trade shuffle in rando @@ -742,7 +742,7 @@ void DrawInventoryTab() { ImGui::PushItemWidth(32.0f); ImGui::BeginGroup(); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name), ImVec2(32.0f, 32.0f)); + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name), ImVec2(32.0f, 32.0f)); ImGui::InputScalar("##ammoInput", ImGuiDataType_S8, &AMMO(item)); ImGui::EndGroup(); @@ -1157,7 +1157,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const uint8_t item = items[CUR_UPG_VALUE(categoryId)]; if (item != ITEM_NONE) { const ItemMapEntry& slotEntry = itemMapping[item]; - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { ImGui::OpenPopup(upgradePopupPicker); } @@ -1185,7 +1185,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const UIWidgets::SetLastItemHoverText("None"); } else { const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]]; - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { Inventory_ChangeUpgrade(categoryId, pickerIndex); ImGui::CloseCurrentPopup(); @@ -1222,7 +1222,7 @@ void DrawEquipmentTab() { bool hasEquip = (bitMask & gSaveContext.inventory.equipment) != 0; const ItemMapEntry& entry = itemMapping[equipmentValues[i]]; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip ? entry.name : entry.nameFaded), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip ? entry.name : entry.nameFaded), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { if (hasEquip) { gSaveContext.inventory.equipment &= ~bitMask; @@ -1321,7 +1321,7 @@ void DrawQuestItemButton(uint32_t item) { uint32_t bitMask = 1 << entry.id; bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { if (hasQuestItem) { gSaveContext.inventory.questItems &= ~bitMask; @@ -1339,7 +1339,7 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) { uint32_t bitMask = 1 << (entry.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { if (hasItem) { gSaveContext.inventory.dungeonItems[scene] &= ~bitMask; @@ -1386,7 +1386,7 @@ void DrawQuestStatusTab() { uint32_t bitMask = 1 << entry.id; bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - if (ImGui::ImageButton(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), + if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), ImVec2(16.0f, 24.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { if (hasQuestItem) { gSaveContext.inventory.questItems &= ~bitMask; @@ -1449,7 +1449,7 @@ void DrawQuestStatusTab() { if (dungeonItemsScene != SCENE_JABU_JABU_BOSS) { float lineHeight = ImGui::GetTextLineHeightWithSpacing(); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight)); + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight)); ImGui::SameLine(); if (ImGui::InputScalar("##Keys", ImGuiDataType_S8, gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) { gSaveContext.sohStats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene]; @@ -1793,34 +1793,34 @@ void SaveEditorWindow::DrawElement() { void SaveEditorWindow::InitElement() { // Load item icons into ImGui for (const auto& entry : itemMapping) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); } for (const auto& entry : gregMapping) { ImVec4 gregGreen = ImVec4(42.0f / 255.0f, 169.0f / 255.0f, 40.0f / 255.0f, 1.0f); ImVec4 gregFadedGreen = gregGreen; gregFadedGreen.w = 0.3f; - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, gregGreen); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, gregFadedGreen); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, gregGreen); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, gregFadedGreen); } for (const auto& entry : triforcePieceMapping) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); } for (const auto& entry : questMapping) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); } for (const auto& entry : songMapping) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color); ImVec4 fadedCol = entry.color; fadedCol.w = 0.3f; - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol); } for (const auto& entry : vanillaSongMapping) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color); ImVec4 fadedCol = entry.color; fadedCol.w = 0.3f; - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol); } } diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 01557efef..1de852e35 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -590,7 +590,7 @@ const std::vector state3 = { "Travelling to Hook Target" }; -class SaveEditorWindow : public LUS::GuiWindow { +class SaveEditorWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugger/dlViewer.cpp b/soh/soh/Enhancements/debugger/dlViewer.cpp index 028234fc1..790f426df 100644 --- a/soh/soh/Enhancements/debugger/dlViewer.cpp +++ b/soh/soh/Enhancements/debugger/dlViewer.cpp @@ -65,7 +65,7 @@ std::map cmdMap = { }; void PerformDisplayListSearch() { - auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); + auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); displayListSearchResults.clear(); @@ -127,7 +127,7 @@ void DLViewerWindow::DrawElement() { } try { - auto res = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); + auto res = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); if (res->GetInitData()->Type != static_cast(LUS::ResourceType::DisplayList)) { ImGui::Text("Resource type is not a Display List. Please choose another."); diff --git a/soh/soh/Enhancements/debugger/dlViewer.h b/soh/soh/Enhancements/debugger/dlViewer.h index 348372a49..9d2785456 100644 --- a/soh/soh/Enhancements/debugger/dlViewer.h +++ b/soh/soh/Enhancements/debugger/dlViewer.h @@ -2,7 +2,7 @@ #include -class DLViewerWindow : public LUS::GuiWindow { +class DLViewerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/debugger/valueViewer.h b/soh/soh/Enhancements/debugger/valueViewer.h index 7631b8c3f..747d39018 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.h +++ b/soh/soh/Enhancements/debugger/valueViewer.h @@ -33,7 +33,7 @@ typedef struct { uint32_t y; } ValueTableElement; -class ValueViewerWindow : public LUS::GuiWindow { +class ValueViewerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 229f76cbb..cf098bda3 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -459,7 +459,7 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint break; } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Sail.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Sail.cpp index a209d8c50..77d48dc80 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Sail.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Sail.cpp @@ -66,7 +66,7 @@ void GameInteractorSail::HandleRemoteJson(nlohmann::json payload) { } std::string command = payload["command"].get(); - std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command); + std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command); responsePayload["status"] = "success"; GameInteractor::Instance->TransmitJsonToRemote(responsePayload); return; @@ -88,7 +88,7 @@ void GameInteractorSail::HandleRemoteJson(nlohmann::json payload) { } std::string command = payload["effect"]["command"].get(); - std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command); + std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch(command); responsePayload["status"] = "success"; GameInteractor::Instance->TransmitJsonToRemote(responsePayload); return; diff --git a/soh/soh/Enhancements/gameplaystatswindow.h b/soh/soh/Enhancements/gameplaystatswindow.h index 2a3786415..453b24559 100644 --- a/soh/soh/Enhancements/gameplaystatswindow.h +++ b/soh/soh/Enhancements/gameplaystatswindow.h @@ -1,7 +1,7 @@ #include #include "gameplaystats.h" -class GameplayStatsWindow : public LUS::GuiWindow { +class GameplayStatsWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index a10dd559b..8f9819f08 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -462,7 +462,7 @@ void RegisterDeleteFileOnDeath() { if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); hasAffectedHealth = false; - std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); + std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); } }); } diff --git a/soh/soh/Enhancements/presets.cpp b/soh/soh/Enhancements/presets.cpp index 726863e05..ea51502e3 100644 --- a/soh/soh/Enhancements/presets.cpp +++ b/soh/soh/Enhancements/presets.cpp @@ -70,7 +70,7 @@ void DrawPresetSelector(PresetType presetTypeId) { if (selectedPresetId != 0) { applyPreset(selectedPresetDef.entries); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::PopStyleVar(1); } diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 167e12667..e53caeef2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -18,7 +18,7 @@ void RandoMain::GenerateRando(std::unordered_map cvarS // std::string settingsFileName = "./randomizer/latest_settings.json"; // CVarSetString("gLoadedPreset", settingsFileName.c_str()); - std::string fileName = LUS::Context::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, enabledTricks, seedString).c_str()); + std::string fileName = Ship::Context::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, enabledTricks, seedString).c_str()); CVarSetString("gSpoilerLog", fileName.c_str()); CVarSave(); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index ce885aec5..235996273 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -895,8 +895,8 @@ const char* SpoilerLog_Write(int language) { WriteAllLocations(language); //WriteHintData(language); - if (!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("Randomizer"))) { - std::filesystem::create_directory(LUS::Context::GetPathRelativeToAppDirectory("Randomizer")); + if (!std::filesystem::exists(Ship::Context::GetPathRelativeToAppDirectory("Randomizer"))) { + std::filesystem::create_directory(Ship::Context::GetPathRelativeToAppDirectory("Randomizer")); } std::string jsonString = jsonData.dump(4); @@ -911,7 +911,7 @@ const char* SpoilerLog_Write(int language) { fileNameStream << std::to_string(Settings::hashIconIndexes[i]); } std::string fileName = fileNameStream.str(); - std::ofstream jsonFile(LUS::Context::GetPathRelativeToAppDirectory( + std::ofstream jsonFile(Ship::Context::GetPathRelativeToAppDirectory( (std::string("Randomizer/") + fileName + std::string(".json")).c_str())); jsonFile << std::setw(4) << jsonString << std::endl; jsonFile.close(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 40b3daaf3..0c7f30e0f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4683,7 +4683,7 @@ void RandomizerSettingsWindow::DrawElement() { excludedLocationString += ","; } CVarSetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), excludedLocationString.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::Text("%s", rcObject->rcShortName.c_str()); @@ -4728,7 +4728,7 @@ void RandomizerSettingsWindow::DrawElement() { } else { CVarSetString(CVAR_RANDOMIZER_SETTING("ExcludedLocations"), excludedLocationString.c_str()); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::Text("%s", rcObject->rcShortName.c_str()); @@ -4914,7 +4914,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); if (ImGui::Button("Enable All")) { @@ -4931,7 +4931,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } if (ImGui::BeginTable("trickTags", showTag.size(), ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) { @@ -5008,7 +5008,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::BeginChild("ChildTricksDisabled", ImVec2(0, -8), false, ImGuiWindowFlags_HorizontalScrollbar); @@ -5044,7 +5044,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); @@ -5118,7 +5118,7 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::BeginChild("ChildTricksEnabled", ImVec2(0, -8), false, ImGuiWindowFlags_HorizontalScrollbar); @@ -5160,7 +5160,7 @@ void RandomizerSettingsWindow::DrawElement() { } else { CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 1123cba72..20b5c333d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -877,7 +877,7 @@ void CheckTrackerWindow::DrawElement() { if (CVarGetInteger(CVAR_TRACKER_CHECK("DisplayType"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { int comboButton1Mask = buttons[CVarGetInteger(CVAR_TRACKER_CHECK("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; int comboButton2Mask = buttons[CVarGetInteger(CVAR_TRACKER_CHECK("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; - OSContPad* trackerButtonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); + OSContPad* trackerButtonsPressed = Ship::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = trackerButtonsPressed != nullptr && trackerButtonsPressed[0].button & comboButton1Mask && trackerButtonsPressed[0].button & comboButton2Mask; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 85a4f1d9e..216da367f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -7,9 +7,9 @@ namespace CheckTracker { -class CheckTrackerSettingsWindow : public LUS::GuiWindow { +class CheckTrackerSettingsWindow : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; ~CheckTrackerSettingsWindow() {}; protected: @@ -18,9 +18,9 @@ class CheckTrackerSettingsWindow : public LUS::GuiWindow { void UpdateElement() override {}; }; -class CheckTrackerWindow : public LUS::GuiWindow { +class CheckTrackerWindow : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; ~CheckTrackerWindow() {}; protected: diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h index fc5346aa3..87d736058 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h @@ -85,7 +85,7 @@ s16 GetLastEntranceOverride(); s16 GetCurrentGrottoId(); const EntranceData* GetEntranceData(s16); -class EntranceTrackerWindow : public LUS::GuiWindow { +class EntranceTrackerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 5ae80b5e7..5fd158d8f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -560,7 +560,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { void DrawEquip(ItemTrackerItem item) { bool hasEquip = HasEquipment(item); int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); @@ -570,7 +570,7 @@ void DrawQuest(ItemTrackerItem item) { bool hasQuestItem = HasQuestItem(item); int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); ImGui::BeginGroup(); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); if (item.id == QUEST_SKULL_TOKEN) { @@ -640,7 +640,7 @@ void DrawItem(ItemTrackerItem item) { ImGui::BeginGroup(); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); DrawItemCount(item, false); @@ -662,7 +662,7 @@ void DrawBottle(ItemTrackerItem item) { } int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); @@ -677,11 +677,11 @@ void DrawDungeonItem(ItemTrackerItem item) { bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; ImGui::BeginGroup(); if (itemId == ITEM_KEY_SMALL) { - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } else { - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } @@ -722,7 +722,7 @@ void DrawSong(ItemTrackerItem item) { ImVec2 p = ImGui::GetCursorScreenPos(); bool hasSong = HasSong(item); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded), + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); } @@ -1013,7 +1013,7 @@ void ItemTrackerWindow::DrawElement() { int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); int comboButton1Mask = buttonMap[CVarGetInteger(CVAR_TRACKER_ITEM("ComboButton1"), TRACKER_COMBO_BUTTON_L)]; int comboButton2Mask = buttonMap[CVarGetInteger(CVAR_TRACKER_ITEM("ComboButton2"), TRACKER_COMBO_BUTTON_R)]; - OSContPad* buttonsPressed = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); + OSContPad* buttonsPressed = Ship::Context::GetInstance()->GetControlDeck()->GetPads(); bool comboButtonsHeld = buttonsPressed != nullptr && buttonsPressed[0].button & comboButton1Mask && buttonsPressed[0].button & comboButton2Mask; bool isPaused = CVarGetInteger(CVAR_TRACKER_ITEM("ShowOnlyPaused"), 0) == 0 || gPlayState != nullptr && gPlayState->pauseCtx.state > 0; @@ -1144,7 +1144,7 @@ void ItemTrackerSettingsWindow::DrawElement() { CVarSetFloat(CVAR_TRACKER_ITEM("BgColorG"), ChromaKeyBackground.y); CVarSetFloat(CVAR_TRACKER_ITEM("BgColorB"), ChromaKeyBackground.z); CVarSetFloat(CVAR_TRACKER_ITEM("BgColorA"), ChromaKeyBackground.w); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::PopItemWidth(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h index 1fb4e1063..cae869c54 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h @@ -29,7 +29,7 @@ typedef struct ItemTrackerDungeon { std::vector items; } ItemTrackerDungeon; -class ItemTrackerSettingsWindow : public LUS::GuiWindow { +class ItemTrackerSettingsWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; @@ -39,7 +39,7 @@ class ItemTrackerSettingsWindow : public LUS::GuiWindow { void UpdateElement() override {}; }; -class ItemTrackerWindow : public LUS::GuiWindow { +class ItemTrackerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/randomizer/randomizer_settings_window.h b/soh/soh/Enhancements/randomizer/randomizer_settings_window.h index bbb55ca3c..566baeaa3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_settings_window.h +++ b/soh/soh/Enhancements/randomizer/randomizer_settings_window.h @@ -1,6 +1,6 @@ #include -class RandomizerSettingsWindow : public LUS::GuiWindow { +class RandomizerSettingsWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp index 892b5798a..69dec46bc 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp @@ -117,7 +117,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { CVarGetInteger("gLowResMode", 0); if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { - LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier( + Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier( CVarGetFloat("gInternalResolution", 1)); } UIWidgets::Tooltip("Multiplies your output resolution by the value entered."); @@ -126,7 +126,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { #ifndef __WIIU__ if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { - LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); + Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); }; UIWidgets::Tooltip( "Activates multi-sample anti-aliasing when above 1x, up to 8x for 8 samples for every pixel.\n\n" diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.h b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.h index 68680c824..f75931451 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.h +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.h @@ -2,12 +2,12 @@ #include namespace AdvancedResolutionSettings { -class AdvancedResolutionSettingsWindow : public LUS::GuiWindow { +class AdvancedResolutionSettingsWindow : public Ship::GuiWindow { private: bool IsDroppingFrames(); public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; void InitElement() override; void DrawElement() override; diff --git a/soh/soh/Enhancements/savestates.cpp b/soh/soh/Enhancements/savestates.cpp index 54dd56860..4d051911e 100644 --- a/soh/soh/Enhancements/savestates.cpp +++ b/soh/soh/Enhancements/savestates.cpp @@ -837,7 +837,7 @@ extern "C" void ProcessSaveStateRequests(void) { } void SaveStateMgr::SetCurrentSlot(unsigned int slot) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "slot %u set", slot); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "slot %u set", slot); this->currentSlot = slot; } @@ -855,12 +855,12 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { this->states[request.slot] = std::make_shared(OTRGlobals::Instance->gSaveStateMgr, request.slot); } this->states[request.slot]->Save(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "saved state %u", request.slot); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "saved state %u", request.slot); break; case RequestType::LOAD: if (this->states.contains(request.slot)) { this->states[request.slot]->Load(); - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); } @@ -876,7 +876,7 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { if (gPlayState == nullptr) { SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\""); - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "states not available here", request.slot); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "states not available here", request.slot); return SaveStateReturn::FAIL_WRONG_GAMESTATE; } @@ -890,7 +890,7 @@ SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { return SaveStateReturn::SUCCESS; } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); return SaveStateReturn::FAIL_INVALID_SLOT; } [[unlikely]] default: diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 3a375230f..abdcda0ee 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -1039,22 +1039,22 @@ void InitTTSBank() { break; } - auto initData = std::make_shared(); + auto initData = std::make_shared(); initData->Format = RESOURCE_FORMAT_BINARY; - initData->Type = static_cast(LUS::ResourceType::Json); + initData->Type = static_cast(Ship::ResourceType::Json); initData->ResourceVersion = 0; - sceneMap = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; + sceneMap = std::static_pointer_cast( + Ship::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; - miscMap = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; + miscMap = std::static_pointer_cast( + Ship::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; - kaleidoMap = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; + kaleidoMap = std::static_pointer_cast( + Ship::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; - fileChooseMap = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; + fileChooseMap = std::static_pointer_cast( + Ship::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; } void RegisterOnSetGameLanguageHook() { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b79b1f9f3..e796d9f96 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -248,19 +248,19 @@ const char* constCameraStrings[] = { OTRGlobals::OTRGlobals() { std::vector OTRFiles; - std::string mqPath = LUS::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName); + std::string mqPath = Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName); if (std::filesystem::exists(mqPath)) { OTRFiles.push_back(mqPath); } - std::string ootPath = LUS::Context::LocateFileAcrossAppDirs("oot.otr", appShortName); + std::string ootPath = Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName); if (std::filesystem::exists(ootPath)) { OTRFiles.push_back(ootPath); } - std::string sohOtrPath = LUS::Context::GetPathRelativeToAppBundle("soh.otr"); + std::string sohOtrPath = Ship::Context::GetPathRelativeToAppBundle("soh.otr"); if (std::filesystem::exists(sohOtrPath)) { OTRFiles.push_back(sohOtrPath); } - std::string patchesPath = LUS::Context::LocateFileAcrossAppDirs("mods", appShortName); + std::string patchesPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName); std::vector patchOTRs = {}; if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) { if (std::filesystem::is_directory(patchesPath)) { @@ -302,7 +302,7 @@ OTRGlobals::OTRGlobals() { OOT_PAL_GC_DBG2 }; - context = LUS::Context::CreateUninitializedInstance("Ship of Harkinian", appShortName, "shipofharkinian.json"); + context = Ship::Context::CreateUninitializedInstance("Ship of Harkinian", appShortName, "shipofharkinian.json"); context->InitLogging(); context->InitGfxDebugger(); @@ -378,7 +378,7 @@ OTRGlobals::OTRGlobals() { #if defined(__SWITCH__) SPDLOG_ERROR("Invalid OTR File!"); #elif defined(__WIIU__) - LUS::WiiU::ThrowInvalidOTR(); + Ship::WiiU::ThrowInvalidOTR(); #else SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Invalid OTR File", "Attempted to load an invalid OTR file. Try regenerating.", nullptr); @@ -450,15 +450,15 @@ bool OTRGlobals::HasOriginal() { } uint32_t OTRGlobals::GetInterpolationFPS() { - if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { return CVarGetInteger("gInterpolationFPS", 20); } if (CVarGetInteger("gMatchRefreshRate", 0)) { - return LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); + return Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); } - return std::min(LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(), CVarGetInteger("gInterpolationFPS", 20)); + return std::min(Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(), CVarGetInteger("gInterpolationFPS", 20)); } struct ExtensionEntry { @@ -853,7 +853,7 @@ extern "C" RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID) { } extern "C" void OTRExtScanner() { - auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles().get(); + auto lst = *Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles().get(); for (auto& rPath : lst) { std::vector raw = StringHelper::Split(rPath, "."); @@ -876,13 +876,13 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) { OTRVersion version = {}; // Use a temporary archive instance to load the otr and read the version file - auto archive = LUS::OtrArchive(otrPath); + auto archive = Ship::OtrArchive(otrPath); if (archive.Open()) { - auto t = archive.LoadFile("portVersion", std::make_shared()); + auto t = archive.LoadFile("portVersion", std::make_shared()); if (t != nullptr && t->IsLoaded) { - auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); - auto reader = std::make_shared(stream); - LUS::Endianness endianness = (LUS::Endianness)reader->ReadUByte(); + auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); + auto reader = std::make_shared(stream); + Ship::Endianness endianness = (Ship::Endianness)reader->ReadUByte(); reader->SetEndianness(endianness); version.major = reader->ReadUInt16(); version.minor = reader->ReadUInt16(); @@ -913,7 +913,7 @@ void CheckSoHOTRVersion(std::string otrPath) { Extractor::ShowErrorBox("soh.otr file is missing", msg.c_str()); exit(1); #elif defined(__SWITCH__) - LUS::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou are missing the soh.otr file." + msg).c_str()); + Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou are missing the soh.otr file." + msg).c_str()); #elif defined(__WIIU__) OSFatal(("You are missing the soh.otr file\n\n" + msg).c_str()); #endif @@ -926,7 +926,7 @@ void CheckSoHOTRVersion(std::string otrPath) { Extractor::ShowErrorBox("soh.otr file version does not match", msg.c_str()); exit(1); #elif defined(__SWITCH__) - LUS::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou have an old soh.otr file." + msg).c_str()); + Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou have an old soh.otr file." + msg).c_str()); #elif defined(__WIIU__) OSFatal(("You have an old soh.otr file\n\n" + msg).c_str()); #endif @@ -937,7 +937,7 @@ void CheckSoHOTRVersion(std::string otrPath) { // For Windows/Mac/Linux if the version doesn't match, offer to void DetectOTRVersion(std::string fileName, bool isMQ) { bool isOtrOld = false; - std::string otrPath = LUS::Context::LocateFileAcrossAppDirs(fileName, appShortName); + std::string otrPath = Ship::Context::LocateFileAcrossAppDirs(fileName, appShortName); // Doesn't exist so nothing to do here if (!std::filesystem::exists(otrPath)) { @@ -967,7 +967,7 @@ void DetectOTRVersion(std::string fileName, bool isMQ) { fileName.c_str(), version); if (Extractor::ShowYesNoBox("Old OTR File Found", msgBuf) == IDYES) { - std::string installPath = LUS::Context::GetAppBundlePath(); + std::string installPath = Ship::Context::GetAppBundlePath(); if (!std::filesystem::exists(installPath + "/assets/extractor")) { Extractor::ShowErrorBox("Extractor assets not found", "Unable to regenerate. Missing assets/extractor folder needed to generate OTR file.\n\nExiting..."); @@ -975,17 +975,17 @@ void DetectOTRVersion(std::string fileName, bool isMQ) { } Extractor extract; - if (!extract.Run(LUS::Context::GetAppDirectoryPath(appShortName), isMQ ? RomSearchMode::MQ : RomSearchMode::Vanilla)) { + if (!extract.Run(Ship::Context::GetAppDirectoryPath(appShortName), isMQ ? RomSearchMode::MQ : RomSearchMode::Vanilla)) { Extractor::ShowErrorBox("Error", "An error occured, no OTR file was generated.\n\nExiting..."); exit(1); } - extract.CallZapd(installPath, LUS::Context::GetAppDirectoryPath(appShortName)); + extract.CallZapd(installPath, Ship::Context::GetAppDirectoryPath(appShortName)); } else { exit(1); } #elif defined(__SWITCH__) - LUS::Switch::PrintErrorMessageToScreen("\x1b[2;2HYou've launched the Ship with an old game OTR file." + Ship::Switch::PrintErrorMessageToScreen("\x1b[2;2HYou've launched the Ship with an old game OTR file." "\x1b[4;2HPlease regenerate a new game OTR and relaunch." "\x1b[6;2HPress the Home button to exit..."); #elif defined(__WIIU__) @@ -1013,9 +1013,9 @@ bool PathTestCleanup(FILE* tfile) { extern "C" void InitOTR() { #ifdef __SWITCH__ - LUS::Switch::Init(LUS::PreInitPhase); + Ship::Switch::Init(Ship::PreInitPhase); #elif defined(__WIIU__) - LUS::WiiU::Init(appShortName); + Ship::WiiU::Init(appShortName); #endif #ifdef _WIN32 @@ -1055,13 +1055,13 @@ extern "C" void InitOTR() { } #endif - CheckSoHOTRVersion(LUS::Context::GetPathRelativeToAppBundle("soh.otr")); + CheckSoHOTRVersion(Ship::Context::GetPathRelativeToAppBundle("soh.otr")); - if (!std::filesystem::exists(LUS::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName)) && - !std::filesystem::exists(LUS::Context::LocateFileAcrossAppDirs("oot.otr", appShortName))){ + if (!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName)) && + !std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName))){ #if not defined(__SWITCH__) && not defined(__WIIU__) - std::string installPath = LUS::Context::GetAppBundlePath(); + std::string installPath = Ship::Context::GetAppBundlePath(); if (!std::filesystem::exists(installPath + "/assets/extractor")) { Extractor::ShowErrorBox("Extractor assets not found", "No OTR files found. Missing assets/extractor folder needed to generate OTR file.\n\nExiting..."); @@ -1071,26 +1071,26 @@ extern "C" void InitOTR() { bool generatedOtrIsMQ = false; if (Extractor::ShowYesNoBox("No OTR Files", "No OTR files found. Generate one now?") == IDYES) { Extractor extract; - if (!extract.Run(LUS::Context::GetAppDirectoryPath(appShortName))) { + if (!extract.Run(Ship::Context::GetAppDirectoryPath(appShortName))) { Extractor::ShowErrorBox("Error", "An error occured, no OTR file was generated.\n\nExiting..."); exit(1); } - extract.CallZapd(installPath, LUS::Context::GetAppDirectoryPath(appShortName)); + extract.CallZapd(installPath, Ship::Context::GetAppDirectoryPath(appShortName)); generatedOtrIsMQ = extract.IsMasterQuest(); } else { exit(1); } if (Extractor::ShowYesNoBox("Extraction Complete", "ROM Extracted. Extract another?") == IDYES) { Extractor extract; - if (!extract.Run(LUS::Context::GetAppDirectoryPath(appShortName), generatedOtrIsMQ ? RomSearchMode::Vanilla : RomSearchMode::MQ)) { + if (!extract.Run(Ship::Context::GetAppDirectoryPath(appShortName), generatedOtrIsMQ ? RomSearchMode::Vanilla : RomSearchMode::MQ)) { Extractor::ShowErrorBox("Error", "An error occured, an OTR file may have been generated by a different step.\n\nContinuing..."); } else { - extract.CallZapd(installPath, LUS::Context::GetAppDirectoryPath(appShortName)); + extract.CallZapd(installPath, Ship::Context::GetAppDirectoryPath(appShortName)); } } #elif defined(__SWITCH__) - LUS::Switch::PrintErrorMessageToScreen("\x1b[2;2HYou've launched the Ship without a game OTR file." + Ship::Switch::PrintErrorMessageToScreen("\x1b[2;2HYou've launched the Ship without a game OTR file." "\x1b[4;2HPlease generate a game OTR and relaunch." "\x1b[6;2HPress the Home button to exit..."); #elif defined(__WIIU__) @@ -1165,9 +1165,9 @@ extern "C" void InitOTR() { } #endif - std::shared_ptr conf = OTRGlobals::Instance->context->GetConfig(); - conf->RegisterConfigVersionUpdater(std::make_shared()); - conf->RegisterConfigVersionUpdater(std::make_shared()); + std::shared_ptr conf = OTRGlobals::Instance->context->GetConfig(); + conf->RegisterConfigVersionUpdater(std::make_shared()); + conf->RegisterConfigVersionUpdater(std::make_shared()); conf->RunVersionUpdates(); } @@ -1245,14 +1245,14 @@ extern bool ToggleAltAssetsAtEndOfFrame; extern "C" void Graph_StartFrame() { #ifndef __WIIU__ - using LUS::KbScancode; + using Ship::KbScancode; int32_t dwScancode = OTRGlobals::Instance->context->GetWindow()->GetLastScancode(); OTRGlobals::Instance->context->GetWindow()->SetLastScancode(-1); switch (dwScancode) { case KbScancode::LUS_KB_F5: { if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; } @@ -1274,7 +1274,7 @@ extern "C" void Graph_StartFrame() { } case KbScancode::LUS_KB_F6: { if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; } @@ -1289,7 +1289,7 @@ extern "C" void Graph_StartFrame() { } case KbScancode::LUS_KB_F7: { if (CVarGetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0) == 0) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()-> TextDrawNotification(6.0f, true, "Save states not enabled. Check Cheats Menu."); return; } @@ -1431,15 +1431,15 @@ extern "C" uint16_t OTRGetPixelDepth(float x, float y) { } extern "C" uint32_t ResourceMgr_GetNumGameVersions() { - return LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions().size(); + return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions().size(); } extern "C" uint32_t ResourceMgr_GetGameVersion(int index) { - return LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; + return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; } extern "C" uint32_t ResourceMgr_GetGamePlatform(int index) { - uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; + uint32_t version = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; switch (version) { case OOT_NTSC_US_10: @@ -1462,7 +1462,7 @@ extern "C" uint32_t ResourceMgr_GetGamePlatform(int index) { } extern "C" uint32_t ResourceMgr_GetGameRegion(int index) { - uint32_t version = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; + uint32_t version = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->GetGameVersions()[index]; switch (version) { case OOT_NTSC_US_10: @@ -1531,10 +1531,10 @@ extern "C" uint32_t ResourceMgr_IsGameMasterQuest() { } extern "C" void ResourceMgr_LoadDirectory(const char* resName) { - LUS::Context::GetInstance()->GetResourceManager()->LoadDirectory(resName); + Ship::Context::GetInstance()->GetResourceManager()->LoadDirectory(resName); } extern "C" void ResourceMgr_DirtyDirectory(const char* resName) { - LUS::Context::GetInstance()->GetResourceManager()->DirtyDirectory(resName); + Ship::Context::GetInstance()->GetResourceManager()->DirtyDirectory(resName); } extern "C" void ResourceMgr_UnloadResource(const char* resName) { @@ -1542,13 +1542,13 @@ extern "C" void ResourceMgr_UnloadResource(const char* resName) { if (path.substr(0, 7) == "__OTR__") { path = path.substr(7); } - auto res = LUS::Context::GetInstance()->GetResourceManager()->UnloadResource(path); + auto res = Ship::Context::GetInstance()->GetResourceManager()->UnloadResource(path); } // OTRTODO: There is probably a more elegant way to go about this... // Kenix: This is definitely leaking memory when it's called. extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) { - auto lst = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(searchMask); + auto lst = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(searchMask); char** result = (char**)malloc(lst->size() * sizeof(char*)); for (size_t i = 0; i < lst->size(); i++) { @@ -1592,7 +1592,7 @@ extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { } } -std::shared_ptr GetResourceByNameHandlingMQ(const char* path) { +std::shared_ptr GetResourceByNameHandlingMQ(const char* path) { std::string Path = path; if (ResourceMgr_IsGameMasterQuest()) { size_t pos = 0; @@ -1600,7 +1600,7 @@ std::shared_ptr GetResourceByNameHandlingMQ(const char* path) { Path.replace(pos, 7, "/mq/"); } } - return LUS::Context::GetInstance()->GetResourceManager()->LoadResource(Path.c_str()); + return Ship::Context::GetInstance()->GetResourceManager()->LoadResource(Path.c_str()); } extern "C" char* GetResourceDataByNameHandlingMQ(const char* path) { @@ -1728,7 +1728,7 @@ std::unordered_map> origi // instead (When that is available). Index can be found using the commented out section below. extern "C" void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction) { auto res = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource(path)); + Ship::Context::GetInstance()->GetResourceManager()->LoadResource(path)); // Leaving this here for people attempting to find the correct Dlist index to patch /*if (strcmp("__OTR__objects/object_gi_longsword/gGiBiggoronSwordDL", path) == 0) { @@ -1767,7 +1767,7 @@ extern "C" void ResourceMgr_PatchGfxByName(const char* path, const char* patchNa extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex) { auto res = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource(path)); + Ship::Context::GetInstance()->GetResourceManager()->LoadResource(path)); // Do not patch custom assets as they most likely do not have the same instructions as authentic assets if (res->GetInitData()->IsCustom) { @@ -1790,7 +1790,7 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch extern "C" void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName) { if (originalGfx.contains(path) && originalGfx[path].contains(patchName)) { auto res = std::static_pointer_cast( - LUS::Context::GetInstance()->GetResourceManager()->LoadResource(path)); + Ship::Context::GetInstance()->GetResourceManager()->LoadResource(path)); Gfx* gfx = (Gfx*)&res->Instructions[originalGfx[path][patchName].index]; *gfx = originalGfx[path][patchName].instruction; @@ -1850,7 +1850,7 @@ extern "C" SoundFontSample* ReadCustomSample(const char* path) { ExtensionEntry entry = ExtensionCache[path]; - auto sampleRaw = LUS::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path); + auto sampleRaw = Ship::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path); uint32_t* strem = (uint32_t*)sampleRaw->Buffer.get(); uint8_t* strem2 = (uint8_t*)strem; @@ -1941,7 +1941,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel bool isAlt = CVarGetInteger("gAltAssets", 0); if (isAlt) { - pathStr = LUS::IResource::gAltAssetPrefix + pathStr; + pathStr = Ship::IResource::gAltAssetPrefix + pathStr; } SkeletonHeader* skelHeader = (SkeletonHeader*) ResourceGetDataByName(pathStr.c_str()); @@ -1975,8 +1975,8 @@ extern "C" s32* ResourceMgr_LoadCSByName(const char* path) { return (s32*)GetResourceDataByNameHandlingMQ(path); } -std::filesystem::path GetSaveFile(std::shared_ptr Conf) { - const std::string fileName = Conf->GetString("Game.SaveName", LUS::Context::GetPathRelativeToAppDirectory("oot_save.sav")); +std::filesystem::path GetSaveFile(std::shared_ptr Conf) { + const std::string fileName = Conf->GetString("Game.SaveName", Ship::Context::GetPathRelativeToAppDirectory("oot_save.sav")); std::filesystem::path saveFile = std::filesystem::absolute(fileName); if (!exists(saveFile.parent_path())) { @@ -1987,13 +1987,13 @@ std::filesystem::path GetSaveFile(std::shared_ptr Conf) { } std::filesystem::path GetSaveFile() { - const std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); + const std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); return GetSaveFile(pConf); } void OTRGlobals::CheckSaveFile(size_t sramSize) const { - const std::shared_ptr pConf = Instance->context->GetConfig(); + const std::shared_ptr pConf = Instance->context->GetConfig(); std::filesystem::path savePath = GetSaveFile(pConf); std::fstream saveFile(savePath, std::fstream::in | std::fstream::out | std::fstream::binary); @@ -2210,19 +2210,19 @@ Color_RGB8 GetColorForControllerLED() { extern "C" void OTRControllerCallback(uint8_t rumble) { // We call this every tick, SDL accounts for this use and prevents driver spam // https://github.com/libsdl-org/SDL/blob/f17058b562c8a1090c0c996b42982721ace90903/src/joystick/SDL_joystick.c#L1114-L1144 - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetLED()->SetLEDColor(GetColorForControllerLED()); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetLED()->SetLEDColor(GetColorForControllerLED()); static std::shared_ptr controllerConfigWindow = nullptr; if (controllerConfigWindow == nullptr) { - controllerConfigWindow = std::dynamic_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Input Editor")); + controllerConfigWindow = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Input Editor")); } else if (controllerConfigWindow->TestingRumble()) { return; } if (rumble) { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetRumble()->StartRumble(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetRumble()->StartRumble(); } else { - LUS::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetRumble()->StopRumble(); + Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(0)->GetRumble()->StopRumble(); } } @@ -2262,7 +2262,7 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) { } extern "C" int Controller_ShouldRumble(size_t slot) { - for (auto [id, mapping] : LUS::Context::GetInstance() + for (auto [id, mapping] : Ship::Context::GetInstance() ->GetControlDeck() ->GetControllerByPort(static_cast(slot)) ->GetRumble() @@ -2650,12 +2650,12 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } extern "C" void Overlay_DisplayText(float duration, const char* text) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); } extern "C" void Overlay_DisplayText_Seconds(int seconds, const char* text) { float duration = seconds * OTRGlobals::Instance->GetInterpolationFPS() * 0.05; - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); } extern "C" void Entrance_ClearEntranceTrackingData(void) { @@ -2741,14 +2741,14 @@ void SoH_ProcessDroppedFiles(std::string filePath) { } } - auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui(); + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); gui->GetGuiWindow("Console")->Hide(); gui->GetGuiWindow("Actor Viewer")->Hide(); gui->GetGuiWindow("Collision Viewer")->Hide(); gui->GetGuiWindow("Save Editor")->Hide(); gui->GetGuiWindow("Display List Viewer")->Hide(); gui->GetGuiWindow("Stats")->Hide(); - std::dynamic_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->ClearBindings(); + std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->ClearBindings(); gui->SaveConsoleVariablesOnNextTick(); @@ -2756,12 +2756,12 @@ void SoH_ProcessDroppedFiles(std::string filePath) { gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Configuration Loaded. Hash: %d", finalHash); } catch (std::exception& e) { SPDLOG_ERROR("Failed to load config file: {}", e.what()); - auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui(); + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file"); return; } catch (...) { SPDLOG_ERROR("Failed to load config file"); - auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui(); + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file"); return; } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 49b41ce86..3a1b3e1f6 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -37,7 +37,7 @@ class OTRGlobals public: static OTRGlobals* Instance; - std::shared_ptr context; + std::shared_ptr context; std::shared_ptr gSaveStateMgr; std::shared_ptr gRandomizer; diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index eadfb75de..484a9e1b1 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -44,12 +44,12 @@ void SaveManager::ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, v } std::filesystem::path SaveManager::GetFileName(int fileNum) { - const std::filesystem::path sSavePath(LUS::Context::GetPathRelativeToAppDirectory("Save")); + const std::filesystem::path sSavePath(Ship::Context::GetPathRelativeToAppDirectory("Save")); return sSavePath / ("file" + std::to_string(fileNum + 1) + ".sav"); } std::filesystem::path SaveManager::GetFileTempName(int fileNum) { - const std::filesystem::path sSavePath(LUS::Context::GetPathRelativeToAppDirectory("Save")); + const std::filesystem::path sSavePath(Ship::Context::GetPathRelativeToAppDirectory("Save")); return sSavePath / ("file" + std::to_string(fileNum + 1) + ".temp"); } @@ -371,10 +371,10 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f void SaveManager::Init() { // Wait on saves that snuck through the Wait in OnExitGame ThreadPoolWait(); - const std::filesystem::path sSavePath(LUS::Context::GetPathRelativeToAppDirectory("Save")); + const std::filesystem::path sSavePath(Ship::Context::GetPathRelativeToAppDirectory("Save")); const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav"); - auto sOldSavePath = LUS::Context::GetPathRelativeToAppDirectory("oot_save.sav"); - auto sOldBackupSavePath = LUS::Context::GetPathRelativeToAppDirectory("oot_save.bak"); + auto sOldSavePath = Ship::Context::GetPathRelativeToAppDirectory("oot_save.sav"); + auto sOldBackupSavePath = Ship::Context::GetPathRelativeToAppDirectory("oot_save.bak"); // If the save directory does not exist, create it if (!std::filesystem::exists(sSavePath)) { @@ -1017,7 +1017,7 @@ void SaveManager::SaveGlobal() { globalBlock["zTargetSetting"] = gSaveContext.zTargetSetting; globalBlock["language"] = gSaveContext.language; - const std::filesystem::path sSavePath(LUS::Context::GetPathRelativeToAppDirectory("Save")); + const std::filesystem::path sSavePath(Ship::Context::GetPathRelativeToAppDirectory("Save")); const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav"); std::ofstream output(sGlobalPath); @@ -1076,7 +1076,7 @@ void SaveManager::LoadFile(int fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } catch (const std::exception& e) { input.close(); - std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak")); + std::filesystem::path newFile(Ship::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak")); #if defined(__SWITCH__) || defined(__WIIU__) copy_file(fileName.c_str(), newFile.c_str()); #else diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 28366a668..9055087bd 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -112,9 +112,9 @@ namespace SohGui { std::shared_ptr mSohMenuBar; - std::shared_ptr mConsoleWindow; - std::shared_ptr mStatsWindow; - std::shared_ptr mInputEditorWindow; + std::shared_ptr mConsoleWindow; + std::shared_ptr mStatsWindow; + std::shared_ptr mInputEditorWindow; std::shared_ptr mAudioEditorWindow; std::shared_ptr mInputViewer; @@ -137,10 +137,10 @@ namespace SohGui { std::shared_ptr mModalWindow; void SetupGuiElements() { - auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui(); + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); mSohMenuBar = std::make_shared("gOpenMenuBar", CVarGetInteger("gOpenMenuBar", 0)); - gui->SetMenuBar(std::reinterpret_pointer_cast(mSohMenuBar)); + gui->SetMenuBar(std::reinterpret_pointer_cast(mSohMenuBar)); if (gui->GetMenuBar() && !gui->GetMenuBar()->IsVisible()) { #if defined(__SWITCH__) || defined(__WIIU__) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 20bcc43b8..e7a99b39f 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -106,11 +106,11 @@ namespace SohGui { void DrawMenuBarIcon() { static bool gameIconLoaded = false; if (!gameIconLoaded) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Game_Icon", "textures/icons/gIcon.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Game_Icon", "textures/icons/gIcon.png"); gameIconLoaded = true; } - if (LUS::Context::GetInstance()->GetWindow()->GetGui()->HasTextureByName("Game_Icon")) { + if (Ship::Context::GetInstance()->GetWindow()->GetGui()->HasTextureByName("Game_Icon")) { #ifdef __SWITCH__ ImVec2 iconSize = ImVec2(20.0f, 20.0f); float posScale = 1.0f; @@ -122,7 +122,7 @@ void DrawMenuBarIcon() { float posScale = 1.0f; #endif ImGui::SetCursorPos(ImVec2(5, 2.5f) * posScale); - ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), iconSize); + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), iconSize); ImGui::SameLine(); ImGui::SetCursorPos(ImVec2(25, 0) * posScale); } @@ -137,12 +137,12 @@ void DrawShipMenu() { "[-]" #endif )) { - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetMenuBar()->ToggleVisibility(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetMenuBar()->ToggleVisibility(); } UIWidgets::Spacer(0); #if !defined(__SWITCH__) && !defined(__WIIU__) if (ImGui::MenuItem("Toggle Fullscreen", "F11")) { - LUS::Context::GetInstance()->GetWindow()->ToggleFullscreen(); + Ship::Context::GetInstance()->GetWindow()->ToggleFullscreen(); } UIWidgets::Spacer(0); #endif @@ -155,25 +155,25 @@ void DrawShipMenu() { "" #endif )) { - std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); + std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); } #if !defined(__SWITCH__) && !defined(__WIIU__) UIWidgets::Spacer(0); if (ImGui::MenuItem("Open App Files Folder")) { - std::string filesPath = LUS::Context::GetInstance()->GetAppDirectoryPath(); + std::string filesPath = Ship::Context::GetInstance()->GetAppDirectoryPath(); SDL_OpenURL(std::string("file:///" + std::filesystem::absolute(filesPath).string()).c_str()); } UIWidgets::Spacer(0); if (ImGui::MenuItem("Quit")) { - LUS::Context::GetInstance()->GetWindow()->Close(); + Ship::Context::GetInstance()->GetWindow()->Close(); } #endif ImGui::EndMenu(); } } -extern std::shared_ptr mInputEditorWindow; +extern std::shared_ptr mInputEditorWindow; extern std::shared_ptr mInputViewer; extern std::shared_ptr mInputViewerSettings; extern std::shared_ptr mAdvancedResolutionSettingsWindow; @@ -196,27 +196,27 @@ void DrawSettingsMenu() { Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); } - static std::unordered_map audioBackendNames = { - { LUS::AudioBackend::WASAPI, "Windows Audio Session API" }, - { LUS::AudioBackend::SDL, "SDL" } + static std::unordered_map audioBackendNames = { + { Ship::AudioBackend::WASAPI, "Windows Audio Session API" }, + { Ship::AudioBackend::SDL, "SDL" } }; ImGui::Text("Audio API (Needs reload)"); - auto currentAudioBackend = LUS::Context::GetInstance()->GetAudio()->GetAudioBackend(); + auto currentAudioBackend = Ship::Context::GetInstance()->GetAudio()->GetAudioBackend(); - if (LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) { + if (Ship::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } if (ImGui::BeginCombo("##AApi", audioBackendNames[currentAudioBackend])) { - for (uint8_t i = 0; i < LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size(); i++) { - auto backend = LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->data()[i]; + for (uint8_t i = 0; i < Ship::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size(); i++) { + auto backend = Ship::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->data()[i]; if (ImGui::Selectable(audioBackendNames[backend], backend == currentAudioBackend)) { - LUS::Context::GetInstance()->GetAudio()->SetAudioBackend(backend); + Ship::Context::GetInstance()->GetAudio()->SetAudioBackend(backend); } } ImGui::EndCombo(); } - if (LUS::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) { + if (Ship::Context::GetInstance()->GetAudio()->GetAvailableAudioBackends()->size() <= 1) { UIWidgets::ReEnableComponent(""); } @@ -274,7 +274,7 @@ void DrawSettingsMenu() { CVarGetInteger("gAdvancedResolution.Enabled", 0); if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { - LUS::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); + Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); } UIWidgets::Tooltip("Resolution scale. Multiplies output resolution by this value, on each axis relative to window size.\n" "Lower values may improve performance.\n" @@ -307,7 +307,7 @@ void DrawSettingsMenu() { if (UIWidgets::PaddedEnhancementSliderInt( (CVarGetInteger("gMSAAValue", 1) == 1) ? "Anti-aliasing (MSAA): Off" : "Anti-aliasing (MSAA): %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { - LUS::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); + Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); } UIWidgets::Tooltip("Activates MSAA (multi-sample anti-aliasing) from 2x up to 8x, to smooth the edges of rendered geometry.\n" "Higher sample count will result in smoother edges on models, but may reduce performance.\n\n" @@ -318,10 +318,10 @@ void DrawSettingsMenu() { { // FPS Slider const int minFps = 20; static int maxFps; - if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { maxFps = 360; } else { - maxFps = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); + maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); } int currentFps = fmax(fmin(OTRGlobals::Instance->GetInterpolationFPS(), maxFps), minFps); #ifdef __WIIU__ @@ -383,15 +383,15 @@ void DrawSettingsMenu() { currentFps = 60; } CVarSetInteger("gInterpolationFPS", currentFps); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); #else bool matchingRefreshRate = - CVarGetInteger("gMatchRefreshRate", 0) && LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() != LUS::WindowBackend::DX11; + CVarGetInteger("gMatchRefreshRate", 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11; UIWidgets::PaddedEnhancementSliderInt( (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps", "##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); #endif - if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { UIWidgets::Tooltip( "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n" "This is purely visual and does not impact game logic, execution of glitches etc.\n" @@ -406,13 +406,13 @@ void DrawSettingsMenu() { } } // END FPS Slider - if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { UIWidgets::Spacer(0); if (ImGui::Button("Match Frame Rate to Refresh Rate")) { - int hz = LUS::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); + int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); if (hz >= 20 && hz <= 360) { CVarSetInteger("gInterpolationFPS", hz); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } } else { @@ -420,7 +420,7 @@ void DrawSettingsMenu() { } UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate."); - if (LUS::Context::GetInstance()->GetWindow()->GetWindowBackend() == LUS::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", "##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false); UIWidgets::Tooltip( @@ -442,52 +442,52 @@ void DrawSettingsMenu() { UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); - static std::unordered_map windowBackendNames = { - { LUS::WindowBackend::DX11, "DirectX" }, - { LUS::WindowBackend::SDL_OPENGL, "OpenGL"}, - { LUS::WindowBackend::SDL_METAL, "Metal" }, - { LUS::WindowBackend::GX2, "GX2"} + static std::unordered_map windowBackendNames = { + { Ship::WindowBackend::DX11, "DirectX" }, + { Ship::WindowBackend::SDL_OPENGL, "OpenGL"}, + { Ship::WindowBackend::SDL_METAL, "Metal" }, + { Ship::WindowBackend::GX2, "GX2"} }; ImGui::Text("Renderer API (Needs reload)"); - LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend(); - LUS::WindowBackend configWindowBackend; - int configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); - if (configWindowBackendId != -1 && configWindowBackendId < static_cast(LUS::WindowBackend::BACKEND_COUNT)) { - configWindowBackend = static_cast(configWindowBackendId); + Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend(); + Ship::WindowBackend configWindowBackend; + int configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); + if (configWindowBackendId != -1 && configWindowBackendId < static_cast(Ship::WindowBackend::BACKEND_COUNT)) { + configWindowBackend = static_cast(configWindowBackendId); } else { configWindowBackend = runningWindowBackend; } - if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) { - for (size_t i = 0; i < LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) { - auto backend = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i]; + for (size_t i = 0; i < Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) { + auto backend = Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i]; if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) { - LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend)); - LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", + Ship::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend)); + Ship::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", windowBackendNames[backend]); - LUS::Context::GetInstance()->GetConfig()->Save(); + Ship::Context::GetInstance()->GetConfig()->Save(); } } ImGui::EndCombo(); } - if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { UIWidgets::ReEnableComponent(""); } - if (LUS::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) { + if (Ship::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) { UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false); UIWidgets::Tooltip("Activate vertical sync, to prevent screen tearing."); } - if (LUS::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) { + if (Ship::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) { UIWidgets::PaddedEnhancementCheckbox("Windowed fullscreen", "gSdlWindowedFullscreen", true, false); } - if (LUS::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) { + if (Ship::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) { UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows (Needs reload)", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect."); } @@ -503,7 +503,7 @@ void DrawSettingsMenu() { UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); // Draw LUS settings menu (such as Overlays Text Font) - LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->DrawSettings(); ImGui::EndMenu(); } @@ -1417,9 +1417,9 @@ void DrawEnhancementsMenu() { #ifdef __SWITCH__ UIWidgets::Spacer(0); ImGui::Text("Switch performance mode"); - if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("SwitchPerfMode"), SWITCH_CPU_PROFILES, (int)LUS::SwitchProfiles::STOCK)) { - SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[CVarGetInteger(CVAR_ENHANCEMENT("SwitchPerfMode"), (int)LUS::SwitchProfiles::STOCK)]); - LUS::Switch::ApplyOverclock(); + if (UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("SwitchPerfMode"), SWITCH_CPU_PROFILES, (int)Ship::SwitchProfiles::STOCK)) { + SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[CVarGetInteger(CVAR_ENHANCEMENT("SwitchPerfMode"), (int)Ship::SwitchProfiles::STOCK)]); + Ship::Switch::ApplyOverclock(); } #endif @@ -1504,7 +1504,7 @@ void DrawCheatsMenu() { if (UIWidgets::PaddedEnhancementCheckbox("I promise I have read the warning", CVAR_CHEAT("SaveStatePromise"), true, false)) { CVarSetInteger(CVAR_CHEAT("SaveStatesEnabled"), 0); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (CVarGetInteger(CVAR_CHEAT("SaveStatePromise"), 0) == 1) { UIWidgets::PaddedEnhancementCheckbox("I understand, enable save states", CVAR_CHEAT("SaveStatesEnabled"), true, @@ -1598,8 +1598,8 @@ void DrawCheatsMenu() { CVarSetInteger(CVAR_CHEAT("EnableBetaQuest"), betaQuestEnabled); CVarSetInteger(CVAR_CHEAT("BetaQuestWorld"), betaQuestWorld); - std::reinterpret_pointer_cast(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + std::reinterpret_pointer_cast(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (!isBetaQuestEnabled) { @@ -1613,8 +1613,8 @@ void DrawCheatsMenu() { } } -extern std::shared_ptr mStatsWindow; -extern std::shared_ptr mConsoleWindow; +extern std::shared_ptr mStatsWindow; +extern std::shared_ptr mConsoleWindow; extern std::shared_ptr mSaveEditorWindow; extern std::shared_ptr mColViewerWindow; extern std::shared_ptr mActorViewerWindow; @@ -1772,7 +1772,7 @@ void DrawRemoteControlMenu() { port = 43384; break; } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: @@ -1808,14 +1808,14 @@ void DrawRemoteControlMenu() { ImGui::Text("Remote IP & Port"); if (ImGui::InputText("##gRemote.IP", (char*)ip.c_str(), ip.capacity() + 1)) { CVarSetString(CVAR_REMOTE("IP"), ip.c_str()); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetFontSize() * 5); if (ImGui::InputScalar("##gRemote.Port", ImGuiDataType_U16, &port)) { CVarSetInteger(CVAR_REMOTE("Port"), port); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::PopItemWidth(); @@ -1828,7 +1828,7 @@ void DrawRemoteControlMenu() { if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) { if (GameInteractor::Instance->isRemoteInteractorEnabled) { CVarSetInteger(CVAR_REMOTE("Enabled"), 0); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Disable(); @@ -1839,7 +1839,7 @@ void DrawRemoteControlMenu() { } } else { CVarSetInteger(CVAR_REMOTE("Enabled"), 1); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: GameInteractorSail::Instance->Enable(); diff --git a/soh/soh/SohMenuBar.h b/soh/soh/SohMenuBar.h index ce62344ad..99fb8a0ae 100644 --- a/soh/soh/SohMenuBar.h +++ b/soh/soh/SohMenuBar.h @@ -5,9 +5,9 @@ #include "window/gui/GuiElement.h" namespace SohGui { -class SohMenuBar : public LUS::GuiMenuBar { +class SohMenuBar : public Ship::GuiMenuBar { public: - using LUS::GuiMenuBar::GuiMenuBar; + using Ship::GuiMenuBar::GuiMenuBar; protected: void DrawElement() override; void InitElement() override {}; diff --git a/soh/soh/SohModals.h b/soh/soh/SohModals.h index 6f5acb2c0..b64e180b6 100644 --- a/soh/soh/SohModals.h +++ b/soh/soh/SohModals.h @@ -4,9 +4,9 @@ #include "window/gui/GuiMenuBar.h" #include "window/gui/GuiElement.h" -class SohModalWindow : public LUS::GuiWindow { +class SohModalWindow : public Ship::GuiWindow { public: - using LUS::GuiWindow::GuiWindow; + using GuiWindow::GuiWindow; void InitElement() override {}; void DrawElement() override; diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 4817e85fc..5bf2e7b73 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -208,7 +208,7 @@ namespace UIWidgets { bool val = (bool)CVarGetInteger(cvarName, defaultValue); if (CustomCheckbox(text, &val, disabled, disabledGraphic)) { CVarSetInteger(cvarName, val); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); changed = true; } @@ -248,7 +248,7 @@ namespace UIWidgets { CVarSetInteger(cvarName, i); selected = i; changed = true; - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } } @@ -261,7 +261,7 @@ namespace UIWidgets { if (disabledValue >= 0 && selected != disabledValue) { CVarSetInteger(cvarName, disabledValue); changed = true; - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } @@ -351,7 +351,7 @@ namespace UIWidgets { if (changed && (oldVal != val)) { CVarSetInteger(cvarName, val); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } else { changed = false; } @@ -452,7 +452,7 @@ namespace UIWidgets { ss << std::setprecision(ticks + 1) << std::setiosflags(std::ios_base::fixed) << val; val = std::stof(ss.str()); CVarSetFloat(cvarName, val); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } else { changed = false; } @@ -501,7 +501,7 @@ namespace UIWidgets { int val = CVarGetInteger(cvarName, 0); if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { CVarSetInteger(cvarName, id); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ret = true; } ImGui::SameLine(); @@ -528,7 +528,7 @@ namespace UIWidgets { CVarSetColor(cvarName, colorsRGBA); CVarSetInteger(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); changed = true; } Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color"); @@ -553,7 +553,7 @@ namespace UIWidgets { NewColors.b = fmin(fmax(colors->z * 255, 0), 255); CVarSetColor(cvarName, NewColors); CVarSetInteger(Cvar_RBM.c_str(), 0); // On click disable rainbow mode. - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); changed = true; } Tooltip("Chooses a random color\nOverwrites previously chosen color"); @@ -614,7 +614,7 @@ namespace UIWidgets { colors.a = 255.0; CVarSetColor(cvarName, colors); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); changed = true; } } @@ -630,7 +630,7 @@ namespace UIWidgets { colors.a = ColorRGBA.w * 255.0; CVarSetColor(cvarName, colors); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); changed = true; } } diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index 1951e78e1..994505dd6 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -1,11 +1,11 @@ #include "ConfigUpdaters.h" #include "soh/Enhancements/audio/AudioCollection.h" -namespace LUS { +namespace SOH { ConfigVersion1Updater::ConfigVersion1Updater() : ConfigVersionUpdater(1) {} ConfigVersion2Updater::ConfigVersion2Updater() : ConfigVersionUpdater(2) {} - void ConfigVersion1Updater::Update(Config* conf) { + void ConfigVersion1Updater::Update(Ship::Config* conf) { if (conf->GetInt("Window.Width", 640) == 640) { conf->Erase("Window.Width"); } @@ -36,10 +36,10 @@ namespace LUS { if (conf->GetInt("Window.Fullscreen.Height", 1080) == 1080) { conf->Erase("Window.Fullscreen.Height"); } - if (conf->GetInt("Shortcuts.Fullscreen", KbScancode::LUS_KB_F11) == KbScancode::LUS_KB_F10) { + if (conf->GetInt("Shortcuts.Fullscreen", Ship::KbScancode::LUS_KB_F11) == Ship::KbScancode::LUS_KB_F10) { conf->Erase("Shortcuts.Fullscreen"); } - if (conf->GetInt("Shortcuts.Console", KbScancode::LUS_KB_OEM_3) == KbScancode::LUS_KB_OEM_3) { + if (conf->GetInt("Shortcuts.Console", Ship::KbScancode::LUS_KB_OEM_3) == Ship::KbScancode::LUS_KB_OEM_3) { conf->Erase("Shortcuts.Console"); } if (conf->GetString("Game.SaveName", "") == "") { @@ -63,7 +63,7 @@ namespace LUS { CVarClear("gSeededRandomizedEnemies"); } - void ConfigVersion2Updater::Update(Config* conf) { + void ConfigVersion2Updater::Update(Ship::Config* conf) { for (auto seq : AudioCollection::Instance->GetAllSequences()) { CVarClear(std::string("gAudioEditor.ReplacedSequences." + seq.second.sfxKey).c_str()); } diff --git a/soh/soh/config/ConfigUpdaters.h b/soh/soh/config/ConfigUpdaters.h index cc8f6109a..4c9234476 100644 --- a/soh/soh/config/ConfigUpdaters.h +++ b/soh/soh/config/ConfigUpdaters.h @@ -1,15 +1,15 @@ #include "libultraship/libultraship.h" -namespace LUS { - class ConfigVersion1Updater : public ConfigVersionUpdater { +namespace SOH { + class ConfigVersion1Updater : public Ship::ConfigVersionUpdater { public: ConfigVersion1Updater(); - void Update(Config* conf); + void Update(Ship::Config* conf); }; - class ConfigVersion2Updater : public ConfigVersionUpdater { + class ConfigVersion2Updater : public Ship::ConfigVersionUpdater { public: ConfigVersion2Updater(); - void Update(Config* conf); + void Update(Ship::Config* conf); }; } \ No newline at end of file diff --git a/soh/soh/resource/importer/AnimationFactory.cpp b/soh/soh/resource/importer/AnimationFactory.cpp index 8e1aca9b7..13aa71c86 100644 --- a/soh/soh/resource/importer/AnimationFactory.cpp +++ b/soh/soh/resource/importer/AnimationFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto animation = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); AnimationType animType = (AnimationType)reader->ReadUInt32(); animation->type = animType; diff --git a/soh/soh/resource/importer/AnimationFactory.h b/soh/soh/resource/importer/AnimationFactory.h index 36dfceaae..ae27832b6 100644 --- a/soh/soh/resource/importer/AnimationFactory.h +++ b/soh/soh/resource/importer/AnimationFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryAnimationV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryAnimationV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/AudioSampleFactory.cpp b/soh/soh/resource/importer/AudioSampleFactory.cpp index b45e698e5..0ec3f5260 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.cpp +++ b/soh/soh/resource/importer/AudioSampleFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto audioSample = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); audioSample->sample.codec = reader->ReadUByte(); audioSample->sample.medium = reader->ReadUByte(); @@ -71,7 +71,7 @@ extern "C" SoundFontSample* ReadCustomSample(const char* path) { ExtensionEntry entry = ExtensionCache[path]; - auto sampleRaw = LUS::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path); + auto sampleRaw = Ship::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path); uint32_t* strem = (uint32_t*)sampleRaw->Buffer.get(); uint8_t* strem2 = (uint8_t*)strem; diff --git a/soh/soh/resource/importer/AudioSampleFactory.h b/soh/soh/resource/importer/AudioSampleFactory.h index 2680ccdc2..372e8a310 100644 --- a/soh/soh/resource/importer/AudioSampleFactory.h +++ b/soh/soh/resource/importer/AudioSampleFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryAudioSampleV2 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/AudioSequenceFactory.cpp b/soh/soh/resource/importer/AudioSequenceFactory.cpp index ba2a36697..35da7f798 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.cpp +++ b/soh/soh/resource/importer/AudioSequenceFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto audioSequence = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); audioSequence->sequence.seqDataSize = reader->ReadInt32(); audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize); diff --git a/soh/soh/resource/importer/AudioSequenceFactory.h b/soh/soh/resource/importer/AudioSequenceFactory.h index fb4391d61..35fd1ebef 100644 --- a/soh/soh/resource/importer/AudioSequenceFactory.h +++ b/soh/soh/resource/importer/AudioSequenceFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryAudioSequenceV2 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.cpp b/soh/soh/resource/importer/AudioSoundFontFactory.cpp index 6d7efc58c..534a7914c 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.cpp +++ b/soh/soh/resource/importer/AudioSoundFontFactory.cpp @@ -4,13 +4,13 @@ #include "libultraship/libultraship.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto audioSoundFont = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); audioSoundFont->soundFont.fntIndex = reader->ReadInt32(); audioSoundFont->medium = reader->ReadInt8(); @@ -67,7 +67,7 @@ std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResou if (sampleFileName.empty()) { drum.sound.sample = nullptr; } else { - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); drum.sound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } @@ -111,7 +111,7 @@ std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResou bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.lowNotesSound.tuning = reader->ReadFloat(); - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.lowNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.lowNotesSound.sample = nullptr; @@ -123,7 +123,7 @@ std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResou bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.normalNotesSound.tuning = reader->ReadFloat(); - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.normalNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.normalNotesSound.sample = nullptr; @@ -135,7 +135,7 @@ std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResou bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); instrument.highNotesSound.tuning = reader->ReadFloat(); - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); instrument.highNotesSound.sample = static_cast(res ? res->GetRawPointer() : nullptr); } else { instrument.highNotesSound.sample = nullptr; @@ -160,7 +160,7 @@ std::shared_ptr ResourceFactoryBinaryAudioSoundFontV2::ReadResou bool hasSampleRef = reader->ReadInt8(); std::string sampleFileName = reader->ReadString(); soundEffect.tuning = reader->ReadFloat(); - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str()); soundEffect.sample = static_cast(res ? res->GetRawPointer() : nullptr); } diff --git a/soh/soh/resource/importer/AudioSoundFontFactory.h b/soh/soh/resource/importer/AudioSoundFontFactory.h index a63533db9..a80b8fe97 100644 --- a/soh/soh/resource/importer/AudioSoundFontFactory.h +++ b/soh/soh/resource/importer/AudioSoundFontFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryAudioSoundFontV2 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/BackgroundFactory.cpp b/soh/soh/resource/importer/BackgroundFactory.cpp index 07c47cbe9..6be484698 100644 --- a/soh/soh/resource/importer/BackgroundFactory.cpp +++ b/soh/soh/resource/importer/BackgroundFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryBackgroundV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryBackgroundV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto background = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); uint32_t dataSize = reader->ReadUInt32(); diff --git a/soh/soh/resource/importer/BackgroundFactory.h b/soh/soh/resource/importer/BackgroundFactory.h index 787ee509c..e74e897e9 100644 --- a/soh/soh/resource/importer/BackgroundFactory.h +++ b/soh/soh/resource/importer/BackgroundFactory.h @@ -4,8 +4,8 @@ #include "resource/ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryBackgroundV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryBackgroundV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.cpp b/soh/soh/resource/importer/CollisionHeaderFactory.cpp index c5372f249..4636d80c7 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/CollisionHeaderFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryCollisionHeaderV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryCollisionHeaderV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto collisionHeader = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); collisionHeader->collisionHeaderData.minBounds.x = reader->ReadInt16(); collisionHeader->collisionHeaderData.minBounds.y = reader->ReadInt16(); @@ -123,7 +123,7 @@ std::shared_ptr ResourceFactoryBinaryCollisionHeaderV0::ReadReso return collisionHeader; } -std::shared_ptr ResourceFactoryXMLCollisionHeaderV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryXMLCollisionHeaderV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } diff --git a/soh/soh/resource/importer/CollisionHeaderFactory.h b/soh/soh/resource/importer/CollisionHeaderFactory.h index abd878909..dd438f9c3 100644 --- a/soh/soh/resource/importer/CollisionHeaderFactory.h +++ b/soh/soh/resource/importer/CollisionHeaderFactory.h @@ -5,13 +5,13 @@ #include "ResourceFactoryXML.h" namespace SOH { -class ResourceFactoryBinaryCollisionHeaderV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryCollisionHeaderV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class ResourceFactoryXMLCollisionHeaderV0 : public LUS::ResourceFactoryXML { +class ResourceFactoryXMLCollisionHeaderV0 : public Ship::ResourceFactoryXML { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/CutsceneFactory.cpp b/soh/soh/resource/importer/CutsceneFactory.cpp index 28f5e642b..49e44680c 100644 --- a/soh/soh/resource/importer/CutsceneFactory.cpp +++ b/soh/soh/resource/importer/CutsceneFactory.cpp @@ -2,19 +2,19 @@ #include "soh/resource/type/Cutscene.h" #include "spdlog/spdlog.h" -static inline uint32_t read_CMD_BBBB(std::shared_ptr reader) { +static inline uint32_t read_CMD_BBBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); return v; } -static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { +static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half word to match endianness - if (reader->GetEndianness() != LUS::Endianness::Native) { + if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[2]; b[2] = b[3]; @@ -24,12 +24,12 @@ static inline uint32_t read_CMD_BBH(std::shared_ptr reader) { return v; } -static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { +static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half word to match endianness - if (reader->GetEndianness() != LUS::Endianness::Native) { + if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[0]; b[0] = b[1]; @@ -39,12 +39,12 @@ static inline uint32_t read_CMD_HBB(std::shared_ptr reader) { return v; } -static inline uint32_t read_CMD_HH(std::shared_ptr reader) { +static inline uint32_t read_CMD_HH(std::shared_ptr reader) { uint32_t v; reader->Read((char*)&v, sizeof(uint32_t)); // swap the half words to match endianness - if (reader->GetEndianness() != LUS::Endianness::Native) { + if (reader->GetEndianness() != Ship::Endianness::Native) { uint8_t* b = (uint8_t*)&v; uint8_t tmp = b[0]; b[0] = b[1]; @@ -58,13 +58,13 @@ static inline uint32_t read_CMD_HH(std::shared_ptr reader) { } namespace SOH { -std::shared_ptr ResourceFactoryBinaryCutsceneV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryCutsceneV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto cutscene = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); uint32_t numEntries = reader->ReadUInt32(); cutscene->commands.reserve(numEntries); diff --git a/soh/soh/resource/importer/CutsceneFactory.h b/soh/soh/resource/importer/CutsceneFactory.h index 8194615af..8afe98bb8 100644 --- a/soh/soh/resource/importer/CutsceneFactory.h +++ b/soh/soh/resource/importer/CutsceneFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryCutsceneV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryCutsceneV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/PathFactory.cpp b/soh/soh/resource/importer/PathFactory.cpp index 07fc86f40..00807b75a 100644 --- a/soh/soh/resource/importer/PathFactory.cpp +++ b/soh/soh/resource/importer/PathFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryPathV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryPathV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto path = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); path->numPaths = reader->ReadUInt32(); path->paths.reserve(path->numPaths); diff --git a/soh/soh/resource/importer/PathFactory.h b/soh/soh/resource/importer/PathFactory.h index aa8ae747c..ddbee772d 100644 --- a/soh/soh/resource/importer/PathFactory.h +++ b/soh/soh/resource/importer/PathFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryPathV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryPathV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/PlayerAnimationFactory.cpp b/soh/soh/resource/importer/PlayerAnimationFactory.cpp index 4c25d5e80..59610da46 100644 --- a/soh/soh/resource/importer/PlayerAnimationFactory.cpp +++ b/soh/soh/resource/importer/PlayerAnimationFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryPlayerAnimationV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryPlayerAnimationV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto playerAnimation = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); uint32_t numEntries = reader->ReadUInt32(); playerAnimation->limbRotData.reserve(numEntries); diff --git a/soh/soh/resource/importer/PlayerAnimationFactory.h b/soh/soh/resource/importer/PlayerAnimationFactory.h index 8b459a38b..3ee8b1d3a 100644 --- a/soh/soh/resource/importer/PlayerAnimationFactory.h +++ b/soh/soh/resource/importer/PlayerAnimationFactory.h @@ -4,8 +4,8 @@ #include "ResourceFactoryBinary.h" namespace SOH { -class ResourceFactoryBinaryPlayerAnimationV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryPlayerAnimationV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/SceneFactory.cpp b/soh/soh/resource/importer/SceneFactory.cpp index c537cb312..1bcf92e1c 100644 --- a/soh/soh/resource/importer/SceneFactory.cpp +++ b/soh/soh/resource/importer/SceneFactory.cpp @@ -58,7 +58,7 @@ ResourceFactoryBinarySceneV0::ResourceFactoryBinarySceneV0() { sceneCommandFactories[SceneCommandID::SetMesh] = std::make_shared(); } -void ResourceFactoryBinarySceneV0::ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader) { +void ResourceFactoryBinarySceneV0::ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader) { uint32_t commandCount = reader->ReadUInt32(); scene->commands.reserve(commandCount); @@ -68,16 +68,16 @@ void ResourceFactoryBinarySceneV0::ParseSceneCommands(std::shared_ptr sce } std::shared_ptr ResourceFactoryBinarySceneV0::ParseSceneCommand(std::shared_ptr scene, - std::shared_ptr reader, uint32_t index) { + std::shared_ptr reader, uint32_t index) { SceneCommandID cmdID = (SceneCommandID)reader->ReadInt32(); - reader->Seek(-sizeof(int32_t), LUS::SeekOffsetType::Current); + reader->Seek(-sizeof(int32_t), Ship::SeekOffsetType::Current); std::shared_ptr result = nullptr; auto commandFactory = ResourceFactoryBinarySceneV0::sceneCommandFactories[cmdID]; if (commandFactory != nullptr) { - auto initData = std::make_shared(); + auto initData = std::make_shared(); initData->Id = scene->GetInitData()->Id; initData->Type = static_cast(SOH::ResourceType::SOH_SceneCommand); initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index); @@ -93,13 +93,13 @@ std::shared_ptr ResourceFactoryBinarySceneV0::ParseSceneCommand(s return result; } -std::shared_ptr ResourceFactoryBinarySceneV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinarySceneV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto scene = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); ParseSceneCommands(scene, reader); @@ -200,7 +200,7 @@ std::shared_ptr ResourceFactoryXMLSceneV0::ParseSceneCommand(std: auto commandFactory = ResourceFactoryXMLSceneV0::sceneCommandFactories[cmdID]; if (commandFactory != nullptr) { - auto initData = std::make_shared(); + auto initData = std::make_shared(); initData->Id = scene->GetInitData()->Id; initData->Type = static_cast(ResourceType::SOH_SceneCommand); initData->Path = scene->GetInitData()->Path + "/SceneCommand" + std::to_string(index); @@ -216,7 +216,7 @@ std::shared_ptr ResourceFactoryXMLSceneV0::ParseSceneCommand(std: return result; } -std::shared_ptr ResourceFactoryXMLSceneV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryXMLSceneV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } diff --git a/soh/soh/resource/importer/SceneFactory.h b/soh/soh/resource/importer/SceneFactory.h index a1b345f7d..115c3f3f5 100644 --- a/soh/soh/resource/importer/SceneFactory.h +++ b/soh/soh/resource/importer/SceneFactory.h @@ -8,12 +8,12 @@ #include "ResourceFactoryXML.h" namespace SOH { -class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinarySceneV0 : public Ship::ResourceFactoryBinary { public: ResourceFactoryBinarySceneV0(); - std::shared_ptr ReadResource(std::shared_ptr file) override; - void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); + std::shared_ptr ReadResource(std::shared_ptr file) override; + void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); // Doing something very similar to what we do on the ResourceLoader. // Eventually, scene commands should be moved up to the ResourceLoader as well. @@ -21,14 +21,14 @@ class ResourceFactoryBinarySceneV0 : public LUS::ResourceFactoryBinary { // and the exporter does not export the commands with a proper OTR header. static inline std::unordered_map> sceneCommandFactories; protected: - std::shared_ptr ParseSceneCommand(std::shared_ptr scene, std::shared_ptr reader, uint32_t index); + std::shared_ptr ParseSceneCommand(std::shared_ptr scene, std::shared_ptr reader, uint32_t index); }; -class ResourceFactoryXMLSceneV0 : public LUS::ResourceFactoryXML { +class ResourceFactoryXMLSceneV0 : public Ship::ResourceFactoryXML { public: ResourceFactoryXMLSceneV0(); - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; void ParseSceneCommands(std::shared_ptr scene, std::shared_ptr reader); // Doing something very similar to what we do on the ResourceLoader. diff --git a/soh/soh/resource/importer/SkeletonFactory.cpp b/soh/soh/resource/importer/SkeletonFactory.cpp index fedfda400..d4cb965bf 100644 --- a/soh/soh/resource/importer/SkeletonFactory.cpp +++ b/soh/soh/resource/importer/SkeletonFactory.cpp @@ -4,13 +4,13 @@ #include namespace SOH { -std::shared_ptr ResourceFactoryBinarySkeletonV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinarySkeletonV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto skeleton = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); skeleton->type = (SkeletonType)reader->ReadInt8(); skeleton->limbType = (LimbType)reader->ReadInt8(); @@ -43,7 +43,7 @@ std::shared_ptr ResourceFactoryBinarySkeletonV0::ReadResource(st for (size_t i = 0; i < skeleton->limbTable.size(); i++) { std::string limbStr = skeleton->limbTable[i]; - auto limb = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbStr.c_str()); + auto limb = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbStr.c_str()); skeleton->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr); } @@ -62,7 +62,7 @@ std::shared_ptr ResourceFactoryBinarySkeletonV0::ReadResource(st return skeleton; } -std::shared_ptr ResourceFactoryXMLSkeletonV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryXMLSkeletonV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } @@ -112,7 +112,7 @@ std::shared_ptr ResourceFactoryXMLSkeletonV0::ReadResource(std:: std::string limbName = child->Attribute("Path"); skel->limbTable.push_back(limbName); - auto limb = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbName.c_str()); + auto limb = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(limbName.c_str()); skel->skeletonHeaderSegments.push_back(limb ? limb->GetRawPointer() : nullptr); } diff --git a/soh/soh/resource/importer/SkeletonFactory.h b/soh/soh/resource/importer/SkeletonFactory.h index 5de02175f..24f92720a 100644 --- a/soh/soh/resource/importer/SkeletonFactory.h +++ b/soh/soh/resource/importer/SkeletonFactory.h @@ -5,13 +5,13 @@ #include "ResourceFactoryXML.h" namespace SOH { -class ResourceFactoryBinarySkeletonV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinarySkeletonV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class ResourceFactoryXMLSkeletonV0 : public LUS::ResourceFactoryXML { +class ResourceFactoryXMLSkeletonV0 : public Ship::ResourceFactoryXML { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.cpp b/soh/soh/resource/importer/SkeletonLimbFactory.cpp index 15ba92281..3f780e6d4 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.cpp +++ b/soh/soh/resource/importer/SkeletonLimbFactory.cpp @@ -4,13 +4,13 @@ #include "libultraship/libultraship.h" namespace SOH { -std::shared_ptr ResourceFactoryBinarySkeletonLimbV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinarySkeletonLimbV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto skeletonLimb = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); skeletonLimb->limbType = (LimbType)reader->ReadInt8(); skeletonLimb->skinSegmentType = (ZLimbSkinType)reader->ReadInt8(); @@ -184,7 +184,7 @@ std::shared_ptr ResourceFactoryBinarySkeletonLimbV0::ReadResourc return skeletonLimb; } -std::shared_ptr ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.h b/soh/soh/resource/importer/SkeletonLimbFactory.h index 125dde2b8..222cefa2c 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.h +++ b/soh/soh/resource/importer/SkeletonLimbFactory.h @@ -5,13 +5,13 @@ #include "ResourceFactoryXML.h" namespace SOH { -class ResourceFactoryBinarySkeletonLimbV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinarySkeletonLimbV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class ResourceFactoryXMLSkeletonLimbV0 : public LUS::ResourceFactoryXML { +class ResourceFactoryXMLSkeletonLimbV0 : public Ship::ResourceFactoryXML { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/TextFactory.cpp b/soh/soh/resource/importer/TextFactory.cpp index 89d229f80..1da1d50db 100644 --- a/soh/soh/resource/importer/TextFactory.cpp +++ b/soh/soh/resource/importer/TextFactory.cpp @@ -3,13 +3,13 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr ResourceFactoryBinaryTextV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryBinaryTextV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } auto text = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); + auto reader = std::get>(file->Reader); uint32_t msgCount = reader->ReadUInt32(); text->messages.reserve(msgCount); @@ -27,7 +27,7 @@ std::shared_ptr ResourceFactoryBinaryTextV0::ReadResource(std::s return text; } -std::shared_ptr ResourceFactoryXMLTextV0::ReadResource(std::shared_ptr file) { +std::shared_ptr ResourceFactoryXMLTextV0::ReadResource(std::shared_ptr file) { if (!FileHasValidFormatAndReader(file)) { return nullptr; } diff --git a/soh/soh/resource/importer/TextFactory.h b/soh/soh/resource/importer/TextFactory.h index cb466204b..55a569366 100644 --- a/soh/soh/resource/importer/TextFactory.h +++ b/soh/soh/resource/importer/TextFactory.h @@ -5,13 +5,13 @@ #include "ResourceFactoryXML.h" namespace SOH { -class ResourceFactoryBinaryTextV0 : public LUS::ResourceFactoryBinary { +class ResourceFactoryBinaryTextV0 : public Ship::ResourceFactoryBinary { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; -class ResourceFactoryXMLTextV0 : public LUS::ResourceFactoryXML { +class ResourceFactoryXMLTextV0 : public Ship::ResourceFactoryXML { public: - std::shared_ptr ReadResource(std::shared_ptr file) override; + std::shared_ptr ReadResource(std::shared_ptr file) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp index debcf7ab1..6932117f1 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -EndMarkerFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +EndMarkerFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto endMarker = std::make_shared(initData); ReadCommandId(endMarker, reader); @@ -17,7 +17,7 @@ EndMarkerFactory::ReadResource(std::shared_ptr initData, return endMarker; } -std::shared_ptr EndMarkerFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr EndMarkerFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto endMarker = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h index 8e3875ef2..62dfcd7c4 100644 --- a/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h +++ b/soh/soh/resource/importer/scenecommand/EndMarkerFactory.h @@ -5,12 +5,12 @@ namespace SOH { class EndMarkerFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class EndMarkerFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp index 9ab5d1611..8d7de5021 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.cpp @@ -3,7 +3,7 @@ #include "spdlog/spdlog.h" namespace SOH { -void SceneCommandFactoryBinaryV0::ReadCommandId(std::shared_ptr command, std::shared_ptr reader) { +void SceneCommandFactoryBinaryV0::ReadCommandId(std::shared_ptr command, std::shared_ptr reader) { command->cmdId = (SceneCommandID)reader->ReadInt32(); } } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h index 73e5a2e06..601996ea4 100644 --- a/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h +++ b/soh/soh/resource/importer/scenecommand/SceneCommandFactory.h @@ -9,15 +9,15 @@ namespace SOH { class SceneCommandFactoryBinaryV0 { public: - virtual std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) = 0; + virtual std::shared_ptr ReadResource(std::shared_ptr initData, std::shared_ptr reader) = 0; protected: - void ReadCommandId(std::shared_ptr command, std::shared_ptr reader); + void ReadCommandId(std::shared_ptr command, std::shared_ptr reader); }; class SceneCommandFactoryXMLV0 { public: - virtual std::shared_ptr ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) = 0; + virtual std::shared_ptr ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) = 0; protected: void ReadCommandId(std::shared_ptr command, tinyxml2::XMLElement* reader); diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp index cf397fcd3..6c262e7af 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetActorListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetActorListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setActorList = std::make_shared(initData); ReadCommandId(setActorList, reader); @@ -34,7 +34,7 @@ SetActorListFactory::ReadResource(std::shared_ptr initDat return setActorList; } -std::shared_ptr SetActorListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetActorListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setActorList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h index 5dd872f8a..703181c9a 100644 --- a/soh/soh/resource/importer/scenecommand/SetActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetActorListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetActorListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetActorListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp index 40e31f0f2..c04f717c3 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp @@ -5,8 +5,8 @@ #include "libultraship/libultraship.h" namespace SOH { -std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setAlternateHeaders = std::make_shared(initData); ReadCommandId(setAlternateHeaders, reader); @@ -16,7 +16,7 @@ std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::sh for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { auto headerName = reader->ReadString(); if (!headerName.empty()) { - setAlternateHeaders->headers.push_back(std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); } else { setAlternateHeaders->headers.push_back(nullptr); } @@ -29,7 +29,7 @@ std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::sh return setAlternateHeaders; } -std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setAlternateHeaders = std::make_shared(initData); @@ -43,7 +43,7 @@ std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std: for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { auto headerName = std::string(child->Attribute("HeaderName")); if (!headerName.empty()) { - setAlternateHeaders->headers.push_back(std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); } else { setAlternateHeaders->headers.push_back(nullptr); } diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h index 84e730905..7b1324a60 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetAlternateHeadersFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetAlternateHeadersFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp index 521586262..58c6ab4e3 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setCameraSettings = std::make_shared(initData); ReadCommandId(setCameraSettings, reader); @@ -20,7 +20,7 @@ std::shared_ptr SetCameraSettingsFactory::ReadResource(std::shar return setCameraSettings; } -std::shared_ptr SetCameraSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetCameraSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setCameraSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h index a03287b35..a8c21f776 100644 --- a/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCameraSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetCameraSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetCameraSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp index f50ee3790..a67778f63 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.cpp @@ -5,14 +5,14 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setCollisionHeader = std::make_shared(initData); ReadCommandId(setCollisionHeader, reader); setCollisionHeader->fileName = reader->ReadString(); - setCollisionHeader->collisionHeader = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); + setCollisionHeader->collisionHeader = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { LogSetCollisionHeaderAsXML(setCollisionHeader); @@ -21,14 +21,14 @@ std::shared_ptr SetCollisionHeaderFactory::ReadResource(std::sha return setCollisionHeader; } -std::shared_ptr SetCollisionHeaderFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetCollisionHeaderFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setCollisionHeader = std::make_shared(initData); setCollisionHeader->cmdId = SceneCommandID::SetCollisionHeader; setCollisionHeader->fileName = reader->Attribute("FileName"); - setCollisionHeader->collisionHeader = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); + setCollisionHeader->collisionHeader = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCollisionHeader->fileName.c_str())); return setCollisionHeader; } diff --git a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h index 12b872f3c..35902e7cb 100644 --- a/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCollisionHeaderFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetCollisionHeaderFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetCollisionHeaderFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp index 569b8b1d9..7ae8237bf 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetCsCameraFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetCsCameraFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setCsCamera = std::make_shared(initData); ReadCommandId(setCsCamera, reader); @@ -22,7 +22,7 @@ SetCsCameraFactory::ReadResource(std::shared_ptr initData return setCsCamera; } -std::shared_ptr SetCsCameraFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetCsCameraFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setCsCamera = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h index 89c92a699..ad232a11d 100644 --- a/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCsCameraFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetCsCameraFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetCsCameraFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp index 7aea7c70d..7ca657403 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.cpp @@ -5,14 +5,14 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetCutscenesFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetCutscenesFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setCutscenes = std::make_shared(initData); ReadCommandId(setCutscenes, reader); setCutscenes->fileName = reader->ReadString(); - setCutscenes->cutscene = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); + setCutscenes->cutscene = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { LogCutscenesAsXML(setCutscenes); @@ -21,14 +21,14 @@ SetCutscenesFactory::ReadResource(std::shared_ptr initDat return setCutscenes; } -std::shared_ptr SetCutscenesFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetCutscenesFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setCutscenes = std::make_shared(initData); setCutscenes->cmdId = SceneCommandID::SetCutscenes; setCutscenes->fileName = reader->Attribute("FileName"); - setCutscenes->cutscene = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); + setCutscenes->cutscene = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(setCutscenes->fileName.c_str())); return setCutscenes; } diff --git a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h index c78bf621c..4bd76b563 100644 --- a/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetCutscenesFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetCutscenesFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetCutscenesFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp index d4c6e9a50..4038ea825 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetEchoSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetEchoSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setEchoSettings = std::make_shared(initData); ReadCommandId(setEchoSettings, reader); @@ -19,7 +19,7 @@ SetEchoSettingsFactory::ReadResource(std::shared_ptr init return setEchoSettings; } -std::shared_ptr SetEchoSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetEchoSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setEchoSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h index 4be1fe399..c76885cf9 100644 --- a/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEchoSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetEchoSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetEchoSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp index f3817c39c..0590bfeb7 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetEntranceListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetEntranceListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setEntranceList = std::make_shared(initData); ReadCommandId(setEntranceList, reader); @@ -28,7 +28,7 @@ SetEntranceListFactory::ReadResource(std::shared_ptr init return setEntranceList; } -std::shared_ptr SetEntranceListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetEntranceListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setEntranceList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h index a5349cf83..207e9f050 100644 --- a/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetEntranceListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetEntranceListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetEntranceListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp index b6078199b..328b41d8a 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetExitListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetExitListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setExitList = std::make_shared( initData); ReadCommandId(setExitList, reader); @@ -23,7 +23,7 @@ SetExitListFactory::ReadResource(std::shared_ptr initData return setExitList; } -std::shared_ptr SetExitListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetExitListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setExitList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h index fc47b88d0..4b050f46f 100644 --- a/soh/soh/resource/importer/scenecommand/SetExitListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetExitListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetExitListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetExitListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp index af7f1bb3c..e1cbd2122 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetLightListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetLightListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setLightList = std::make_shared(initData); ReadCommandId(setLightList, reader); @@ -38,7 +38,7 @@ SetLightListFactory::ReadResource(std::shared_ptr initDat return setLightList; } -std::shared_ptr SetLightListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetLightListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setLightList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h index aae5c8e4a..0af868d17 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetLightListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetLightListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp index 573998cfa..7e35a7ac0 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetLightingSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetLightingSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setLightingSettings = std::make_shared(initData); ReadCommandId(setLightingSettings, reader); @@ -51,7 +51,7 @@ std::shared_ptr SetLightingSettingsFactory::ReadResource(std::sh return setLightingSettings; } -std::shared_ptr SetLightingSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetLightingSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setLightingSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h index 39ae6934d..d5b3be279 100644 --- a/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetLightingSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetLightingSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetLightingSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp index 8c4109c5a..bdc5a0106 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.cpp @@ -5,8 +5,8 @@ #include "libultraship/libultraship.h" namespace SOH { -std::shared_ptr -SetMeshFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetMeshFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setMesh = std::make_shared(initData); ReadCommandId(setMesh, reader); @@ -41,8 +41,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -56,8 +56,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st std::string imgOpa = reader->ReadString(); std::string imgXlu = reader->ReadString(); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); + auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); + auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -104,8 +104,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -124,8 +124,8 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st std::string meshOpa = reader->ReadString(); std::string meshXlu = reader->ReadString(); - auto opaRes = meshOpa != "" ? LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()) : nullptr; - auto xluRes = meshXlu != "" ? LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()) : nullptr; + auto opaRes = meshOpa != "" ? Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()) : nullptr; + auto xluRes = meshXlu != "" ? Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()) : nullptr; dlist.opa = (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr); dlist.xlu = (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr); @@ -155,7 +155,7 @@ SetMeshFactory::ReadResource(std::shared_ptr initData, st return setMesh; } -std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setMesh = std::make_shared(initData); @@ -199,8 +199,8 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr< std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -214,8 +214,8 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr< std::string imgOpa = child->Attribute("ImgOpa"); std::string imgXlu = child->Attribute("ImgXlu"); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); + auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgOpa.c_str()); + auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(imgXlu.c_str()); pType.opa = imgOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; pType.xlu = imgXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -271,8 +271,8 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr< std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); - opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); pType.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; pType.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; @@ -291,8 +291,8 @@ std::shared_ptr SetMeshFactoryXML::ReadResource(std::shared_ptr< std::string meshOpa = child->Attribute("MeshOpa"); std::string meshXlu = child->Attribute("MeshXlu"); - auto opaRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); - auto xluRes = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); + auto opaRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshOpa.c_str()); + auto xluRes = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(meshXlu.c_str()); dlist.opa = meshOpa != "" ? (Gfx*)(opaRes ? opaRes->GetRawPointer() : nullptr) : 0; dlist.xlu = meshXlu != "" ? (Gfx*)(xluRes ? xluRes->GetRawPointer() : nullptr) : 0; diff --git a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h index f64b55d72..c87123174 100644 --- a/soh/soh/resource/importer/scenecommand/SetMeshFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetMeshFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetMeshFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetMeshFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp index 1d64a9aec..0ba356f7b 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetObjectListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetObjectListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setObjectList = std::make_shared(initData); ReadCommandId(setObjectList, reader); @@ -23,7 +23,7 @@ SetObjectListFactory::ReadResource(std::shared_ptr initDa return setObjectList; } -std::shared_ptr SetObjectListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetObjectListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setObjectList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h index 094c30a92..663ef2304 100644 --- a/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetObjectListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetObjectListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetObjectListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp index 0e26e96e4..65af2e0de 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp @@ -5,8 +5,8 @@ #include namespace SOH { -std::shared_ptr -SetPathwaysFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetPathwaysFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setPathways = std::make_shared(initData); ReadCommandId(setPathways, reader); @@ -15,7 +15,7 @@ SetPathwaysFactory::ReadResource(std::shared_ptr initData setPathways->paths.reserve(setPathways->numPaths); for (uint32_t i = 0; i < setPathways->numPaths; i++) { std::string pathFileName = reader->ReadString(); - auto path = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); + auto path = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); setPathways->paths.push_back(path->GetPointer()); } @@ -26,7 +26,7 @@ SetPathwaysFactory::ReadResource(std::shared_ptr initData return setPathways; } -std::shared_ptr SetPathwaysFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetPathwaysFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setPathways = std::make_shared(initData); @@ -38,7 +38,7 @@ std::shared_ptr SetPathwaysFactoryXML::ReadResource(std::shared_ std::string childName = child->Name(); if (childName == "Pathway") { std::string pathFileName = child->Attribute("FilePath"); - auto path = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); + auto path = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); setPathways->paths.push_back(path->GetPointer()); setPathways->pathFileNames.push_back(pathFileName); } diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h index 2e334c7a5..783c9f45c 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetPathwaysFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetPathwaysFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp index 25a3bf931..14bb787ed 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetRoomBehaviorFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetRoomBehaviorFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setRoomBehavior = std::make_shared(initData); ReadCommandId(setRoomBehavior, reader); @@ -20,7 +20,7 @@ SetRoomBehaviorFactory::ReadResource(std::shared_ptr init return setRoomBehavior; } -std::shared_ptr SetRoomBehaviorFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetRoomBehaviorFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setRoomBehavior = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h index 97c5c7bb4..87e55194d 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomBehaviorFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetRoomBehaviorFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetRoomBehaviorFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp index 67c3afd0f..b19ac98d7 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetRoomListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetRoomListFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setRoomList = std::make_shared(initData); ReadCommandId(setRoomList, reader); @@ -31,7 +31,7 @@ SetRoomListFactory::ReadResource(std::shared_ptr initData return setRoomList; } -std::shared_ptr SetRoomListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetRoomListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setRoomList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h index c6e82dfa9..1e05c7e03 100644 --- a/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetRoomListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetRoomListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetRoomListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp index 9147989dd..6c0ee1400 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setSkyboxModifier = std::make_shared(initData); ReadCommandId(setSkyboxModifier, reader); @@ -20,7 +20,7 @@ std::shared_ptr SetSkyboxModifierFactory::ReadResource(std::shar return setSkyboxModifier; } -std::shared_ptr SetSkyboxModifierFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetSkyboxModifierFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setSkyboxModifier = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h index cbd260ecc..a4ef58150 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxModifierFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetSkyboxModifierFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetSkyboxModifierFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp index 7f9f4d3d0..607909d65 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setSkyboxSettings = std::make_shared(initData); ReadCommandId(setSkyboxSettings, reader); @@ -22,7 +22,7 @@ std::shared_ptr SetSkyboxSettingsFactory::ReadResource(std::shar return setSkyboxSettings; } -std::shared_ptr SetSkyboxSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetSkyboxSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setSkyboxSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h index 6bc668667..352275b58 100644 --- a/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSkyboxSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetSkyboxSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetSkyboxSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp index 46d81c074..61c1892dd 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetSoundSettingsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetSoundSettingsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setSoundSettings = std::make_shared(initData); ReadCommandId(setSoundSettings, reader); @@ -21,7 +21,7 @@ std::shared_ptr SetSoundSettingsFactory::ReadResource(std::share return setSoundSettings; } -std::shared_ptr SetSoundSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetSoundSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setSoundSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h index fa6f0ac2f..14d1ebe84 100644 --- a/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSoundSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetSoundSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetSoundSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp index b90aa9c9d..f28393134 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setSpecialObjects = std::make_shared(initData); ReadCommandId(setSpecialObjects, reader); @@ -20,7 +20,7 @@ std::shared_ptr SetSpecialObjectsFactory::ReadResource(std::shar return setSpecialObjects; } -std::shared_ptr SetSpecialObjectsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetSpecialObjectsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setSpecialObjects = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h index 47b30bafc..38b1ea511 100644 --- a/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetSpecialObjectsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetSpecialObjectsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetSpecialObjectsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp index abfa6f807..3dee5d992 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetStartPositionListFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetStartPositionListFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setStartPositionList = std::make_shared(initData); ReadCommandId(setStartPositionList, reader); @@ -34,7 +34,7 @@ std::shared_ptr SetStartPositionListFactory::ReadResource(std::s return setStartPositionList; } -std::shared_ptr SetStartPositionListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetStartPositionListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setStartPositionList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h index 4e381036a..b4894207e 100644 --- a/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetStartPositionListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetStartPositionListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetStartPositionListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp index 8e54e4573..739da5330 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetTimeSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetTimeSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setTimeSettings = std::make_shared(initData); ReadCommandId(setTimeSettings, reader); @@ -21,7 +21,7 @@ SetTimeSettingsFactory::ReadResource(std::shared_ptr init return setTimeSettings; } -std::shared_ptr SetTimeSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetTimeSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setTimeSettings = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h index ff3fdda37..4b7b5c90f 100644 --- a/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTimeSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetTimeSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetTimeSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp index 5bf1a114d..4289ef46e 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr SetTransitionActorListFactory::ReadResource(std::shared_ptr initData, - std::shared_ptr reader) { +std::shared_ptr SetTransitionActorListFactory::ReadResource(std::shared_ptr initData, + std::shared_ptr reader) { auto setTransitionActorList = std::make_shared(initData); ReadCommandId(setTransitionActorList, reader); @@ -36,7 +36,7 @@ std::shared_ptr SetTransitionActorListFactory::ReadResource(std: return setTransitionActorList; } -std::shared_ptr SetTransitionActorListFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetTransitionActorListFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setTransitionActorList = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h index eaeb2b5ec..a3fc42f41 100644 --- a/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetTransitionActorListFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetTransitionActorListFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetTransitionActorListFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp index 77991b12c..587e9dcc7 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.cpp @@ -4,8 +4,8 @@ #include "spdlog/spdlog.h" namespace SOH { -std::shared_ptr -SetWindSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { +std::shared_ptr +SetWindSettingsFactory::ReadResource(std::shared_ptr initData, std::shared_ptr reader) { auto setWind = std::make_shared(initData); ReadCommandId(setWind, reader); @@ -22,7 +22,7 @@ SetWindSettingsFactory::ReadResource(std::shared_ptr init return setWind; } -std::shared_ptr SetWindSettingsFactoryXML::ReadResource(std::shared_ptr initData, +std::shared_ptr SetWindSettingsFactoryXML::ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) { auto setWind = std::make_shared(initData); diff --git a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h index bab55dbd9..85381e517 100644 --- a/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h +++ b/soh/soh/resource/importer/scenecommand/SetWindSettingsFactory.h @@ -5,13 +5,13 @@ namespace SOH { class SetWindSettingsFactory : public SceneCommandFactoryBinaryV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, std::shared_ptr reader) override; }; class SetWindSettingsFactoryXML : public SceneCommandFactoryXMLV0 { public: - std::shared_ptr - ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; + std::shared_ptr + ReadResource(std::shared_ptr initData, tinyxml2::XMLElement* reader) override; }; } // namespace SOH diff --git a/soh/soh/resource/logging/SceneCommandLoggers.cpp b/soh/soh/resource/logging/SceneCommandLoggers.cpp index b1eeb554d..7c55bcaf0 100644 --- a/soh/soh/resource/logging/SceneCommandLoggers.cpp +++ b/soh/soh/resource/logging/SceneCommandLoggers.cpp @@ -27,7 +27,7 @@ namespace SOH { -void LogEndMarkerAsXML(std::shared_ptr resource) { +void LogEndMarkerAsXML(std::shared_ptr resource) { std::shared_ptr endMarker = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -40,7 +40,7 @@ void LogEndMarkerAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogActorListAsXML(std::shared_ptr resource) { +void LogActorListAsXML(std::shared_ptr resource) { std::shared_ptr setActorList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -66,7 +66,7 @@ void LogActorListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogAlternateHeadersAsXML(std::shared_ptr resource) { +void LogAlternateHeadersAsXML(std::shared_ptr resource) { std::shared_ptr setAlternateHeaders = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -79,7 +79,7 @@ void LogAlternateHeadersAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogCameraSettingsAsXML(std::shared_ptr resource) { +void LogCameraSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setCameraSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -95,7 +95,7 @@ void LogCameraSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogSetCollisionHeaderAsXML(std::shared_ptr resource) { +void LogSetCollisionHeaderAsXML(std::shared_ptr resource) { std::shared_ptr setCollisionHeader = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -110,7 +110,7 @@ void LogSetCollisionHeaderAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogCsCameraAsXML(std::shared_ptr resource) { +void LogCsCameraAsXML(std::shared_ptr resource) { std::shared_ptr setCsCamera = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -123,7 +123,7 @@ void LogCsCameraAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogCutscenesAsXML(std::shared_ptr resource) { +void LogCutscenesAsXML(std::shared_ptr resource) { std::shared_ptr setCutscenes = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -138,7 +138,7 @@ void LogCutscenesAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogEchoSettingsAsXML(std::shared_ptr resource) { +void LogEchoSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setEchoSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -153,7 +153,7 @@ void LogEchoSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogEntranceListAsXML(std::shared_ptr resource) { +void LogEntranceListAsXML(std::shared_ptr resource) { std::shared_ptr setEntranceList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -173,7 +173,7 @@ void LogEntranceListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogExitListAsXML(std::shared_ptr resource) { +void LogExitListAsXML(std::shared_ptr resource) { std::shared_ptr setExitList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -192,7 +192,7 @@ void LogExitListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogLightingSettingsAsXML(std::shared_ptr resource) { +void LogLightingSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setLightingSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -234,7 +234,7 @@ void LogLightingSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogLightListAsXML(std::shared_ptr resource) { +void LogLightListAsXML(std::shared_ptr resource) { std::shared_ptr setLightList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -270,7 +270,7 @@ void LogLightListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogMeshAsXML(std::shared_ptr resource) { +void LogMeshAsXML(std::shared_ptr resource) { std::shared_ptr setMesh = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -371,7 +371,7 @@ void LogMeshAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogObjectListAsXML(std::shared_ptr resource) { +void LogObjectListAsXML(std::shared_ptr resource) { std::shared_ptr setObjectList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -390,7 +390,7 @@ void LogObjectListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogPathwaysAsXML(std::shared_ptr resource) { +void LogPathwaysAsXML(std::shared_ptr resource) { std::shared_ptr setPathways = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -409,7 +409,7 @@ void LogPathwaysAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogRoomBehaviorAsXML(std::shared_ptr resource) { +void LogRoomBehaviorAsXML(std::shared_ptr resource) { std::shared_ptr setRoomBehavior = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -425,7 +425,7 @@ void LogRoomBehaviorAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogRoomListAsXML(std::shared_ptr resource) { +void LogRoomListAsXML(std::shared_ptr resource) { std::shared_ptr setRoomList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -444,7 +444,7 @@ void LogRoomListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogSkyboxModifierAsXML(std::shared_ptr resource) { +void LogSkyboxModifierAsXML(std::shared_ptr resource) { std::shared_ptr setSkyboxModifier = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -460,7 +460,7 @@ void LogSkyboxModifierAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogSkyboxSettingsAsXML(std::shared_ptr resource) { +void LogSkyboxSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setSkyboxSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -478,7 +478,7 @@ void LogSkyboxSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogSoundSettingsAsXML(std::shared_ptr resource) { +void LogSoundSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setSoundSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -495,7 +495,7 @@ void LogSoundSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogSpecialObjectsAsXML(std::shared_ptr resource) { +void LogSpecialObjectsAsXML(std::shared_ptr resource) { std::shared_ptr setSpecialObjects = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -511,7 +511,7 @@ void LogSpecialObjectsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogStartPositionListAsXML(std::shared_ptr resource) { +void LogStartPositionListAsXML(std::shared_ptr resource) { std::shared_ptr setStartPositionList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -537,7 +537,7 @@ void LogStartPositionListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogTimeSettingsAsXML(std::shared_ptr resource) { +void LogTimeSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setTimeSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -554,7 +554,7 @@ void LogTimeSettingsAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogTransitionActorListAsXML(std::shared_ptr resource) { +void LogTransitionActorListAsXML(std::shared_ptr resource) { std::shared_ptr setTransitionActorList = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; @@ -582,7 +582,7 @@ void LogTransitionActorListAsXML(std::shared_ptr resource) { SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); } -void LogWindSettingsAsXML(std::shared_ptr resource) { +void LogWindSettingsAsXML(std::shared_ptr resource) { std::shared_ptr setWindSettings = std::static_pointer_cast(resource); tinyxml2::XMLDocument doc; diff --git a/soh/soh/resource/logging/SceneCommandLoggers.h b/soh/soh/resource/logging/SceneCommandLoggers.h index 1351a5c77..f952ac766 100644 --- a/soh/soh/resource/logging/SceneCommandLoggers.h +++ b/soh/soh/resource/logging/SceneCommandLoggers.h @@ -3,30 +3,30 @@ namespace SOH { -void LogEndMarkerAsXML(std::shared_ptr resource); -void LogActorListAsXML(std::shared_ptr resource); -void LogAlternateHeadersAsXML(std::shared_ptr resource); -void LogCameraSettingsAsXML(std::shared_ptr resource); -void LogSetCollisionHeaderAsXML(std::shared_ptr resource); -void LogCsCameraAsXML(std::shared_ptr resource); -void LogCutscenesAsXML(std::shared_ptr resource); -void LogEchoSettingsAsXML(std::shared_ptr resource); -void LogEntranceListAsXML(std::shared_ptr resource); -void LogExitListAsXML(std::shared_ptr resource); -void LogLightingSettingsAsXML(std::shared_ptr resource); -void LogLightListAsXML(std::shared_ptr resource); -void LogMeshAsXML(std::shared_ptr resource); -void LogObjectListAsXML(std::shared_ptr resource); -void LogPathwaysAsXML(std::shared_ptr resource); -void LogRoomBehaviorAsXML(std::shared_ptr resource); -void LogRoomListAsXML(std::shared_ptr resource); -void LogSkyboxModifierAsXML(std::shared_ptr resource); -void LogSkyboxSettingsAsXML(std::shared_ptr resource); -void LogSoundSettingsAsXML(std::shared_ptr resource); -void LogSpecialObjectsAsXML(std::shared_ptr resource); -void LogStartPositionListAsXML(std::shared_ptr resource); -void LogTimeSettingsAsXML(std::shared_ptr resource); -void LogTransitionActorListAsXML(std::shared_ptr resource); -void LogWindSettingsAsXML(std::shared_ptr resource); +void LogEndMarkerAsXML(std::shared_ptr resource); +void LogActorListAsXML(std::shared_ptr resource); +void LogAlternateHeadersAsXML(std::shared_ptr resource); +void LogCameraSettingsAsXML(std::shared_ptr resource); +void LogSetCollisionHeaderAsXML(std::shared_ptr resource); +void LogCsCameraAsXML(std::shared_ptr resource); +void LogCutscenesAsXML(std::shared_ptr resource); +void LogEchoSettingsAsXML(std::shared_ptr resource); +void LogEntranceListAsXML(std::shared_ptr resource); +void LogExitListAsXML(std::shared_ptr resource); +void LogLightingSettingsAsXML(std::shared_ptr resource); +void LogLightListAsXML(std::shared_ptr resource); +void LogMeshAsXML(std::shared_ptr resource); +void LogObjectListAsXML(std::shared_ptr resource); +void LogPathwaysAsXML(std::shared_ptr resource); +void LogRoomBehaviorAsXML(std::shared_ptr resource); +void LogRoomListAsXML(std::shared_ptr resource); +void LogSkyboxModifierAsXML(std::shared_ptr resource); +void LogSkyboxSettingsAsXML(std::shared_ptr resource); +void LogSoundSettingsAsXML(std::shared_ptr resource); +void LogSpecialObjectsAsXML(std::shared_ptr resource); +void LogStartPositionListAsXML(std::shared_ptr resource); +void LogTimeSettingsAsXML(std::shared_ptr resource); +void LogTransitionActorListAsXML(std::shared_ptr resource); +void LogWindSettingsAsXML(std::shared_ptr resource); } //namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/Animation.h b/soh/soh/resource/type/Animation.h index abd319d97..bf2497107 100644 --- a/soh/soh/resource/type/Animation.h +++ b/soh/soh/resource/type/Animation.h @@ -63,11 +63,11 @@ LinkAnimationHeader linkAnimationHeader; TransformUpdateIndex transformUpdateIndex; }; -class Animation : public LUS::Resource { +class Animation : public Ship::Resource { public: using Resource::Resource; - Animation() : Resource(std::shared_ptr()) {} + Animation() : Resource(std::shared_ptr()) {} AnimationData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/AudioSample.h b/soh/soh/resource/type/AudioSample.h index 4d6929c59..f37659091 100644 --- a/soh/soh/resource/type/AudioSample.h +++ b/soh/soh/resource/type/AudioSample.h @@ -39,11 +39,11 @@ namespace SOH { s32 sampleRate; // For wav samples only... } Sample; // size = 0x10 - class AudioSample : public LUS::Resource { + class AudioSample : public Ship::Resource { public: using Resource::Resource; - AudioSample() : Resource(std::shared_ptr()) {} + AudioSample() : Resource(std::shared_ptr()) {} Sample* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/AudioSequence.h b/soh/soh/resource/type/AudioSequence.h index 457db6243..d7a8820a3 100644 --- a/soh/soh/resource/type/AudioSequence.h +++ b/soh/soh/resource/type/AudioSequence.h @@ -17,11 +17,11 @@ typedef struct { uint8_t fonts[16]; } Sequence; -class AudioSequence : public LUS::Resource { +class AudioSequence : public Ship::Resource { public: using Resource::Resource; - AudioSequence() : Resource(std::shared_ptr()) {} + AudioSequence() : Resource(std::shared_ptr()) {} Sequence* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/AudioSoundFont.h b/soh/soh/resource/type/AudioSoundFont.h index 11b899d3e..12d66b2d2 100644 --- a/soh/soh/resource/type/AudioSoundFont.h +++ b/soh/soh/resource/type/AudioSoundFont.h @@ -52,11 +52,11 @@ typedef struct { s32 fntIndex; } SoundFont; // size = 0x14 -class AudioSoundFont : public LUS::Resource { +class AudioSoundFont : public Ship::Resource { public: using Resource::Resource; - AudioSoundFont() : Resource(std::shared_ptr()) {} + AudioSoundFont() : Resource(std::shared_ptr()) {} SoundFont* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Background.h b/soh/soh/resource/type/Background.h index 9edc4b0d6..aa81edde4 100644 --- a/soh/soh/resource/type/Background.h +++ b/soh/soh/resource/type/Background.h @@ -3,11 +3,11 @@ #include "resource/Resource.h" namespace SOH { -class Background : public LUS::Resource { +class Background : public Ship::Resource { public: using Resource::Resource; - Background() : Resource(std::shared_ptr()) {} + Background() : Resource(std::shared_ptr()) {} uint8_t* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/CollisionHeader.h b/soh/soh/resource/type/CollisionHeader.h index e2ddf3f7a..dba5994ce 100644 --- a/soh/soh/resource/type/CollisionHeader.h +++ b/soh/soh/resource/type/CollisionHeader.h @@ -67,11 +67,11 @@ typedef struct { size_t cameraDataListLen; // OTRTODO: Added to allow for bounds checking the cameraDataList. } CollisionHeaderData; // original name: BGDataInfo -class CollisionHeader : public LUS::Resource { +class CollisionHeader : public Ship::Resource { public: using Resource::Resource; - CollisionHeader() : Resource(std::shared_ptr()) {} + CollisionHeader() : Resource(std::shared_ptr()) {} CollisionHeaderData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Cutscene.h b/soh/soh/resource/type/Cutscene.h index c4d5fb0d5..664413d2d 100644 --- a/soh/soh/resource/type/Cutscene.h +++ b/soh/soh/resource/type/Cutscene.h @@ -41,11 +41,11 @@ enum class CutsceneCommands { Error = 0xFEAF, }; -class Cutscene : public LUS::Resource { +class Cutscene : public Ship::Resource { public: using Resource::Resource; - Cutscene() : Resource(std::shared_ptr()) {} + Cutscene() : Resource(std::shared_ptr()) {} uint32_t* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Path.h b/soh/soh/resource/type/Path.h index c4078bed3..5adf683d3 100644 --- a/soh/soh/resource/type/Path.h +++ b/soh/soh/resource/type/Path.h @@ -13,11 +13,11 @@ typedef struct { /* 0x04 */ Vec3s* points; // Segment Address to the array of points } PathData; // size = 0x8 -class Path : public LUS::Resource { +class Path : public Ship::Resource { public: using Resource::Resource; - Path() : Resource(std::shared_ptr()) {} + Path() : Resource(std::shared_ptr()) {} PathData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/PlayerAnimation.h b/soh/soh/resource/type/PlayerAnimation.h index 416b3928c..e44d30b1b 100644 --- a/soh/soh/resource/type/PlayerAnimation.h +++ b/soh/soh/resource/type/PlayerAnimation.h @@ -5,11 +5,11 @@ #include "Resource.h" namespace SOH { -class PlayerAnimation : public LUS::Resource { +class PlayerAnimation : public Ship::Resource { public: using Resource::Resource; - PlayerAnimation() : Resource(std::shared_ptr()) {} + PlayerAnimation() : Resource(std::shared_ptr()) {} int16_t* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Scene.h b/soh/soh/resource/type/Scene.h index 79ff69392..722c51845 100644 --- a/soh/soh/resource/type/Scene.h +++ b/soh/soh/resource/type/Scene.h @@ -9,11 +9,11 @@ namespace SOH { -class Scene : public LUS::Resource { +class Scene : public Ship::Resource { public: using Resource::Resource; - Scene() : Resource(std::shared_ptr()) {} + Scene() : Resource(std::shared_ptr()) {} void* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 39c28f533..8abce78db 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -36,9 +36,9 @@ void SkeletonPatcher::RegisterSkeleton(std::string& path, SkelAnime* skelAnime) } // Determine if we're using an alternate skeleton - if (path.starts_with(LUS::IResource::gAltAssetPrefix)) { - info.vanillaSkeletonPath = path.substr(LUS::IResource::gAltAssetPrefix.length(), - path.size() - LUS::IResource::gAltAssetPrefix.length()); + if (path.starts_with(Ship::IResource::gAltAssetPrefix)) { + info.vanillaSkeletonPath = path.substr(Ship::IResource::gAltAssetPrefix.length(), + path.size() - Ship::IResource::gAltAssetPrefix.length()); } else { info.vanillaSkeletonPath = path; } @@ -68,8 +68,8 @@ void SkeletonPatcher::UpdateSkeletons() { bool isHD = CVarGetInteger("gAltAssets", 0); for (auto skel : skeletons) { Skeleton* newSkel = - (Skeleton*)LUS::Context::GetInstance()->GetResourceManager() - ->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) + (Skeleton*)Ship::Context::GetInstance()->GetResourceManager() + ->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) .get(); if (newSkel != nullptr) { diff --git a/soh/soh/resource/type/Skeleton.h b/soh/soh/resource/type/Skeleton.h index 81aa90c68..72d81c5a5 100644 --- a/soh/soh/resource/type/Skeleton.h +++ b/soh/soh/resource/type/Skeleton.h @@ -50,11 +50,11 @@ union SkeletonData { SkelCurveLimbList skelCurveLimbList; }; -class Skeleton : public LUS::Resource { +class Skeleton : public Ship::Resource { public: using Resource::Resource; - Skeleton() : Resource(std::shared_ptr()) {} + Skeleton() : Resource(std::shared_ptr()) {} SkeletonData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/SkeletonLimb.h b/soh/soh/resource/type/SkeletonLimb.h index bae04092c..04b815f05 100644 --- a/soh/soh/resource/type/SkeletonLimb.h +++ b/soh/soh/resource/type/SkeletonLimb.h @@ -97,11 +97,11 @@ union SkeletonLimbData { SkinLimb skinLimb; }; -class SkeletonLimb : public LUS::Resource { +class SkeletonLimb : public Ship::Resource { public: using Resource::Resource; - SkeletonLimb() : Resource(std::shared_ptr()) {} + SkeletonLimb() : Resource(std::shared_ptr()) {} SkeletonLimbData* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/Text.h b/soh/soh/resource/type/Text.h index 03cf7340b..1ad8c9663 100644 --- a/soh/soh/resource/type/Text.h +++ b/soh/soh/resource/type/Text.h @@ -16,11 +16,11 @@ public: std::string msg; }; -class Text : public LUS::Resource { +class Text : public Ship::Resource { public: using Resource::Resource; - Text() : Resource(std::shared_ptr()) {} + Text() : Resource(std::shared_ptr()) {} MessageEntry* GetPointer(); size_t GetPointerSize(); diff --git a/soh/soh/resource/type/scenecommand/SceneCommand.h b/soh/soh/resource/type/scenecommand/SceneCommand.h index 5eb44ae9d..04216e09b 100644 --- a/soh/soh/resource/type/scenecommand/SceneCommand.h +++ b/soh/soh/resource/type/scenecommand/SceneCommand.h @@ -47,10 +47,10 @@ enum class SceneCommandID : uint8_t { Error = 0xFF }; -class ISceneCommand : public LUS::IResource { +class ISceneCommand : public Ship::IResource { public: using IResource::IResource; - ISceneCommand() : IResource(std::shared_ptr()) {} + ISceneCommand() : IResource(std::shared_ptr()) {} SceneCommandID cmdId; }; diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 05432fc53..49e1e91c4 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -23,10 +23,10 @@ static void SetMessageEntry(MessageTableEntry& entry, const SOH::MessageEntry& m } static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEntry*& table, size_t tableSize) { - auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(folderPath).get(); + auto lst = *Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(folderPath).get(); for (auto& tPath : lst) { - auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); + auto file = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(tPath)); for (size_t j = 0; j < file->messages.size(); ++j) { // Check if same text ID exists already @@ -43,7 +43,7 @@ static void OTRMessage_LoadCustom(const std::string& folderPath, MessageTableEnt } MessageTableEntry* OTRMessage_LoadTable(const std::string& filePath, bool isNES) { - auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); + auto file = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); if (file == nullptr) return nullptr; @@ -120,7 +120,7 @@ extern "C" void OTRMessage_Init() if (sStaffMessageEntryTablePtr == NULL) { auto file2 = - std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource( + std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResource( "text/staff_message_data_static/staff_message_data_static")); // OTRTODO: Should not be malloc'ing here. It's fine for now since we check that the message table is already null. sStaffMessageEntryTablePtr = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file2->messages.size()); diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 522a24eb8..ff485664d 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -13,9 +13,9 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn); s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene); //LUS::OTRResource* OTRPlay_LoadFile(PlayState* play, RomFile* file) { -LUS::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName) +Ship::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName) { - auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResource(fileName); + auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(fileName); return res.get(); } @@ -81,7 +81,7 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn) { if (IS_BOSS_RUSH && play->sceneNum != SCENE_CHAMBER_OF_THE_SAGES) { gSaveContext.isBossRushPaused = 0; } - /* auto data = static_cast(LUS::Context::GetInstance() + /* auto data = static_cast(Ship::Context::GetInstance() ->GetResourceManager() ->ResourceLoad("object_link_child\\object_link_childVtx_01FE08") .get()); diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 0b9ba98f9..6c5ba67df 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -34,13 +34,13 @@ #include "soh/resource/type/scenecommand/SetEchoSettings.h" #include "soh/resource/type/scenecommand/SetAlternateHeaders.h" -extern LUS::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName); +extern Ship::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName); extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); extern "C" RomFile sNaviMsgFiles[]; s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene); // Forward Declaration of function declared in OTRGlobals.cpp -std::shared_ptr GetResourceByNameHandlingMQ(const char* path); +std::shared_ptr GetResourceByNameHandlingMQ(const char* path); bool Scene_CommandSpawnList(PlayState* play, SOH::ISceneCommand* cmd) { // SOH::SetStartPositionList* cmdStartPos = std::static_pointer_cast(cmd); From d69814ed95238cd76aba208a9e321adbe5926350 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:41:33 +0100 Subject: [PATCH 198/300] Real time Hint Assembly, Hint object refactor, and expansion of CustomMessage (#4078) * Hint text refactor WIP DOES NOT BUILD * Update to show people DOES NOT BUILD * stuck on wierd errors * forgot to add * expression error does not name a type * commit in case anyone looks * static assertion failed: T must be an integral type or an enum. * fail without error, complaining about unrefernced things * fix some issues, still linker bs * restructure some trials, conditionalAlwaysHints and hint_list stuff * builds and does not crash, but there's text issues * fix text issues * commit to push, halfway through trimming down log * finish trimming spoiler logging * post merge clean up * plando mode seems to work, looking into song text wierdness * push for debugging crash on HBA sign * fix num and anju issues * fix the damn sign * Fix Windows build Renames GetMessage to GetHintMessage (a different name could be chosen, but GetMessage conflicts with a macro in winuser.h) Changes uint to size_t, uint does not seem to exist on Windows. * fix biggoron * remove some manual formatting that autoformat doesn't like * fix some altar text * fix more altar text * last cleanup --------- Co-authored-by: Christopher Leggett --- .../custom-message/CustomMessageManager.cpp | 478 +- .../custom-message/CustomMessageManager.h | 120 +- .../custom-message/CustomMessageTypes.h | 1 + .../Enhancements/debugger/MessageViewer.cpp | 11 +- soh/soh/Enhancements/mods.cpp | 4 +- soh/soh/Enhancements/presets.h | 3 +- .../randomizer/3drando/custom_messages.cpp | 6 +- .../randomizer/3drando/custom_messages.hpp | 11 +- .../Enhancements/randomizer/3drando/fill.cpp | 8 - .../randomizer/3drando/hint_list.cpp | 5977 ++++++++--------- .../randomizer/3drando/hint_list.hpp | 16 - .../hint_list/hint_list_exclude_dungeon.cpp | 3167 ++++----- .../hint_list/hint_list_exclude_overworld.cpp | 2956 ++++---- .../3drando/hint_list/hint_list_item.cpp | 4224 ++++++------ .../Enhancements/randomizer/3drando/hints.cpp | 1131 ++-- .../Enhancements/randomizer/3drando/hints.hpp | 224 +- .../randomizer/3drando/location_access.hpp | 1 - .../location_access/locacc_castle_town.cpp | 4 +- .../location_access/locacc_ganons_castle.cpp | 24 +- .../location_access/locacc_hyrule_field.cpp | 4 +- .../location_access/locacc_kakariko.cpp | 2 +- .../location_access/locacc_lost_woods.cpp | 4 +- .../location_access/locacc_zoras_domain.cpp | 4 +- .../randomizer/3drando/rando_main.cpp | 2 - .../randomizer/3drando/spoiler_log.cpp | 126 +- .../Enhancements/randomizer/3drando/text.hpp | 31 +- soh/soh/Enhancements/randomizer/context.cpp | 208 +- soh/soh/Enhancements/randomizer/context.h | 19 +- soh/soh/Enhancements/randomizer/hint.cpp | 719 +- soh/soh/Enhancements/randomizer/hint.h | 95 +- soh/soh/Enhancements/randomizer/item.cpp | 2 +- soh/soh/Enhancements/randomizer/item.h | 2 +- soh/soh/Enhancements/randomizer/item_list.cpp | 8 +- .../Enhancements/randomizer/item_location.cpp | 14 +- .../Enhancements/randomizer/item_location.h | 12 +- soh/soh/Enhancements/randomizer/location.cpp | 6 +- .../Enhancements/randomizer/location_list.cpp | 151 +- .../randomizer/option_descriptions.cpp | 13 +- .../Enhancements/randomizer/randomizer.cpp | 554 +- soh/soh/Enhancements/randomizer/randomizer.h | 4 - .../Enhancements/randomizer/randomizerTypes.h | 318 +- soh/soh/Enhancements/randomizer/settings.cpp | 19 +- .../Enhancements/randomizer/static_data.cpp | 307 + soh/soh/Enhancements/randomizer/static_data.h | 30 +- soh/soh/Enhancements/randomizer/trial.cpp | 40 +- soh/soh/Enhancements/randomizer/trial.h | 30 +- soh/soh/OTRGlobals.cpp | 251 +- soh/soh/SaveManager.cpp | 185 +- soh/soh/SaveManager.h | 1 + soh/soh/z_message_OTR.cpp | 24 +- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 29 +- 51 files changed, 10736 insertions(+), 10844 deletions(-) delete mode 100644 soh/soh/Enhancements/randomizer/3drando/hint_list.hpp create mode 100644 soh/soh/Enhancements/randomizer/static_data.cpp diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 92c13e85f..8c71fb023 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -3,7 +3,9 @@ #include #include #include -#include +#include +#include +#include using namespace std::literals::string_literals; @@ -14,9 +16,10 @@ static const std::unordered_map textBoxSpecialCharacters = { { "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B }, { "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E } }; -static const std::unordered_map colors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, +static const std::unordered_map percentColors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE }, { "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK } }; + static const std::unordered_map altarIcons = { { "0", ITEM_KOKIRI_EMERALD }, { "1", ITEM_GORON_RUBY }, @@ -33,61 +36,190 @@ static const std::unordered_map altarIcons = { { "c", ITEM_OCARINA_FAIRY }, { "i", ITEM_OCARINA_TIME }, { "L", ITEM_BOW_ARROW_LIGHT }, - { "k", ITEM_TUNIC_KOKIRI } + { "k", ITEM_TUNIC_KOKIRI }, + { "m", ITEM_DUNGEON_MAP }, + { "C", ITEM_COMPASS }, + { "s", ITEM_SKULL_TOKEN }, + { "g", ITEM_MASK_GORON } +}; + +static std::map pixelWidthTable = { + { " ", 6 }, { "!", 6 }, { "\"", 5 }, { "#", 7 }, { "$", 7 }, { "%", 11 }, { "&", 9 }, { "\'", 3 }, + { "(", 6 }, { ")", 6 }, { "*", 6 }, { "+", 7 }, { ",", 3 }, { "-", 5 }, { ".", 3 }, { "/", 7 }, + { "0", 8 }, { "1", 4 }, { "2", 7 }, { "3", 7 }, { "4", 8 }, { "5", 7 }, { "6", 7 }, { "7", 7 }, + { "8", 7 }, { "9", 7 }, { ":", 5 }, { ";", 5 }, { "<", 7 }, { "=", 9 }, { ">", 7 }, { "?", 9 }, + { "@", 10 }, { "A", 9 }, { "B", 7 }, { "C", 9 }, { "D", 9 }, { "E", 6 }, { "F", 6 }, { "G", 9 }, + { "H", 8 }, { "I", 3 }, { "J", 6 }, { "K", 8 }, { "L", 6 }, { "M", 10 }, { "N", 9 }, { "O", 10 }, + { "P", 7 }, { "Q", 10 }, { "R", 8 }, { "S", 8 }, { "T", 7 }, { "U", 8 }, { "V", 9 }, { "W", 12 }, + { "X", 9 }, { "Y", 8 }, { "Z", 8 }, { "[", 6 }, { "\\", 8 }, { "]", 6 }, { "^", 8 }, { "_", 7 }, + { "`", 4 }, { "a", 6 }, { "b", 7 }, { "c", 6 }, { "d", 7 }, { "e", 7 }, { "f", 5 }, { "g", 7 }, + { "h", 6 }, { "i", 3 }, { "j", 5 }, { "k", 6 }, { "l", 3 }, { "m", 9 }, { "n", 7 }, { "o", 7 }, + { "p", 7 }, { "q", 7 }, { "r", 6 }, { "s", 6 }, { "t", 6 }, { "u", 6 }, { "v", 7 }, { "w", 9 }, + { "x", 6 }, { "y", 7 }, { "z", 6 }, { "{", 6 }, { "¦", 4 }, { "}", 6 }, { "¡", 5 }, { "¢", 7 }, + { "£", 8 }, { "¤", 7 }, { "¥", 8 }, { "|", 4 }, { "§", 12 }, { "¨", 12 }, { "©", 10 }, { "ª", 5 }, + { "«", 8 }, { "¬", 7 }, { "\u00AD", 6 }, { "®", 10 }, { "¯", 8 }, { "°", 12 }, { "±", 12 }, { "²", 5 }, + { "³", 5 }, { "µ", 6 }, { "¶", 8 }, { "·", 4 }, { "¹", 4 }, { "º", 5 }, { "»", 9 }, { "¼", 9 }, + { "½", 9 }, { "¾", 10 }, { "¿", 7 }, { "À", 11 }, { "Á", 9 }, { "Â", 9 }, { "Ã", 9 }, { "Ä", 9 }, + { "Å", 9 }, { "Æ", 12 }, { "Ç", 9 }, { "È", 6 }, { "É", 6 }, { "Ê", 6 }, { "Ë", 6 }, { "Ì", 5 }, + { "Í", 5 }, { "Î", 5 }, { "Ï", 5 }, { "Ð", 10 }, { "Ñ", 9 }, { "Ò", 10 }, { "Ó", 10 }, { "Ô", 10 }, + { "Õ", 10 }, { "Ö", 10 }, { "×", 9 }, { "Ø", 10 }, { "Ù", 8 }, { "Ú", 8 }, { "Û", 8 }, { "Ü", 8 }, + { "Ý", 10 }, { "Þ", 8 }, { "ß", 7 }, { "à", 6 }, { "á", 6 }, { "â", 6 }, { "ã", 6 }, { "ä", 6 }, + { "å", 6 }, { "æ", 11 }, { "ç", 6 }, { "è", 7 }, { "é", 7 }, { "ê", 7 }, { "ë", 7 }, { "ì", 5 }, + { "í", 5 }, { "î", 5 }, { "ï", 5 }, { "ð", 7 }, { "ñ", 7 }, { "ò", 7 }, { "ó", 7 }, { "ô", 7 }, + { "õ", 7 }, { "ö", 7 }, { "÷", 11 }, { "ø", 9 }, { "ù", 7 }, { "ú", 7 }, { "û", 7 }, { "ü", 7 }, + { "ý", 8 }, { "þ", 8 }, { "ÿ", 8 }, { "Œ", 11 }, { "œ", 11 }, { "„", 5 }, { "”", 5 }, { "€", 10 }, + { "Ÿ", 10 }, { "~", 8 } }; CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_, TextBoxPosition position_) - : english(std::move(english_)), german(std::move(german_)), french(std::move(french_)), type(type_), - position(position_) { + : type(type_), position(position_){ + messages[LANGUAGE_ENG] = std::move(english_); + messages[LANGUAGE_GER] = std::move(german_); + messages[LANGUAGE_FRA] = std::move(french_); +} + +CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, std::vector colors_, + std::vector capital_, TextBoxType type_, TextBoxPosition position_) { + messages[LANGUAGE_ENG] = std::move(english_); + messages[LANGUAGE_GER] = std::move(german_); + messages[LANGUAGE_FRA] = std::move(french_); + colors = colors_; + capital = capital_; + type = type_; + position = position_; +} + +CustomMessage::CustomMessage(std::string english_, TextBoxType type_, TextBoxPosition position_) + : type(type_), position(position_) { + messages[LANGUAGE_ENG] = std::move(english_); +} + +CustomMessage::CustomMessage(std::string english_, std::vector colors_, std::vector capital_, TextBoxType type_, TextBoxPosition position_){ + messages[LANGUAGE_ENG] = std::move(english_); + colors = colors_; + capital = capital_; + type = type_; + position = position_; } CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition position_) - : english(text.GetEnglish()), german(text.GetGerman()), french(text.GetFrench()), type(type_), - position(position_) { + : type(type_), position(position_) { + messages[LANGUAGE_ENG] = text.GetEnglish(); + messages[LANGUAGE_GER] = text.GetGerman(); + messages[LANGUAGE_FRA] = text.GetFrench(); } -const std::string& CustomMessage::GetEnglish() const { - return english; +const std::string CustomMessage::GetEnglish(MessageFormat format) const { + return GetForLanguage(LANGUAGE_ENG, format); } -const std::string& CustomMessage::GetFrench() const { - if (french.length() > 0) { - return french; - } - return english; +const std::string CustomMessage::GetGerman(MessageFormat format) const { + return GetForLanguage(LANGUAGE_GER, format); } -const std::string& CustomMessage::GetGerman() const { - if (german.length() > 0) { - return german; + +const std::string CustomMessage::GetFrench(MessageFormat format) const { + return GetForLanguage(LANGUAGE_FRA, format); +} + +const std::string CustomMessage::GetForCurrentLanguage(MessageFormat format) const { + return GetForLanguage(gSaveContext.language, format); +} + +const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat format) const { + std::string output = messages[language].length() > 0 ? messages[language] : messages[LANGUAGE_ENG]; + ProcessMessageFormat(output, format); + return output; +} + +const std::vector CustomMessage::GetAllMessages(MessageFormat format) const{ + std::vector output = messages; + for (auto str : output){ + ProcessMessageFormat(str, format); } - return english; + return output; +} + +void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const { + if (format == MF_FORMATTED){ + FormatString(str); + } else if (format == MF_CLEAN){ + CleanString(str); + } else if (format == MF_AUTO_FORMAT){ + AutoFormatString(str); + } +} + +const std::vector& CustomMessage::GetCapital() const { + return capital; +} + +void CustomMessage::SetCapital(std::vector capital_){ + capital = capital_; +} +const std::vector& CustomMessage::GetColors() const { + return colors; +} + +void CustomMessage::SetColors(std::vector colors_){ + colors = colors_; } const TextBoxType& CustomMessage::GetTextBoxType() const { return type; } +void CustomMessage::SetTextBoxType(TextBoxType boxType){ + type = boxType; +} + const TextBoxPosition& CustomMessage::GetTextBoxPosition() const { return position; } CustomMessage CustomMessage::operator+(const CustomMessage& right) const { - return CustomMessage(english + right.GetEnglish(), german + right.GetGerman(), french + right.GetFrench()); + std::vector newColors = colors; + std::vector rColors = right.GetColors(); + for (auto color: rColors){ + newColors.push_back(color); + } + std::vector newCapital = capital; + newCapital.insert(capital.end(), right.GetCapital().begin(), right.GetCapital().end()); + return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW), + messages[LANGUAGE_GER] + right.GetGerman(MF_RAW), + messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), + newColors, newCapital, type, position); } CustomMessage CustomMessage::operator+(const std::string& right) const { - return CustomMessage(english + right, german + right, french + right); + return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right, messages[LANGUAGE_FRA] + right); +} + +void CustomMessage::operator+=(const CustomMessage& right) { + messages[LANGUAGE_ENG] += right.GetEnglish(MF_RAW); + messages[LANGUAGE_GER] += right.GetGerman(MF_RAW); + messages[LANGUAGE_FRA] += right.GetFrench(MF_RAW); + colors.insert(colors.end(), right.GetColors().begin(), right.GetColors().end()); + capital.insert(capital.end(), right.GetCapital().begin(), right.GetCapital().end()); } void CustomMessage::operator+=(const std::string& right) { - english += right; - french += right; - german += right; + messages[LANGUAGE_ENG] += right; + messages[LANGUAGE_GER] += right; + messages[LANGUAGE_FRA] += right; } bool CustomMessage::operator==(const CustomMessage& operand) const { - return english == operand.english; + return messages[LANGUAGE_ENG] == operand.messages[LANGUAGE_ENG]; +} + +bool CustomMessage::operator==(const std::string& operand) const { + for (auto str: messages){ + if (str == operand){ + return true; + } + } + return false; } bool CustomMessage::operator!=(const CustomMessage& operand) const { @@ -95,83 +227,209 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const { } void CustomMessage::Replace(std::string&& oldStr, std::string&& newStr) { - for (std::string* str : { &english, &french, &german }) { - size_t position = str->find(oldStr); + for (std::string& str : messages) { + size_t position = str.find(oldStr); while (position != std::string::npos) { - str->replace(position, oldStr.length(), newStr); - position = str->find(oldStr); + str.replace(position, oldStr.length(), newStr); + position = str.find(oldStr); } } - Format(); } -void CustomMessage::Replace(std::string&& oldStr, std::string&& newEnglish, std::string&& newGerman, - std::string&& newFrench) { - size_t position = 0; - position = english.find(oldStr); - while (position != std::string::npos) { - english.replace(position, oldStr.length(), newEnglish); - position = english.find(oldStr); +void CustomMessage::Replace(std::string&& oldStr, CustomMessage newMessage) { + for (uint8_t language = 0; language < LANGUAGE_MAX; language++) { + size_t position = messages[language].find(oldStr); + while (position != std::string::npos) { + messages[language].replace(position, oldStr.length(), newMessage.messages[language]); + position = messages[language].find(oldStr); + } } - position = french.find(oldStr); - while (position != std::string::npos) { - french.replace(position, oldStr.length(), newFrench); - position = french.find(oldStr); - } - position = german.find(oldStr); - while (position != std::string::npos) { - german.replace(position, oldStr.length(), newGerman); - position = german.find(oldStr); - } - Format(); } void CustomMessage::Format(ItemID iid) { - for (std::string* str : { &english, &french, &german }) { - str->insert(0, ITEM_OBTAINED(iid)); + for (std::string &str : messages) { + str.insert(0, ITEM_OBTAINED(iid)); size_t start_pos = 0; - std::replace(str->begin(), str->end(), '&', NEWLINE()[0]); - while ((start_pos = str->find('^', start_pos)) != std::string::npos) { - str->replace(start_pos, 1, WAIT_FOR_INPUT() + ITEM_OBTAINED(iid)); + std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); + while ((start_pos = str.find('^', start_pos)) != std::string::npos) { + str.replace(start_pos, 1, WAIT_FOR_INPUT() + ITEM_OBTAINED(iid)); start_pos += 3; } - std::replace(str->begin(), str->end(), '@', PLAYER_NAME()[0]); + std::replace(str.begin(), str.end(), '@', PLAYER_NAME()[0]); + ReplaceSpecialCharacters(str); + ReplaceColors(str); + ReplaceAltarIcons(str); } - ReplaceSpecialCharacters(); - ReplaceColors(); - ReplaceAltarIcons(); *this += MESSAGE_END(); } void CustomMessage::Format() { - for (std::string* str : { &english, &french, &german }) { - std::replace(str->begin(), str->end(), '&', NEWLINE()[0]); - std::replace(str->begin(), str->end(), '^', WAIT_FOR_INPUT()[0]); - std::replace(str->begin(), str->end(), '@', PLAYER_NAME()[0]); + for (std::string& str : messages) { + FormatString(str); } - ReplaceSpecialCharacters(); - ReplaceColors(); - ReplaceAltarIcons(); - *this += MESSAGE_END(); } +void CustomMessage::AutoFormat() { + for (std::string& str : messages) { + AutoFormatString(str); + } +} + +void CustomMessage::Clean() { + for (std::string& str : messages) { + CleanString(str); + } +} + +void CustomMessage::FormatString(std::string& str) const { + std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); + std::replace(str.begin(), str.end(), '^', WAIT_FOR_INPUT()[0]); + std::replace(str.begin(), str.end(), '@', PLAYER_NAME()[0]); + ReplaceSpecialCharacters(str); + ReplaceColors(str); + ReplaceAltarIcons(str); + str += MESSAGE_END(); +} + +void DeleteControlCode(std::string& str, std::string code){ + size_t start_pos = 0; + while ((start_pos = str.find(code, start_pos)) != std::string::npos) { + str.replace(start_pos, code.length(), ""); + start_pos += code.length(); + } +} + +void CustomMessage::CleanString(std::string& str) const { + std::replace(str.begin(), str.end(), '&', "\n"[0]); + std::replace(str.begin(), str.end(), '^', " "[0]); + for (const auto& colorPair : percentColors) { + DeleteControlCode(str, "%" + colorPair.first); + } + std::erase(str, '#'); + for (const auto& iconPair : altarIcons) { + DeleteControlCode(str, "$" + iconPair.first); + } +} + +static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) { + const size_t maxLinePixelWidth = hasIcon ? 200 : 216; + + + size_t totalPixelWidth = 0; + size_t currentPos = lastNewline; + + // Looping through the string from the lastNewline until the total + // width of counted characters exceeds the maximum pixels in a line. + size_t nextPosJump = 0; + while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { + // Skip over control codes + if (textStr->at(currentPos) == '%') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '$') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '@') { + nextPosJump = 1; + // Assume worst case for player name 12 * 8 (widest character * longest name length) + totalPixelWidth += 96; + } else { + // Some characters only one byte while others are two bytes + // So check both possibilities when checking for a character + if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; + nextPosJump = 1; + } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; + nextPosJump = 2; + } else { + SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); + SPDLOG_DEBUG("Full string: " + *textStr); + nextPosJump = 1; + } + } + currentPos += nextPosJump; + } + // return the total number of characters we looped through + if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') { + return currentPos - lastNewline - nextPosJump; + } else { + return currentPos - lastNewline; + } +} + +void CustomMessage::AutoFormatString(std::string& str) const {// did I do this right? + ReplaceAltarIcons(str); + ReplaceColors(str); + // insert newlines either manually or when encountering a '&' + size_t lastNewline = 0; + const bool hasIcon = str.find('$', 0) != std::string::npos; + size_t lineLength = NextLineLength(&str, lastNewline, hasIcon); + while (lastNewline + lineLength < str.length()) { + const size_t carrot = str.find('^', lastNewline); + const size_t ampersand = str.find('&', lastNewline); + const size_t lastSpace = str.rfind(' ', lastNewline + lineLength); + const size_t lastPeriod = str.rfind('.', lastNewline + lineLength); + // replace '&' first if it's within the newline range + if (ampersand < lastNewline + lineLength) { + lastNewline = ampersand + 1; + // 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) { + str.replace(lastPeriod, 1, ".&"); + lastNewline = lastPeriod + 2; + } else { + str.replace(lastSpace, 1, "&"); + lastNewline = lastSpace + 1; + } + lineLength = NextLineLength(&str, lastNewline, hasIcon); + } + ReplaceSpecialCharacters(str); + ReplaceAltarIcons(str); + std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); + std::replace(str.begin(), str.end(), '^', WAIT_FOR_INPUT()[0]); + std::replace(str.begin(), str.end(), '@', PLAYER_NAME()[0]); + str += MESSAGE_END(); +} + +void CustomMessage::InsertNumber(uint8_t num){ + for (std::string& str : messages) { + size_t firstBar = str.find('|'); + if (firstBar != std::string::npos) { + size_t secondBar = str.find('|', firstBar + 1); + if (secondBar != std::string::npos) { + size_t thirdBar = str.find('|', secondBar + 1); + if (thirdBar != std::string::npos) { + if (num == 1) { + str.erase(secondBar, thirdBar - secondBar); + } else { + str.erase(firstBar, secondBar - firstBar); + } + } + } + } + } + //remove the remaining bar + this->Replace("|", ""); + Replace("[[d]]", std::to_string(num)); +} + + void CustomMessage::Capitalize() { - for (std::string* str : { &english, &french, &german }) { - (*str)[0] = std::toupper((*str)[0]); + for (std::string str : messages) { + (str)[0] = std::toupper((str)[0]); } } -void CustomMessage::ReplaceSpecialCharacters() { +void CustomMessage::ReplaceSpecialCharacters(std::string& str) const { // add special characters - for (std::string* str : { &english, &french, &german }) { - for (auto specialCharacterPair : textBoxSpecialCharacters) { - size_t start_pos = 0; - std::string textBoxSpecialCharacterString = ""s; - textBoxSpecialCharacterString += specialCharacterPair.second; - while ((start_pos = str->find(specialCharacterPair.first, start_pos)) != std::string::npos) { - str->replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString); - start_pos += textBoxSpecialCharacterString.length(); - } + for (auto specialCharacterPair : textBoxSpecialCharacters) { + size_t start_pos = 0; + std::string textBoxSpecialCharacterString = ""s; + textBoxSpecialCharacterString += specialCharacterPair.second; + while ((start_pos = str.find(specialCharacterPair.first, start_pos)) != std::string::npos) { + str.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString); + start_pos += textBoxSpecialCharacterString.length(); } } } @@ -194,31 +452,49 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) { return textChar; } -void CustomMessage::ReplaceColors() { - for (std::string* str : { &english, &french, &german }) { - for (const auto& colorPair : colors) { - std::string textToReplace = "%"; - textToReplace += colorPair.first; - size_t start_pos = 0; - while ((start_pos = str->find(textToReplace, start_pos)) != std::string::npos) { - str->replace(start_pos, textToReplace.length(), COLOR(colorPair.second)); - start_pos += textToReplace.length(); - } +void CustomMessage::ReplaceColors(std::string& str) const { + for (const auto& colorPair : percentColors) { + std::string textToReplace = "%"; + textToReplace += colorPair.first; + size_t start_pos = 0; + while ((start_pos = str.find(textToReplace, start_pos)) != std::string::npos) { + str.replace(start_pos, textToReplace.length(), COLOR(colorPair.second)); + start_pos += textToReplace.length(); + } + } + for (auto color: colors) { + if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) { + str.replace(firstHashtag, 1, COLOR(color)); + if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) { + str.replace(secondHashtag, 1, COLOR(QM_WHITE)); + } else { + SPDLOG_DEBUG("non-matching hashtags in string: \"%s\"", str); + } + } + } + // Remove any remaining '#' characters. + std::erase(str, '#'); +} + +void CustomMessage::ReplaceAltarIcons(std::string& str) const { + for (const auto& iconPair : altarIcons) { + std::string textToReplace = "$"; + textToReplace += iconPair.first; + size_t start_pos = 0; + while ((start_pos = str.find(textToReplace, start_pos)) != std::string::npos) { + str.replace(start_pos, textToReplace.length(), ITEM_OBTAINED(iconPair.second)); + start_pos += textToReplace.length(); } } } -void CustomMessage::ReplaceAltarIcons() { - for (std::string* str : { &english, &french, &german }) { - for (const auto& iconPair : altarIcons) { - std::string textToReplace = "$"; - textToReplace += iconPair.first; - size_t start_pos = 0; - while ((start_pos = str->find(textToReplace, start_pos)) != std::string::npos) { - str->replace(start_pos, textToReplace.length(), ITEM_OBTAINED(iconPair.second)); - start_pos += textToReplace.length(); - } - } +void CustomMessage::InsertNames(std::vector toInsert){ + for(uint8_t a = 0; a < toInsert.size(); a++){ + CustomMessage temp = toInsert[a]; + if ((capital.size() > a) && (capital[a] = true)){ + temp.Capitalize(); + } + Replace("[[" + std::to_string(a+1) + "]]", temp); } } @@ -234,8 +510,12 @@ std::string CustomMessage::NEWLINE() { return "\x01"s; } -std::string CustomMessage::COLOR(uint8_t x) { - return "\x05"s + char(x); +std::string CustomMessage::COLOR(std::string x) { + return "\x05"s + x; +} + +std::string CustomMessage::POINTS(std::string x) { + return "\x1E"s + x; } std::string CustomMessage::WAIT_FOR_INPUT() { diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 9c5cc92ee..2c797e527 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -1,8 +1,9 @@ #pragma once -#include #include #include #include +#include +#include #include "../../../include/z64item.h" #include "../../../include/message_data_textbox_types.h" @@ -10,14 +11,23 @@ #undef MESSAGE_END -#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 +#define QM_WHITE "\x00"s +#define QM_RED "\x41" +#define QM_GREEN "\x42" +#define QM_BLUE "\x43" +#define QM_LBLUE "\x44" +#define QM_PINK "\x45" +#define QM_YELLOW "\x46" +#define QM_BLACK "\x47" + +#define HS_HORSE_ARCHERY "\x00"s //HS_HBA is an enum already + +typedef enum { + MF_FORMATTED, + MF_CLEAN, + MF_RAW, + MF_AUTO_FORMAT +} MessageFormat; /** * @brief Encapsulates logic surrounding languages, and formatting strings for OoT's textboxes and @@ -30,25 +40,41 @@ class CustomMessage { CustomMessage() = default; CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + CustomMessage(std::string english_, std::string german_, std::string french_, std::vector colors_, std::vector capital_ = {}, + TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + CustomMessage(std::string english_, std::vector colors_, std::vector capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); static std::string MESSAGE_END() ; static std::string ITEM_OBTAINED(uint8_t x) ; static std::string NEWLINE() ; - static std::string COLOR(uint8_t x) ; + static std::string COLOR(std::string x) ; + static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro static std::string WAIT_FOR_INPUT() ; static std::string PLAYER_NAME() ; - const std::string& GetEnglish() const; - const std::string& GetFrench() const; - const std::string& GetGerman() const; + const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; + const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; + const std::string GetGerman(MessageFormat format = MF_FORMATTED) const; + const std::string GetForCurrentLanguage(MessageFormat format = MF_FORMATTED) const; + const std::string GetForLanguage(uint8_t language, MessageFormat format = MF_FORMATTED) const; + const std::vector GetAllMessages(MessageFormat format = MF_FORMATTED) const; + void ProcessMessageFormat(std::string& str, MessageFormat format) const; + const std::vector& GetColors() const; + void SetColors(std::vector colors_); + const std::vector& GetCapital() const; + void SetCapital(std::vector capital_); const TextBoxType& GetTextBoxType() const; + void SetTextBoxType(TextBoxType boxType); const TextBoxPosition& GetTextBoxPosition() const; CustomMessage operator+(const CustomMessage& right) const; CustomMessage operator+(const std::string& right) const; void operator+=(const std::string& right); - bool operator==(const CustomMessage& right) const; + void operator+=(const CustomMessage& right); + bool operator==(const CustomMessage& operand) const; + bool operator==(const std::string& operand) const; bool operator!=(const CustomMessage& right) const; /** @@ -63,15 +89,13 @@ class CustomMessage { /** * @brief Finds an instance of oldStr in each language of the CustomMessage, - * and replaces it with the corresponding new string provided for each language. + * and replaces it with the corresponding string in the provided CustomMessage. * Typically used for dynamic variable replacement (i.e. gameplay stats, skulltula count) * * @param oldStr the string to be replaced - * @param newEnglish the new string for the English message - * @param newGerman the new string for the German message - * @param newFrench the new string for the French message + * @param newMessage the message containing the new strings. */ - void Replace(std::string&& oldStr, std::string&& newEnglish, std::string&& newGerman, std::string&& newFrench); + void Replace(std::string&& oldStr, CustomMessage newMessage); /** * @brief Capitalizes the first letter of the string for each language. @@ -82,17 +106,22 @@ class CustomMessage { * @brief Replaces special characters (things like diacritics for non-english langugages) * with the control codes used to display them in OoT's textboxes. */ - void ReplaceSpecialCharacters(); + void ReplaceSpecialCharacters(std::string& str) const; /** * @brief Replaces our color variable strings with the OoT control codes. */ - void ReplaceColors(); + void ReplaceColors(std::string& str) const; /** * @brief Replaces `$` variable strings with OoT control codes. */ - void ReplaceAltarIcons(); + void ReplaceAltarIcons(std::string& str) const; + + /** + * @brief Replaces [[1]] style variable strings with the provided vector of customMessages + */ + void InsertNames(std::vector toInsert); /** * @brief Replaces various symbols with the control codes necessary to @@ -103,6 +132,15 @@ class CustomMessage { */ void Format(ItemID iid); + /** + * @brief Replaces [[d]] in text with the supplied number, and if plural + * options exist (2 blocks of text surrounded by |) choose the former if it 1, + * and the latter otherwise, deleting the other and the |'s. + * + * @param num the number to insert. + */ + void InsertNumber(uint8_t num); + /** * @brief Replaces various symbols with the control codes necessary to * display them in OoT's textboxes. i.e. special characters, colors, newlines, @@ -110,12 +148,44 @@ class CustomMessage { */ void Format(); + /** + * @brief formats the message specifically to fit in OoT's + * textboxes, and use it's formatting. + */ + void AutoFormat(); + + /** + * @brief Removes all OoT formatting from the message, + * making it a good form for writing into spoiler logs. + */ + void Clean(); + + /** + * @brief Replaces various symbols with the control codes necessary to + * display them in OoT's textboxes for a single string + * . i.e. special characters, colors, newlines, wait for input, etc. + */ + void FormatString(std::string& str) const; + + /** + * @brief formats the string specifically to fit in OoT's + * textboxes, and use it's formatting. + * RANDOTODO whoever knows exactly what this does check my adaption + */ + void AutoFormatString(std::string& str) const; + + /** + * @brief Removes symbols used for control codes from the string, + * leaving raw text + */ + void CleanString(std::string& str) const; + private: - std::string english = ""; - std::string french = ""; - std::string german = ""; + std::vector messages = {"","",""}; TextBoxType type = TEXTBOX_TYPE_BLACK; TextBoxPosition position = TEXTBOX_POS_BOTTOM; + std::vector colors = {}; + std::vector capital = {}; }; typedef std::unordered_map CustomMessageTable; diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 737d22665..1f5a093c7 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -100,6 +100,7 @@ typedef enum { TEXT_MALON_LINK_HAS_TIME_BUT_NO_RECORD = 0x2090, TEXT_MALON_LINK_HAS_RECORD = 0x2091, TEXT_MALON_FIRST_BEAT_THIS_RECORD = 0x2092, + TEXT_BIGGORON_I_MAAAADE_THISSSS = 0x3002, TEXT_MEDIGORON = 0x304C, TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME = 0x3052, TEXT_BIGGORON_BETTER_AT_SMITHING = 0x3053, diff --git a/soh/soh/Enhancements/debugger/MessageViewer.cpp b/soh/soh/Enhancements/debugger/MessageViewer.cpp index 51fe3c0b9..92ae5070d 100644 --- a/soh/soh/Enhancements/debugger/MessageViewer.cpp +++ b/soh/soh/Enhancements/debugger/MessageViewer.cpp @@ -204,16 +204,7 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId); font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); switch (language) { - case LANGUAGE_FRA: - font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetFrench(), maxBufferSize); - break; - case LANGUAGE_GER: - font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetGerman(), maxBufferSize); - break; - case LANGUAGE_ENG: - default: - font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetEnglish(), maxBufferSize); - break; + font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize); } msgCtx->msgLength = static_cast(font->msgLength); } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 5d86b11f4..e129048c8 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1161,9 +1161,7 @@ void RegisterAltTrapTypes() { void RegisterRandomizerSheikSpawn() { GameInteractor::Instance->RegisterGameHook([]() { if (!gPlayState) return; - bool canSheik = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIAL_COUNT) != 0 && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LIGHT_ARROWS_HINT)); - if (!IS_RANDO || !LINK_IS_ADULT || !canSheik) return; + if (!IS_RANDO || !LINK_IS_ADULT || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHEIK_LA_HINT)) return; switch (gPlayState->sceneNum) { case SCENE_TEMPLE_OF_TIME: if (gPlayState->roomCtx.curRoom.num == 1) { diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 822b61c75..7bc941afb 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -403,7 +403,8 @@ const std::vector randomizerCvars = { "gRandomizeLacsRewardOptions", "gRandomizeLacsStoneCount", "gRandomizeLacsTokenCount", - "gRandomizeLAHint", + "gRandomizeGanondorfHint", + "gRandomizeSheikLAHint", "gRandomizeLinksPocket", "gRandomizeLogicRules", "gRandomizeMedallionCount", diff --git a/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp b/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp index 338cb86e7..c00ec8840 100644 --- a/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp @@ -158,7 +158,7 @@ constexpr std::array DungeonColors = { CreateMessage(textId, unk_04, textBoxType, textBoxPosition, text.GetEnglish(), text.GetFrench(), text.GetSpanish()); } - Text AddColorsAndFormat(Text text, const std::vector& colors /*= {}*/) { + Text AddColorsAndFormat(Text text, const std::vector& colors /*= {}*/) { //for each language for (std::string* textStr : {&text.english, &text.french, &text.spanish}) { @@ -280,12 +280,12 @@ constexpr std::array DungeonColors = { std::string SET_SPEED(uint8_t x) { return "\x7F\x10"s + char(x); } - std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; } + std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; } //RANDOTODO just refernce the versions in CustomMessage std::string CURRENT_TIME() { return "\x7F\x17"s; } std::string UNSKIPPABLE() { return "\x7F\x19"s; } std::string TWO_WAY_CHOICE() { return "\x1B"s; } std::string NEWLINE() { return "\x7F\x1C"s; } - std::string COLOR(uint8_t x) { return "\x7F\x1D"s + char(x); } + std::string COLOR(std::string x) { return "\x7F\x1D"s + 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; } diff --git a/soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp b/soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp index c8029dc66..b9d2a08c6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp @@ -7,15 +7,6 @@ #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. @@ -73,7 +64,7 @@ typedef struct { std::string UNSKIPPABLE(); std::string TWO_WAY_CHOICE(); std::string NEWLINE(); - std::string COLOR(uint8_t x); + std::string COLOR(std::string x); std::string CENTER_TEXT(); std::string IF_NOT_MQ(); std::string MQ_ELSE(); diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index f87871944..bf9b9ef19 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -9,7 +9,6 @@ #include "spoiler_log.hpp" #include "starting_inventory.hpp" #include "hints.hpp" -#include "hint_list.hpp" #include "../entrance.h" #include "shops.hpp" #include "pool_functions.hpp" @@ -1145,13 +1144,6 @@ int Fill() { ctx->CreateItemOverrides(); ctx->GetEntranceShuffler()->CreateEntranceOverrides(); - SPDLOG_INFO("Creating Other Hint Texts..."); - //funny ganon line - Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); - CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); - SetGanonText(ganonText); - SPDLOG_INFO("Creating Other Hint Texts Done"); - CreateAllHints(); CreateWarpSongTexts(); return 1; diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index c6269d5de..33f6c64d0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -1,12 +1,11 @@ -#include "hint_list.hpp" #include "custom_messages.hpp" #include "../randomizerTypes.h" #include "../context.h" - -#include +#include "../static_data.h" using namespace CustomMessages; +using namespace std::literals::string_literals; // Big thanks to Lioncache, Gabyelnuevo, Danius88, and Charade for their translations! @@ -19,27 +18,34 @@ using namespace CustomMessages; // surrounding text with '#' will make it a different color // - OoT Randomizer -// '%d' indicates a number will be placed there. +// '[[d]]' indicates a number will be placed there, numbers in [[]] will be replaced by other text in hints +namespace Rando { -std::array hintTable; - -void HintTable_Init() { +void StaticData::HintTable_Init() { /*-------------------------- - | GENERAL TEXT | + | GENERAL TEXT | ---------------------------*/ - hintTable[RHT_NONE] = HintText::Exclude({ Text{ "No Hint", "Pas d'Indice", "" } }); - hintTable[RHT_PREFIX] = - HintText::Exclude({ Text{ "They say that ", /*french*/ "Selon moi, ", /*spanish*/ "Según dicen, " } }); - hintTable[RHT_WAY_OF_THE_HERO] = - HintText::Exclude({ Text{ " is on #the way of the hero#.", /*french*/ " est sur #la voie du héros#.", - /*spanish*/ " conduce a la senda del héroe." } }); - hintTable[RHT_PLUNDERING] = - HintText::Exclude({ Text{ "plundering ", /*french*/ "explorer ", /*spanish*/ "inspeccionar " } }); - hintTable[RHT_FOOLISH] = HintText::Exclude( - { Text{ " is #a foolish choice#.", /*french*/ " est #futile#.", /*spanish*/ " #no es una sabia decisión#." } }); - hintTable[RHT_CAN_BE_FOUND_AT] = - HintText::Exclude({ Text{ "can be found at", /*french*/ "se trouve dans", /*spanish*/ "aguarda en" } }); - hintTable[RHT_HOARDS] = HintText::Exclude({ Text{ "hoards", /*french*/ "recèle", /*spanish*/ "acapara" } }); + hintTextTable[RHT_NONE] = HintText(CustomMessage("No Hint", "", "Pas d'Indice" )); + hintTextTable[RHT_WAY_OF_THE_HERO] = + HintText(CustomMessage( "They say that #[[1]]# is on #the way of the hero#.", + "", + /*french*/ "Selon moi, #[[1]]# est sur #la voie du héros#.", {QM_RED, QM_LBLUE})); + // /*spanish*/ "Según dicen, #[[1]]# conduce a la senda del héroe." + hintTextTable[RHT_FOOLISH] = + HintText(CustomMessage( "They say that plundering #[[1]]# is #a foolish choice#.", + "", + /*french*/ "Selon moi, explorer #[[1]]# est #futile#.", {QM_RED, QM_PINK})); + // /*spanish*/ "Según dicen, inspeccionar #[[1]]# #no es una sabia decisión#." + hintTextTable[RHT_CAN_BE_FOUND_AT] = + HintText(CustomMessage( "They say that #[[1]]# can be found at #[[2]]#.", + "", + /*french*/ "Selon moi, #[[1]]# se trouve dans #[[2]]#.", {QM_GREEN, QM_RED})); + // /*spanish*/ "Según dicen, #[[1]]# aguarda en #[[2]]#." + hintTextTable[RHT_HOARDS] = + HintText(CustomMessage( "They say that #[[2]]# hoards #[[1]]#.", + "", + /*french*/ "Selon moi, #[[2]]# recèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ "Según dicen, #[[2]]# acapara #[[1]]#." HintTable_Init_Item(); HintTable_Init_Exclude_Overworld(); @@ -50,2036 +56,1720 @@ void HintTable_Init() { | SOMETIMES HINT TEXT | ---------------------------*/ - hintTable[RHT_KF_LINKS_HOUSE_COW] = HintText::Sometimes( - { - // obscure text - Text{ "the #bovine bounty of a horseback hustle# gifts", - /*french*/ "le cadeau #qui découle d'une réussite équestre# est", - /*spanish*/ "la #recompensa bovina de un paseo a caballo# brinda" }, - }, - {}, - // clear text - Text{ "#Malon's obstacle course# leads to", /*french*/ "la #course à obstacle de Malon# amène à", - /*spanish*/ "la #carrera de obstáculos de Malon# brinda" }); - - hintTable[RHT_KAK_100_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#100 bug badges# rewards", - /*french*/ "#100 écussons# donnent", - /*spanish*/ "#100 medallas de insectos# otorgan" }, - Text{ "#100 spider souls# yields", - /*french*/ "#100 âmes d'arachnide# donnent", - /*spanish*/ "#100 almas de araña# otorgan" }, - Text{ "#100 auriferous arachnids# lead to", - /*french*/ "#100 arachnides aurifères# donnent", - /*spanish*/ "#100 arácnidos auríferos# otorgan" }, - }, - {}, - // clear text - Text{ "slaying #100 Gold Skulltulas# reveals", - /*french*/ "détruire #100 Skulltulas d'or# donne", - /*spanish*/ "exterminar #100 skulltulas doradas# revela" }); - - hintTable[RHT_SONG_FROM_OCARINA_OF_TIME] = HintText::Sometimes({ - // obscure text - Text{ "the #Ocarina of Time# teaches", /*french*/ "l'#Ocarina du Temps# est accompagné par", - /*spanish*/ "la #Ocarina del Tiempo# enseña" }, - }); - - hintTable[RHT_SONG_FROM_ROYAL_FAMILYS_TOMB] = HintText::Sometimes({ - // obscure text - Text{ "#ReDead in the Composers' Grave# guard", - /*french*/ "les #Éffrois du tombeau des compositeurs# protègent", - /*spanish*/ "los #ReDeads del Panteón Real# guardan" }, - Text{ "the #Composer Brothers wrote#", /*french*/ "le #trésor des compositeurs# est", - /*spanish*/ "los #hermanos compositores escribieron#" }, - }); - - hintTable[RHT_SHEIK_IN_FOREST] = HintText::Sometimes({ - // obscure text - Text{ "#in a meadow# Sheik teaches", /*french*/ "Sheik confiera, #dans un bosquet#,", - /*spanish*/ "#en la pradera sagrada# Sheik enseña" }, - }); - - hintTable[RHT_SHEIK_AT_TEMPLE] = HintText::Sometimes({ - // obscure text - Text{ "Sheik waits at a #monument to time# to teach", - /*french*/ "Sheik confiera, #au pied de l'épée légendaire#,", - /*spanish*/ "Sheik espera en el #momumento del tiempo# para enseñar" }, - }); - - hintTable[RHT_SHEIK_IN_CRATER] = HintText::Sometimes({ - // obscure text - Text{ "the #crater's melody# is", /*french*/ "Sheik confiera, #entouré de lave#,", - /*spanish*/ "la #melodía del cráter# otorga" }, - }); - - hintTable[RHT_SHEIK_IN_ICE_CAVERN] = HintText::Sometimes({ - // obscure text - Text{ "the #frozen cavern# echoes with", /*french*/ "Sheik confiera, #dans une caverne enneigée#,", - /*spanish*/ "en la #caverna de hielo# retumban los ecos de" }, - }); - - hintTable[RHT_SHEIK_IN_KAKARIKO] = HintText::Sometimes({ - // obscure text - Text{ "a #ravaged village# mourns with", /*french*/ "Sheik confirera, #au coeur d'un village ravagé#,", - /*spanish*/ "un #arrasado pueblo# llora" }, - }); - - hintTable[RHT_SHEIK_AT_COLOSSUS] = HintText::Sometimes({ - // obscure text - Text{ "a hero ventures #beyond the wasteland# to learn", - /*french*/ "Sheik confiera, #au bout d'un chemin sableux#,", - /*spanish*/ "el héroe que se adentre #más allá del desierto# aprenderá" }, - }); - - hintTable[RHT_MARKET_10_BIG_POES] = HintText::Sometimes( - { - // obscure text - Text{ "#ghost hunters# will be rewarded with", - /*french*/ "#les chasseurs de fantômes# sont récompensés avec", - /*spanish*/ "los #cazafantasmas# son premiados con" }, - }, - {}, - // clear text - Text{ "catching #Big Poes# leads to", /*french*/ "#d'attraper des Àmes# donne", - /*spanish*/ "hacerte con #Grandes Poes# conduce a" }); - - hintTable[RHT_DEKU_THEATER_SKULL_MASK] = HintText::Sometimes({ - // obscure text - Text{ "the #Skull Mask# yields", /*french*/ "le #Masque de Mort# donne", - /*spanish*/ "la #máscara de calavera# otorga" }, - }); - - hintTable[RHT_DEKU_THEATER_MASK_OF_TRUTH] = HintText::Sometimes( - { - // obscure text - Text{ "showing a #truthful eye to the crowd# rewards", - /*french*/ "montrer #l'oeil de vérité à la foule# donne", - /*spanish*/ "#mostrarle el ojo verdadero# a una multitud brinda" }, - }, - {}, - // clear text - Text{ "the #Mask of Truth# yields", /*french*/ "le #Masque de Vérité# donne", - /*spanish*/ "la #máscara de la verdad# premia" }); - - hintTable[RHT_HF_OCARINA_OF_TIME_ITEM] = HintText::Sometimes({ - // obscure text - Text{ "the #treasure thrown by Princess Zelda# is", /*french*/ "le trésor #laissé par la princesse# est", - /*spanish*/ "el #tesoro arrojado por la Princesa Zelda# se trata de" }, - }); - - hintTable[RHT_DMT_TRADE_BROKEN_SWORD] = HintText::Sometimes({ - // obscure text - Text{ "a #blinded Biggoron# entrusts", /*french*/ "un #Grogoron aveuglé# confie", - /*spanish*/ "un #miope Biggoron# otorga" }, - }); - - hintTable[RHT_DMT_TRADE_EYEDROPS] = HintText::Sometimes({ - // obscure text - Text{ "while you wait, #Biggoron# gives", /*french*/ "pendant que tu attends, #Biggoron# donne", - /*spanish*/ "#Biggoron# está a la espera de otorgar" }, - }); - - hintTable[RHT_DMT_TRADE_CLAIM_CHECK] = HintText::Sometimes({ - // obscure text - Text{ "#Biggoron# crafts", /*french*/ "#Biggoron# fabrique", /*spanish*/ "#Biggoron# forja" }, - }); - - hintTable[RHT_KAK_50_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#50 bug badges# rewards", /*french*/ "#50 écussons# donnent", - /*spanish*/ "#50 medallas de insectos# otorgan" }, - Text{ "#50 spider souls# yields", /*french*/ "#50 âmes d'arachnide# donnent", - /*spanish*/ "#50 almas de araña# otorgan" }, - Text{ "#50 auriferous arachnids# lead to", /*french*/ "#50 arachnides aurifères# donnent", - /*spanish*/ "#50 arácnidos auríferos# otorgan" }, - }, - {}, - // clear text - Text{ "slaying #50 Gold Skulltulas# reveals", /*french*/ "détruire #50 Skulltulas d'or# donne", - /*spanish*/ "exterminar #50 skulltulas doradas# revela" }); - - hintTable[RHT_KAK_40_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#40 bug badges# rewards", /*french*/ "#40 écussons# donnent", - /*spanish*/ "#40 medallas de insectos# otorgan" }, - Text{ "#40 spider souls# yields", /*french*/ "#40 âmes d'arachnide# donnent", - /*spanish*/ "#40 almas de araña# otorgan" }, - Text{ "#40 auriferous arachnids# lead to", /*french*/ "#40 arachnides aurifères# donnent", - /*spanish*/ "#40 arácnidos auríferos# otorgan" }, - }, - {}, - // clear text - Text{ "slaying #40 Gold Skulltulas# reveals", /*french*/ "détruire #40 Skulltulas d'or# donne", - /*spanish*/ "exterminar #40 skulltulas doradas# revela" }); - - hintTable[RHT_KAK_30_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#30 bug badges# rewards", /*french*/ "#30 écussons# donnent", - /*spanish*/ "#30 medallas de insectos# otorgan" }, - Text{ "#30 spider souls# yields", /*french*/ "#30 âmes d'arachnide# donnent", - /*spanish*/ "#30 almas de araña# otorgan" }, - Text{ "#30 auriferous arachnids# lead to", /*french*/ "#30 arachnides aurifères# donnent", - /*spanish*/ "#30 arácnidos auríferos# otorgan" }, - }, - {}, - // clear text - Text{ "slaying #30 Gold Skulltulas# reveals", /*french*/ "détruire #30 Skulltulas d'or# donne", - /*spanish*/ "exterminar #30 skulltulas doradas# revela" }); - - hintTable[RHT_KAK_20_GOLD_SKULLTULA_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#20 bug badges# rewards", /*french*/ "#20 écussons# donnent", - /*spanish*/ "#20 medallas de insectos# otorgan" }, - Text{ "#20 spider souls# yields", /*french*/ "#20 âmes d'arachnide# donnent", - /*spanish*/ "#20 almas de araña# otorgan" }, - Text{ "#20 auriferous arachnids# lead to", /*french*/ "#20 arachnides aurifères# donnent", - /*spanish*/ "#20 arácnidos auríferos# otorgan" }, - }, - {}, - // clear text - Text{ "slaying #20 Gold Skulltulas# reveals", /*french*/ "détruire #20 Skulltulas d'or# donne", - /*spanish*/ "exterminar #20 skulltulas doradas# revela" }); - - hintTable[RHT_KAK_ANJU_AS_CHILD] = HintText::Sometimes( - { - // obscure text - Text{ "#wrangling roosters# rewards", /*french*/ "#plumer des poulets# donne", - /*spanish*/ "#atrapar a las gallinas# premia" }, - Text{ "#chucking chickens# gifts", /*french*/ "#lancer des poulets# donne", - /*spanish*/ "#reunir a unos emplumados# premia" }, - }, - {}, - // clear text - Text{ "#collecting cuccos# rewards", /*french*/ "#rapporter les Cocottes# donne", - /*spanish*/ "#hacerte con todos los cucos# premia" }); - - hintTable[RHT_KAK_TRADE_POCKET_CUCCO] = HintText::Sometimes({ - // obscure text - Text{ "an adult's #happy Cucco# awards", /*french*/ "un adulte avec une #poulette joyeuse# obtient", - /*spanish*/ "un #alegre cuco# en la madurez otorga" }, - }); - - hintTable[RHT_KAK_TRADE_ODD_MUSHROOM] = HintText::Sometimes({ - // obscure text - Text{ "the #potion shop lady# entrusts", /*french*/ "la #gribiche du magasin de potion# confie", - /*spanish*/ "la #señora de la tienda de pociones# otorga" }, - }); - - hintTable[RHT_GC_DARUNIAS_JOY] = HintText::Sometimes( - { - // obscure text - Text{ "a #groovin' goron# gifts", /*french*/ "#le Goron joyeux# donne", - /*spanish*/ "#un goron marchoso# otorga" }, - }, - {}, - // clear text - Text{ "#Darunia's dance# leads to", /*french*/ "#la dance de Darunia# donne", - /*spanish*/ "#el baile de Darunia# conduce a" }); - - hintTable[RHT_LW_SKULL_KID] = HintText::Sometimes({ - // obscure text - Text{ "the #Skull Kid# grants", /*french*/ "le #Skull Kid# donne", /*spanish*/ "#Skull Kid# otorga" }, - }); - - hintTable[RHT_LW_TRADE_COJIRO] = HintText::Sometimes({ - // obscure text - Text{ "returning a #special Cucco# awards", /*french*/ "ramener une #poulette précieuse# donne", - /*spanish*/ "quien devuelva un #cuco especial# encontrará" }, - }); - - hintTable[RHT_LW_TRADE_ODD_POTION] = HintText::Sometimes({ - // obscure text - Text{ "a #Kokiri girl in the woods# leaves", /*french*/ "la #fillette Kokiri dans les bois# laisse", - /*spanish*/ "una #chica kokiri del bosque# otorga" }, - }); - - hintTable[RHT_LH_SUN] = HintText::Sometimes( - { - // obscure text - Text{ "staring into #the sun# grants", /*french*/ "regarder #le soleil# donne", - /*spanish*/ "#mirar al sol# revela" }, - }, - {}, - // clear text - Text{ "shooting #the sun# grants", /*french*/ "tirer une flèche dans #sur le soleil# donne", - /*spanish*/ "#disparar al sol# revela" }); - - hintTable[RHT_LH_TRADE_FROG] = HintText::Sometimes({ - // obscure text - Text{ "#Lake Hylia's scientist# hurriedly entrusts", /*french*/ "le #scientifique du lac# confie rapidement", - /*spanish*/ "el #científico del Lago Hylia# otorga con prisa" }, - }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_REWARD] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling# grants", /*french*/ "#parier# donne", /*spanish*/ "#los juegos de azar# revelan" }, - Text{ "there is a #1/32 chance# to win", /*french*/ "être #le gagnant parmi 32# donne", - /*spanish*/ "hay una #probabilidad de 1/32# de ganar" }, - }, - {}, - // clear text - Text{ "the #treasure chest game# grants", /*french*/ "la #Chasse-aux-Trésors# donne", - /*spanish*/ "#el Cofre del Tesoro# premia" }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling once# grants", /*french*/ "#parier une fois# donne", - /*spanish*/ "#apostar solo una vez# revelará" }, - Text{ "the #first or second game chest# contains", - /*french*/ "le #premier ou deuxième coffre à jeu# contient", - /*spanish*/ "#el primer o segundo cofre del azar# revela" }, - }, - {}, - // clear text - Text{ "the #first locked room# in the chest game contains", - /*french*/ "la #première salle# de la Chasse-aux-Trésors contient", - /*spanish*/ "#en la primera sala del Cofre del Tesoro# aguarda" }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling twice# grants", /*french*/ "#parier deux fois# donne", - /*spanish*/ "#apostar dos veces# revelará" }, - Text{ "the #third or fourth game chest# contains", - /*french*/ "le #troisième ou quatrième coffre à jeu# contient", - /*spanish*/ "#el tercer o cuarto cofre del azar# revela" }, - }, - {}, - // clear text - Text{ "the #second locked room# in the chest game contains", - /*french*/ "la #deuxième salle# de la Chasse-aux-Trésors contient", - /*spanish*/ "#en la segunda sala del Cofre del Tesoro# aguarda" }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling 3 times# grants", /*french*/ "#parier trois fois# donne", - /*spanish*/ "#apostar tres veces# revelará" }, - Text{ "the #fifth or sixth game chest# contains", - /*french*/ "le #cinquième ou sixième coffre à jeu# contient", - /*spanish*/ "#el quinto o sexto cofre del azar# revela" }, - }, - {}, - // clear text - Text{ "the #third locked room# in the chest game contains", - /*french*/ "la #troisième salle# de la Chasse-aux-Trésors contient", - /*spanish*/ "#en la tercera sala del Cofre del Tesoro# aguarda" }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling 4 times# grants", /*french*/ "#parier quatre fois# donne", - /*spanish*/ "#apostar cuatro veces# revelará" }, - Text{ "the #seventh or eighth game chest# contains", - /*french*/ "le #septième ou huitième coffre à jeu# contient", - /*spanish*/ "#el séptimo u octavo cofre del azar# revela" }, - }, - {}, - // clear text - Text{ "the #fourth locked room# in the chest game contains", - /*french*/ "la #quatrième salle# de la Chasse-aux-Trésors contient", - /*spanish*/ "#en la cuarta sala del Cofre del Tesoro# aguarda" }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5] = HintText::Sometimes( - { - // obscure text - Text{ "#gambling 5 times# grants", /*french*/ "#parier cinq fois# donne", - /*spanish*/ "#apostar cinco veces# revelará" }, - Text{ "the #ninth or tenth game chest# contains", - /*french*/ "le #neuvième ou dixième coffre à jeu# contient", - /*spanish*/ "#el noveno o décimo cofre del azar# revela" }, - }, - {}, - // clear text - Text{ "the #fifth locked room# in the chest game contains", - /*french*/ "la #cinquième salle# de la Chasse-aux-Trésors contient", - /*spanish*/ "#en la quinta sala del Cofre del Tesoro# aguarda" }); - - hintTable[RHT_GF_HBA_1500_POINTS] = HintText::Sometimes( - { - // obscure text - Text{ "mastery of #horseback archery# grants", /*french*/ "maîtriser l'#archerie équestre# donne", - /*spanish*/ "dominar el #tiro con arco a caballo# premia con" }, - }, - {}, - // clear text - Text{ "scoring 1500 in #horseback archery# grants", - /*french*/ "obtenir 1500 points dans l'#archerie équestre# donne", - /*spanish*/ "conseguir 1500 puntos en el #tiro con arco a caballo# premia" }); - - hintTable[RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "playing #Sun's Song# in a grave spawns", /*french*/ "jouer le #chant du soleil# dans un tombeau donne", - /*spanish*/ "#tocar la Canción del Sol# en una cripta conduce a" }, - }); - - hintTable[RHT_GC_MAZE_LEFT_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "in #Goron City# the hammer unlocks", /*french*/ "dans le #village Goron#, le marteau donne accès à", - /*spanish*/ "en la #Ciudad Goron# el martillo desbloquea" }, - }); - - hintTable[RHT_GV_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "in #Gerudo Valley# the hammer unlocks", /*french*/ "dans la #Vallée Gerudo#, le marteau donne accès à", - /*spanish*/ "en el #Valle Gerudo# el martillo desbloquea" }, - }); - - hintTable[RHT_GV_TRADE_SAW] = HintText::Sometimes({ - // obscure text - Text{ "the #boss of the carpenters# leaves", /*french*/ "le #patron des ouvriers# laisse", - /*spanish*/ "el #capataz de los carpinteros# otorga" }, - }); - - hintTable[RHT_GV_COW] = HintText::Sometimes({ - // obscure text - Text{ "a #cow in Gerudo Valley# gifts", /*french*/ "la #vache de la Vallée Gerudo# donne", - /*spanish*/ "una #vaca del Valle Gerudo# brinda" }, - }); - - hintTable[RHT_HC_GS_STORMS_GROTTO] = HintText::Sometimes({ - // obscure text - Text{ "a #spider behind a muddy wall# in a grotto holds", - /*french*/ "l'#araignée derrière un mur de boue# dans une grotte donne", - /*spanish*/ "una #Skulltula tras la agrietada pared# de una cueva otorga" }, - }); - - hintTable[RHT_HF_GS_COW_GROTTO] = HintText::Sometimes({ - // obscure text - Text{ "a #spider behind webs# in a grotto holds", - /*french*/ "l'#araignée derrière une toile# dans une grotte donne", - /*spanish*/ "una #Skulltula tras la telaraña# de una cueva otorga" }, - }); - - hintTable[RHT_HF_COW_GROTTO_COW] = HintText::Sometimes( - { - // obscure text - Text{ "the #cobwebbed cow# gifts", /*french*/ "la #vache prisonnière d'araignées# donne", - /*spanish*/ "una #vaca tras una telaraña# brinda" }, - }, - {}, - // clear text - Text{ "a #cow behind webs# in a grotto gifts", /*french*/ "la #vache derrière les toiles# d'une grotte donne", - /*spanish*/ "una #vaca tras la telaraña# de una cueva brinda" }); - - hintTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText::Sometimes( - { - // obscure text - Text{ "an #amphibian feast# yields", /*french*/ "un #festin d'amphibiens# donne", - /*spanish*/ "una #fiesta anfibia# brinda" }, - Text{ "the #croaking choir's magnum opus# awards", /*french*/ "la #chorale coassante# donne", - /*spanish*/ "un #coro maestro de ancas# premia" }, - Text{ "the #froggy finale# yields", /*french*/ "la #finale amphibienne# donne", - /*spanish*/ "el #gran final batracio# brinda" }, - }, - {}, - // clear text - Text{ "the final reward from the #Frogs of Zora's River# is", - /*french*/ "la dernière récompense des #grenouilles de la Rivière Zora# est", - /*spanish*/ "la recompensa final de las #ranas del Río Zora# premia" }); - - hintTable[RHT_ZF_GS_HIDDEN_CAVE] = HintText::Sometimes({ - // obscure text - Text{ "a spider high #above the icy waters# holds", /*french*/ "l'araignée #en haut des eaux glacées# donne", - /*spanish*/ "una Skulltula en lo #alto de las congeladas aguas# otorga" }, - }); - - hintTable[RHT_WASTELAND_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "#deep in the wasteland# is", /*french*/ "#loin dans le désert# gît", - /*spanish*/ "en lo #profundo del desierto encantado# yace" }, - Text{ "beneath #the sands#, flames reveal", /*french*/ "#sous le désert#, les flammes font apparaître", - /*spanish*/ "tras las #arenas# unas llamas revelan" }, - }); - - hintTable[RHT_WASTELAND_GS] = HintText::Sometimes({ - // obscure text - Text{ "a #spider in the wasteland# holds", /*french*/ "#l'araignée dans le désert# donne", - /*spanish*/ "una #Skulltula del desierto encantado# otorga" }, - }); - - hintTable[RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "#flames in the Composers' Grave# reveal", - /*french*/ "#les flammes dans le tombeau des compositeurs# cachent", - /*spanish*/ "#las llamas del Panteón Real# revelan" }, - Text{ "the #Composer Brothers hid#", /*french*/ "#les Frères compositeurs on caché#", - /*spanish*/ "los #hermanos compositores esconden#" }, - }); - - hintTable[RHT_ZF_BOTTOM_FREESTANDING_POH] = HintText::Sometimes({ - // obscure text - Text{ "#under the icy waters# lies", /*french*/ "#sous les eaux glacées# se cache", - /*spanish*/ "#bajo las congeladas aguas# yace" }, - }); - - hintTable[RHT_GC_POT_FREESTANDING_POH] = HintText::Sometimes({ - // obscure text - Text{ "spinning #Goron pottery# contains", /*french*/ "la #potterie Goron# contient", - /*spanish*/ "una #cerámica goron# contiene" }, - }); - - hintTable[RHT_ZD_KING_ZORA_THAWED] = HintText::Sometimes( - { - // obscure text - Text{ "a #defrosted dignitary# gifts", /*french*/ "le #monarque libéré# donne", - /*spanish*/ "una #liberación monárquica# brinda" }, - }, - {}, - // clear text - Text{ "unfreezing #King Zora# grants", /*french*/ "dégeler # le Roi Zora# donne", - /*spanish*/ "#descongelar al Rey Zora# conduce a" }); - - hintTable[RHT_ZD_TRADE_PRESCRIPTION] = HintText::Sometimes({ - // obscure text - Text{ "#King Zora# hurriedly entrusts", /*french*/ "le #roi Zora# confie rapidement", - /*spanish*/ "el #Rey Zora# otorga con prisa" }, - }); - - hintTable[RHT_DMC_DEKU_SCRUB] = HintText::Sometimes({ - // obscure text - Text{ "a single #scrub in the crater# sells", /*french*/ "la #peste Mojo dans le cratère# vend", - /*spanish*/ "un solitario #deku del cráter# vende" }, - }); - - hintTable[RHT_DMC_GS_CRATE] = HintText::Sometimes({ - // obscure text - Text{ "a spider under a #crate in the crater# holds", /*french*/ "la Skulltula dans une #boîte volcanique# a", - /*spanish*/ "una Skulltula bajo una #caja del cráter# otorga" }, - }); - - hintTable[RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "a #temporal stone within a tree# contains", /*french*/ "la #pierre bleue dans un arbre# mène à", - /*spanish*/ "un #bloque temporal de un árbol# contiene" }, - }, - {}, - // clear text - Text{ "a #temporal stone within the Deku Tree# contains", - /*french*/ "la #pierre temporelle dans l'Arbre Mojo# cache", - /*spanish*/ "un #bloque temporal del Gran Árbol Deku# contiene" }); - - hintTable[RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = HintText::Sometimes( - { - // obscure text - Text{ "a #spider on a ceiling in a tree# holds", /*french*/ "l'#araignée haut-perchée dans un arbre# a", - /*spanish*/ "una #Skulltula en el techo de un árbol# otorga" }, - }, - {}, - // clear text - Text{ "a #spider on a ceiling in the Deku Tree# holds", - /*french*/ "la#Skulltula dans le Cimetière de l'Arbre Mojo# a", - /*spanish*/ "una #Skulltula en el techo del Gran Árbol Deku# otorga" }); - - hintTable[RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = HintText::Sometimes( - { - // obscure text - Text{ "a spider under #temporal stones in a cavern# holds", - /*french*/ "l'araignée sous #une pierre bleue dans une caverne# a", - /*spanish*/ "una Skulltula bajo #bloques temporales de una cueva# otorga" }, - }, - {}, - // clear text - Text{ "a spider under #temporal stones in Dodongo's Cavern# holds", - /*french*/ "la Skulltula sous #la pierre temporelle dans la Caverne Dodongo# a", - /*spanish*/ "una Skulltula bajo #bloques temporales de la Cueva de los Dodongos# otorga" }); - - hintTable[RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "a school of #stingers swallowed by a deity# guard", - /*french*/ "les #raies dans un gardien# protègent", - /*spanish*/ "unos de #stingers engullidos por cierta deidad# guardan" }, - }, - {}, - // clear text - Text{ "a school of #stingers swallowed by Jabu-Jabu# guard", /*french*/ "les #raies dans Jabu-Jabu# protègent", - /*spanish*/ "unos #stingers engullidos por Jabu-Jabu# guardan" }); - - hintTable[RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = HintText::Sometimes( - { - // obscure text - Text{ "a spider surrounded by #shadows in the belly of a deity# holds", - /*french*/ "l'araignée entourée d'#ombres dans le ventre du gardien# possède", - /*spanish*/ "una Skulltula rodeada de #sombras en la tripa de cierta diedad# otorga" }, - }, - {}, - // clear text - Text{ "a spider surrounded by #shadows in Jabu-Jabu's Belly# holds", - /*french*/ "la Skulltula entourée d'#ombres dans Jabu-Jabu# possède", - /*spanish*/ "una Skulltula rodeada de #sombras en la Tripa de Jabu-Jabu# otorga" }); - - hintTable[RHT_JABU_JABUS_BELLY_MQ_COW] = HintText::Sometimes( - { - // obscure text - Text{ "a #cow swallowed by a deity# gifts", /*french*/ "la #vache dans le gardien# donne", - /*spanish*/ "una #vaca engullida por cierta deidad# brinda" }, - }, - {}, - // clear text - Text{ "a #cow swallowed by Jabu-Jabu# gifts", /*french*/ "la #vache avallée par Jabu-Jabu# donne", - /*spanish*/ "una #vaca engullida por Jabu-Jabu# brinda" }); - - hintTable[RHT_FIRE_TEMPLE_SCARECROW_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "a #scarecrow atop the volcano# hides", /*french*/ "l'#épouvantail au sommet d'un volcan# donne", - /*spanish*/ "un #espantapájaros en lo alto del volcán# esconde" }, - }, - {}, - // clear text - Text{ "#Pierre atop the Fire Temple# hides", /*french*/ "#Pierre au sommet du Temple du Feu# donne", - /*spanish*/ "#Pierre en lo alto del Templo del Fuego# esconde" }); - - hintTable[RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "the #Flare Dancer atop the volcano# guards a chest containing", - /*french*/ "le #danseur au sommet du volcan# protège", - /*spanish*/ "el #Bailafuego en lo alto del volcán# otorga" }, - }, - {}, - // clear text - Text{ "the #Flare Dancer atop the Fire Temple# guards a chest containing", - /*french*/ "le #Danse-Flamme au sommet du Temple du Feu# protège", - /*spanish*/ "el #Bailaguego en lo alto del Templo del Fuego# otorga" }); - - hintTable[RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = HintText::Sometimes( - { - // obscure text - Text{ "the #Flare Dancer atop the volcano# guards a chest containing", - /*french*/ "le #danseur au sommet du volcan# protège", - /*spanish*/ "el #Bailafuego en lo alto del volcán# otorga" }, - }, - {}, - // clear text - Text{ "the #Flare Dancer atop the Fire Temple# guards a chest containing", - /*french*/ "le #Danse-Flamme au sommet du Temple du Feu# protège", - /*spanish*/ "el #Bailafuego en lo alto del Templo del Fuego# otorga" }); - - hintTable[RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = HintText::Sometimes( - { - // obscure text - Text{ "a #spider under a block in the volcano# holds", - /*french*/ "l'#araignée sous un bloc dans le volcan# a", - /*spanish*/ "una #Skulltula bajo el bloque de un volcán# otorga" }, - }, - {}, - // clear text - Text{ "a #spider under a block in the Fire Temple# holds", - /*french*/ "une #Skulltula sous un bloc dans le Temple du Feu# a", - /*spanish*/ "una #Skulltula bajo un bloque del Templo del Fuego# otorga" }); - - hintTable[RHT_WATER_TEMPLE_RIVER_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "beyond the #river under the lake# waits", /*french*/ "au delà de #la rivière sous le lac# se cache", - /*spanish*/ "tras el #río bajo el lago# yace" }, - }, - {}, - // clear text - Text{ "beyond the #river in the Water Temple# waits", - /*french*/ "au delà de #la rivière dans le Temple de l'Eau# se cache", - /*spanish*/ "tras el #río del Templo del Agua# yace" }); - - hintTable[RHT_WATER_TEMPLE_BOSS_KEY_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "dodging #rolling boulders under the lake# leads to", - /*french*/ "éviter des #rochers roulants sous le lac# mène à", - /*spanish*/ "esquivar #rocas rodantes bajo el lago# conduce a" }, - }, - {}, - // clear text - Text{ "dodging #rolling boulders in the Water Temple# leads to", - /*french*/ "éviter des #rochers roulants dans le Temple de l'Eau# mène à", - /*spanish*/ "esquivar #rocas rondantes del Templo del Agua# conduce a" }); - - hintTable[RHT_WATER_TEMPLE_GS_BEHIND_GATE] = HintText::Sometimes( - { - // obscure text - Text{ "a spider behind a #gate under the lake# holds", - /*french*/ "l'araignée derrière une #barrière sous le lac# a", - /*spanish*/ "una Skulltula tras #una valla bajo el lago# otorga" }, - }, - {}, - // clear text - Text{ "a spider behind a #gate in the Water Temple# holds", - /*french*/ "la Skulltula derrière une #barrière dans le Temple de l'Eau# a", - /*spanish*/ "una Skulltula tras #una valla del Templo del Agua# otorga" }); - - hintTable[RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY] = HintText::Sometimes( - { - // obscure text - Text{ "hidden in a #box under the lake# lies", /*french*/ "dans une #boîte sous le lac# gît", - /*spanish*/ "en una #caja bajo el lago# yace" }, - }, - {}, - // clear text - Text{ "hidden in a #box in the Water Temple# lies", /*french*/ "dans une #boîte dans le Temple de l'Eau# gît", - /*spanish*/ "en una #caja del Templo del Agua# yace" }); - - hintTable[RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = HintText::Sometimes( - { - // obscure text - Text{ "the #locked spider under the lake# holds", /*french*/ "l'#araignée emprisonnée sous le lac# a", - /*spanish*/ "la #Skulltula enjaulada bajo el lago# otorga" }, - }, - {}, - // clear text - Text{ "the #locked spider in the Water Temple# holds", - /*french*/ "une #Skulltula emprisonnée dans le Temple de l'Eau# a", - /*spanish*/ "la #Skulltula enjaulada del Templo del Agua# otorga" }); - - hintTable[RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = HintText::Sometimes( - { - // obscure text - Text{ "a spider behind a #gate under the lake# holds", - /*french*/ "l'#araignée derrière une barrière sous le lac# a", - /*spanish*/ "una Skulltula tras una #valla bajo el lago# otorga" }, - }, - {}, - // clear text - Text{ "a spider behind a #gate in the Water Temple# holds", - /*french*/ "une #Skulltula derrière une barrière dans le Temple de l'Eau# a", - /*spanish*/ "una Skulltula tras una #valla del Templo del Agua#" }); - - hintTable[RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "those who seek #sunken silver rupees# will find", - /*french*/ "ceux qui pêchent les #joyaux argentés# trouveront", - /*spanish*/ "aquellos que busquen las #rupias plateadas sumergidas# encontrarán" }, - Text{ "the #thieves' underwater training# rewards", /*french*/ "l'#épreuve de plongée des voleurs# recèle", - /*spanish*/ "la #instrucción submarina de las bandidas# premia" }, - }); - - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "those who seek #sunken silver rupees# will find", - /*french*/ "ceux qui pêchent les #joyaux argentés# trouveront", - /*spanish*/ "aquellos que busquen las #rupias plateadas sumergidas# encontrarán" }, - Text{ "the #thieves' underwater training# rewards", /*french*/ "l'#épreuve de plongée des voleurs# recèle", - /*spanish*/ "la #instrucción submarina de las bandidas# premia" }, - }); - - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "the final prize of #the thieves' training# is", - /*french*/ "la récompense ultime de #l'épreuve des voleurs# est", - /*spanish*/ "la recompensa final de la #instrucción de las bandida# brinda" }, - }); - - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "the final prize of #the thieves' training# is", - /*french*/ "la récompense ultime de #l'épreuve des voleurs# est", - /*spanish*/ "el premio final de la #instrucción de las bandidas# brinda" }, - }); - - hintTable[RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "the well's #grasping ghoul# hides", /*french*/ "la #terreur du Puits# cache", - /*spanish*/ "en las #profundidades del pozo# se esconde" }, - Text{ "a #nether dweller in the well# holds", /*french*/ "le #spectre qui réside dans le Puits# a", - /*spanish*/ "el #temido morador del pozo# concede" }, - }, - {}, - // clear text - Text{ "#Dead Hand in the well# holds", /*french*/ "le #Poigneur dans le Puits# cache", - /*spanish*/ "la #Mano Muerta del pozo# concede" }); - - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "the well's #grasping ghoul# hides", /*french*/ "la #terreur du Puits# cache", - /*spanish*/ "en las #profundidades del pozo# se esconde" }, - Text{ "a #nether dweller in the well# holds", /*french*/ "le #spectre qui réside dans le Puits# a", - /*spanish*/ "el #temido morador del pozo# concede" }, - }, - {}, - // clear text - Text{ "#Dead Hand in the well# holds", /*french*/ "le #Poigneur dans le Puits# cache", - /*spanish*/ "la #Mano Muerta del pozo# concede" }); - - hintTable[RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "the treasure #sought by Nabooru# is", /*french*/ "le trésor que #recherche Nabooru# est", - /*spanish*/ "el #ansiado tesoro de Nabooru# brinda" }, - }, - {}, - // clear text - Text{ "upon the #Colossus's right hand# is", /*french*/ "sur la #main droite du colosse# repose", - /*spanish*/ "en la #mano derecha del Coloso# yace" }); - - hintTable[RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "upon the #Colossus's left hand# is", /*french*/ "sur la #main gauche du colosse# repose", - /*spanish*/ "en la #mano izquierda del Coloso# yace" }, - }); - - hintTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "a #temporal paradox in the Colossus# yields", - /*french*/ "un #paradoxe temporel dans le colosse# révèle", - /*spanish*/ "una #paradoja temporal del Coloso# conduce a" }, - }, - {}, - // clear text - Text{ "a #temporal paradox in the Spirit Temple# yields", - /*french*/ "le #paradoxe temporel dans le Temple de l'Esprit# révèle", - /*spanish*/ "una #paradoja temporal del Coloso# conduce a" }); - - hintTable[RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = HintText::Sometimes( - { - // obscure text - Text{ "a #symphony in the Colossus# yields", /*french*/ "la #symphonie du colosse# révèle", - /*spanish*/ "una #sinfonía del Coloso# conduce a" }, - }, - {}, - // clear text - Text{ "a #symphony in the Spirit Temple# yields", - /*french*/ "les #cinq chansons du Temple de l'Esprit# révèlent", - /*spanish*/ "una #sinfonía del Coloso# conduce a" }); - - hintTable[RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = HintText::Sometimes( - { - // obscure text - Text{ "a #spider's symphony in the Colossus# yields", - /*french*/ "la #mélodie de l'araignée du colosse# révèle", - /*spanish*/ "la #Skulltula de la sinfonía del Coloso# otorga" }, - }, - {}, - // clear text - Text{ "a #spider's symphony in the Spirit Temple# yields", - /*french*/ "la #mélodie de la Skulltula du Temple de l'Esprit# révèle", - /*spanish*/ "la #Skulltula de la sinfonía del Coloso# otorga" }); - - hintTable[RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "shadows in an #invisible maze# guard", /*french*/ "les ombres dans le #labyrinthe invisible# protègent", - /*spanish*/ "las sombras del #laberinto misterioso# esconden" }, - }); - - hintTable[RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = HintText::Sometimes({ - // obscure text - Text{ "shadows in an #invisible maze# guard", /*french*/ "les ombres dans le #labyrinthe invisible# protègent", - /*spanish*/ "las sombras del #laberinto invisible# esconden" }, - }); + hintTextTable[RHT_KF_LINKS_HOUSE_COW] = HintText(CustomMessage("They say that #Malon's obstacle course# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #course à obstacle de Malon# amène à #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #carrera de obstáculos de Malon# brinda #[[1]]#. + {}, + {CustomMessage("They say that the #bovine bounty of a horseback hustle# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le cadeau #qui découle d'une réussite équestre# est #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/la #recompensa bovina de un paseo a caballo# brinda #[[1]]#. + + hintTextTable[RHT_KAK_100_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #100 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #100 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/exterminar #100 skulltulas doradas# revela #[[1]]#. + {}, + {CustomMessage("They say that #100 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #100 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#100 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #100 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #100 âmes d'arachnide# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#100 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #100 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #100 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#100 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_SONG_FROM_OCARINA_OF_TIME] = HintText(CustomMessage("They say that the #Ocarina of Time# teaches #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#Ocarina du Temps# est accompagné par #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/la #Ocarina del Tiempo# enseña #[[1]]#. + + hintTextTable[RHT_SONG_FROM_ROYAL_FAMILYS_TOMB] = HintText(CustomMessage("They say that #ReDead in the Composers' Grave# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Éffrois du tombeau des compositeurs# protègent #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/los #ReDeads del Panteón Real# guardan #[[1]]#. + + hintTextTable[RHT_SHEIK_IN_FOREST] = HintText(CustomMessage("They say that #in a meadow# Sheik teaches #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confiera, #dans un bosquet#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#en la pradera sagrada# Sheik enseña #[[1]]#. + + hintTextTable[RHT_SHEIK_AT_TEMPLE] = HintText(CustomMessage("They say that Sheik waits at a #monument to time# to teach #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confiera, #au pied de l'épée légendaire#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/Sheik espera en el #momumento del tiempo# para enseñar #[[1]]#. + + hintTextTable[RHT_SHEIK_IN_CRATER] = HintText(CustomMessage("They say that the #crater's melody# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confiera, #entouré de lave#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/la #melodía del cráter# otorga #[[1]]#. + + hintTextTable[RHT_SHEIK_IN_ICE_CAVERN] = HintText(CustomMessage("They say that the #frozen cavern# echoes with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confiera, #dans une caverne enneigée#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/en la #caverna de hielo# retumban los ecos de #[[1]]#. + + hintTextTable[RHT_SHEIK_IN_KAKARIKO] = HintText(CustomMessage("They say that a #ravaged village# mourns with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confirera, #au coeur d'un village ravagé#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/un #arrasado pueblo# llora #[[1]]#. + + hintTextTable[RHT_SHEIK_AT_COLOSSUS] = HintText(CustomMessage("They say that a hero ventures #beyond the wasteland# to learn #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, Sheik confiera, #au bout d'un chemin sableux#, #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el héroe que se adentre #más allá del desierto# aprenderá #[[1]]#. + + hintTextTable[RHT_MARKET_10_BIG_POES] = HintText(CustomMessage("They say that catching #Big Poes# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #d'attraper des Àmes# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/hacerte con #Grandes Poes# conduce a #[[1]]#. + {}, + {CustomMessage("They say that #ghost hunters# will be rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les chasseurs de fantômes# sont récompensés avec #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/los #cazafantasmas# son premiados con #[[1]]#. + + hintTextTable[RHT_DEKU_THEATER_SKULL_MASK] = HintText(CustomMessage("They say that the #Skull Mask# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Masque de Mort# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/la #máscara de calavera# otorga #[[1]]#. + + hintTextTable[RHT_DEKU_THEATER_MASK_OF_TRUTH] = HintText(CustomMessage("They say that the #Mask of Truth# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Masque de Vérité# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #máscara de la verdad# premia #[[1]]#. + {}, + {CustomMessage("They say that showing a #truthful eye to the crowd# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, montrer #l'oeil de vérité à la foule# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#mostrarle el ojo verdadero# a una multitud brinda #[[1]]#. + + hintTextTable[RHT_HF_OCARINA_OF_TIME_ITEM] = HintText(CustomMessage("They say that the #treasure thrown by Princess Zelda# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le trésor #laissé par la princesse# est #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el #tesoro arrojado por la Princesa Zelda# se trata de #[[1]]#. + + hintTextTable[RHT_DMT_TRADE_BROKEN_SWORD] = HintText(CustomMessage("They say that a #blinded Biggoron# entrusts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, They say that un #Grogoron aveuglé# confie #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/un #miope Biggoron# otorga #[[1]]#. + + hintTextTable[RHT_DMT_TRADE_EYEDROPS] = HintText(CustomMessage("They say that while you wait, #Biggoron# gives #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, pendant que tu attends, #Biggoron# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#Biggoron# está a la espera de otorgar #[[1]]#. + + hintTextTable[RHT_DMT_TRADE_CLAIM_CHECK] = HintText(CustomMessage("They say that #Biggoron# crafts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Biggoron# fabrique #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#Biggoron# forja #[[1]]#. + + hintTextTable[RHT_KAK_50_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #50 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #50 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/exterminar #50 skulltulas doradas# revela #[[1]]#. + {}, + {CustomMessage("They say that #50 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #50 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#50 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #50 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #50 âmes d'arachnide# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#50 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #50 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #50 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#50 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_KAK_40_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #40 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #40 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/exterminar #40 skulltulas doradas# revela #[[1]]#. + {}, + {CustomMessage("They say that #40 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #40 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#40 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #40 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #40 âmes d'arachnide# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#40 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #40 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #40 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#40 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_KAK_30_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #30 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #30 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/exterminar #30 skulltulas doradas# revela #[[1]]#. + {}, + {CustomMessage("They say that #30 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #30 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#30 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #30 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #30 âmes d'arachnide# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#30 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #30 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #30 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#30 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_KAK_20_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #20 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #20 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/exterminar #20 skulltulas doradas# revela #[[1]]#. + {}, + {CustomMessage("They say that #20 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #20 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#20 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #20 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #20 âmes d'arachnide# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#20 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #20 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #20 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#20 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_KAK_ANJU_AS_CHILD] = HintText(CustomMessage("They say that #collecting cuccos# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #rapporter les Cocottes# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#hacerte con todos los cucos# premia #[[1]]#. + {}, + {CustomMessage("They say that #wrangling roosters# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #plumer des poulets# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#atrapar a las gallinas# premia #[[1]]#. + CustomMessage("They say that #chucking chickens# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #lancer des poulets# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#reunir a unos emplumados# premia #[[1]]#. + + hintTextTable[RHT_KAK_TRADE_POCKET_CUCCO] = HintText(CustomMessage("They say that an adult's #happy Cucco# awards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un adulte avec une #poulette joyeuse# obtient #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/un #alegre cuco# en la madurez otorga #[[1]]#. + + hintTextTable[RHT_KAK_TRADE_ODD_MUSHROOM] = HintText(CustomMessage("They say that the #potion shop lady# entrusts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #gribiche du magasin de potion# confie #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/la #señora de la tienda de pociones# otorga #[[1]]#. + + hintTextTable[RHT_GC_DARUNIAS_JOY] = HintText(CustomMessage("They say that #Darunia's dance# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #la dance de Darunia# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#el baile de Darunia# conduce a #[[1]]#. + {}, + {CustomMessage("They say that a #groovin' goron# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le Goron joyeux# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#un goron marchoso# otorga #[[1]]#. + + hintTextTable[RHT_LW_SKULL_KID] = HintText(CustomMessage("They say that the #Skull Kid# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Skull Kid# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#Skull Kid# otorga #[[1]]#. + + hintTextTable[RHT_LW_TRADE_COJIRO] = HintText(CustomMessage("They say that returning a #special Cucco# awards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, ramener une #poulette précieuse# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/quien devuelva un #cuco especial# encontrará #[[1]]#. + + hintTextTable[RHT_LW_TRADE_ODD_POTION] = HintText(CustomMessage("They say that a #Kokiri girl in the woods# leaves #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fillette Kokiri dans les bois# laisse #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #chica kokiri del bosque# otorga #[[1]]#. + + hintTextTable[RHT_LH_SUN] = HintText(CustomMessage("They say that shooting #the sun# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, tirer une flèche dans #sur le soleil# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#disparar al sol# revela #[[1]]#. + {}, + {CustomMessage("They say that staring into #the sun# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, regarder #le soleil# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#mirar al sol# revela #[[1]]#. + + hintTextTable[RHT_LH_TRADE_FROG] = HintText(CustomMessage("They say that #Lake Hylia's scientist# hurriedly entrusts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #scientifique du lac# confie rapidement #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el #científico del Lago Hylia# otorga con prisa #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_REWARD] = HintText(CustomMessage("They say that the #treasure chest game# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #Chasse-aux-Trésors# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#el Cofre del Tesoro# premia #[[1]]#. + {}, + {CustomMessage("They say that #gambling# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#los juegos de azar# revelan #[[1]]#. + CustomMessage("They say that there is a #1/32 chance# to win #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, être #le gagnant parmi 32# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/hay una #probabilidad de 1/32# de ganar #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1] = HintText(CustomMessage("They say that the #first locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #première salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la primera sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling once# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier une fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar solo una vez# revelará #[[1]]#. + CustomMessage("They say that the #first or second game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #premier ou deuxième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el primer o segundo cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2] = HintText(CustomMessage("They say that the #second locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #deuxième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la segunda sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling twice# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier deux fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar dos veces# revelará #[[1]]#. + CustomMessage("They say that the #third or fourth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #troisième ou quatrième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el tercer o cuarto cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3] = HintText(CustomMessage("They say that the #third locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #troisième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la tercera sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 3 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier trois fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar tres veces# revelará #[[1]]#. + CustomMessage("They say that the #fifth or sixth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #cinquième ou sixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el quinto o sexto cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4] = HintText(CustomMessage("They say that the #fourth locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #quatrième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la cuarta sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 4 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier quatre fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar cuatro veces# revelará #[[1]]#. + CustomMessage("They say that the #seventh or eighth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #septième ou huitième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el séptimo u octavo cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5] = HintText(CustomMessage("They say that the #fifth locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #cinquième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la quinta sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 5 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier cinq fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar cinco veces# revelará #[[1]]#. + CustomMessage("They say that the #ninth or tenth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_GF_HBA_1500_POINTS] = HintText(CustomMessage("They say that scoring 1500 in #horseback archery# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, obtenir 1500 points dans l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/conseguir 1500 puntos en el #tiro con arco a caballo# premia #[[1]]#. + {}, + {CustomMessage("They say that mastery of #horseback archery# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, maîtriser l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/dominar el #tiro con arco a caballo# premia con #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = HintText(CustomMessage("They say that playing #Sun's Song# in a grave spawns #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, jouer le #chant du soleil# dans un tombeau donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#tocar la Canción del Sol# en una cripta conduce a #[[1]]#. + + hintTextTable[RHT_GC_MAZE_LEFT_CHEST] = HintText(CustomMessage("They say that in #Goron City# the hammer unlocks #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans le #village Goron#, le marteau donne accès à #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/en la #Ciudad Goron# el martillo desbloquea #[[1]]#. + + hintTextTable[RHT_GV_CHEST] = HintText(CustomMessage("They say that in #Gerudo Valley# the hammer unlocks #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans la #Vallée Gerudo#, le marteau donne accès à #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/en el #Valle Gerudo# el martillo desbloquea #[[1]]#. + + + hintTextTable[RHT_GV_TRADE_SAW] = HintText(CustomMessage("They say that the #boss of the carpenters# leaves #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #patron des ouvriers# laisse #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el #capataz de los carpinteros# otorga #[[1]]#. + + hintTextTable[RHT_GV_COW] = HintText(CustomMessage("They say that a #cow in Gerudo Valley# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache de la Vallée Gerudo# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #vaca del Valle Gerudo# brinda #[[1]]#. + + hintTextTable[RHT_HC_GS_STORMS_GROTTO] = HintText(CustomMessage("They say that a #spider behind a muddy wall# in a grotto holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée derrière un mur de boue# dans une grotte donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #Skulltula tras la agrietada pared# de una cueva otorga #[[1]]#. + + hintTextTable[RHT_HF_GS_COW_GROTTO] = HintText(CustomMessage("They say that a #spider behind webs# in a grotto holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée derrière une toile# dans une grotte donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #Skulltula tras la telaraña# de una cueva otorga #[[1]]#. + + hintTextTable[RHT_HF_COW_GROTTO_COW] = HintText(CustomMessage("They say that a #cow behind webs# in a grotto gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache derrière les toiles# d'une grotte donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #vaca tras la telaraña# de una cueva brinda #[[1]]#. + {}, + {CustomMessage("They say that the #cobwebbed cow# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache prisonnière d'araignées# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #vaca tras una telaraña# brinda #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText(CustomMessage("They say that the final reward from the #Frogs of Zora's River# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la dernière récompense des #grenouilles de la Rivière Zora# est #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la recompensa final de las #ranas del Río Zora# premia #[[1]]#. + {}, + {CustomMessage("They say that an #amphibian feast# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #festin d'amphibiens# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #fiesta anfibia# brinda #[[1]]#. + CustomMessage("They say that the #croaking choir's magnum opus# awards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #chorale coassante# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/un #coro maestro de ancas# premia #[[1]]#. + CustomMessage("They say that the #froggy finale# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #finale amphibienne# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #gran final batracio# brinda #[[1]]#. + + hintTextTable[RHT_ZF_GS_HIDDEN_CAVE] = HintText(CustomMessage("They say that a spider high #above the icy waters# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'araignée #en haut des eaux glacées# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una Skulltula en lo #alto de las congeladas aguas# otorga #[[1]]#. + + hintTextTable[RHT_WASTELAND_CHEST] = HintText(CustomMessage("They say that #deep in the wasteland# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #loin dans le désert# gît #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/en lo #profundo del desierto encantado# yace #[[1]]#. + + hintTextTable[RHT_WASTELAND_GS] = HintText(CustomMessage("They say that a #spider in the wasteland# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #l'araignée dans le désert# donne #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #Skulltula del desierto encantado# otorga #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = HintText(CustomMessage("They say that #flames in the Composers' Grave# reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les flammes dans le tombeau des compositeurs# cachent #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#las llamas del Panteón Real# revelan #[[1]]#. + + hintTextTable[RHT_ZF_BOTTOM_FREESTANDING_POH] = HintText(CustomMessage("They say that #under the icy waters# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #sous les eaux glacées# se cache #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/#bajo las congeladas aguas# yace #[[1]]#. + + hintTextTable[RHT_GC_POT_FREESTANDING_POH] = HintText(CustomMessage("They say that spinning #Goron pottery# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #potterie Goron# contient #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una #cerámica goron# contiene #[[1]]#. + + hintTextTable[RHT_ZD_KING_ZORA_THAWED] = HintText(CustomMessage("They say that unfreezing #King Zora# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dégeler # le Roi Zora# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#descongelar al Rey Zora# conduce a #[[1]]#. + {}, + {CustomMessage("They say that a #defrosted dignitary# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #monarque libéré# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #liberación monárquica# brinda #[[1]]#. + + hintTextTable[RHT_ZD_TRADE_PRESCRIPTION] = HintText(CustomMessage("They say that #King Zora# hurriedly entrusts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #roi Zora# confie rapidement #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el #Rey Zora# otorga con prisa #[[1]]#. + + hintTextTable[RHT_DMC_DEKU_SCRUB] = HintText(CustomMessage("They say that a single #scrub in the crater# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo dans le cratère# vend #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/un solitario #deku del cráter# vende #[[1]]#. + hintTextTable[RHT_DMC_GS_CRATE] = HintText(CustomMessage("They say that a spider under a #crate in the crater# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la Skulltula dans une #boîte volcanique# a #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/una Skulltula bajo una #caja del cráter# otorga #[[1]]#. + + hintTextTable[RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = HintText(CustomMessage("They say that a #temporal stone within the Deku Tree# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pierre temporelle dans l'Arbre Mojo# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/un #bloque temporal del Gran Árbol Deku# contiene #[[1]]#. + {}, + {CustomMessage("They say that a #temporal stone within a tree# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pierre bleue dans un arbre# mène à #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/un #bloque temporal de un árbol# contiene #[[1]]#. + + + hintTextTable[RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = HintText(CustomMessage("They say that a #spider on a ceiling in the Deku Tree# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la#Skulltula dans le Cimetière de l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #Skulltula en el techo del Gran Árbol Deku# otorga #[[1]]#. + {}, + {CustomMessage("They say that a #spider on a ceiling in a tree# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée haut-perchée dans un arbre# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #Skulltula en el techo de un árbol# otorga #[[1]]#. + + hintTextTable[RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = HintText(CustomMessage("They say that a spider under #temporal stones in Dodongo's Cavern# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la Skulltula sous #la pierre temporelle dans la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una Skulltula bajo #bloques temporales de la Cueva de los Dodongos# otorga #[[1]]#. + {}, + {CustomMessage("They say that a spider under #temporal stones in a cavern# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'araignée sous #une pierre bleue dans une caverne# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una Skulltula bajo #bloques temporales de una cueva# otorga #[[1]]#. + + + hintTextTable[RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST] = HintText(CustomMessage("They say that a school of #stingers swallowed by Jabu-Jabu# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies dans Jabu-Jabu# protègent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/unos #stingers engullidos por Jabu-Jabu# guardan #[[1]]#. + {}, + {CustomMessage("They say that a school of #stingers swallowed by a deity# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies dans un gardien# protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/unos de #stingers engullidos por cierta deidad# guardan #[[1]]#. + + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = HintText(CustomMessage("They say that a spider surrounded by #shadows in Jabu-Jabu's Belly# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la Skulltula entourée d'#ombres dans Jabu-Jabu# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una Skulltula rodeada de #sombras en la Tripa de Jabu-Jabu# otorga #[[1]]#. + {}, + {CustomMessage("They say that a spider surrounded by #shadows in the belly of a deity# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'araignée entourée d'#ombres dans le ventre du gardien# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una Skulltula rodeada de #sombras en la tripa de cierta diedad# otorga #[[1]]#. + + + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_COW] = HintText(CustomMessage("They say that a #cow swallowed by Jabu-Jabu# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache avallée par Jabu-Jabu# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #vaca engullida por Jabu-Jabu# brinda #[[1]]#. + {}, + {CustomMessage("They say that a #cow swallowed by a deity# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans le gardien# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #vaca engullida por cierta deidad# brinda #[[1]]#. + + hintTextTable[RHT_FIRE_TEMPLE_SCARECROW_CHEST] = HintText(CustomMessage("They say that #Pierre atop the Fire Temple# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Pierre au sommet du Temple du Feu# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#Pierre en lo alto del Templo del Fuego# esconde #[[1]]#. + {}, + {CustomMessage("They say that a #scarecrow atop the volcano# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épouvantail au sommet d'un volcan# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/un #espantapájaros en lo alto del volcán# esconde #[[1]]#. + + hintTextTable[RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = HintText(CustomMessage("They say that the #Flare Dancer atop the Fire Temple# guards a chest containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Danse-Flamme au sommet du Temple du Feu# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/el #Bailaguego en lo alto del Templo del Fuego# otorga #[[1]]#. + {}, + {CustomMessage("They say that the #Flare Dancer atop the volcano# guards a chest containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #danseur au sommet du volcan# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #Bailafuego en lo alto del volcán# otorga #[[1]]#. + + hintTextTable[RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = HintText(CustomMessage("They say that the #Flare Dancer atop the Fire Temple# guards a chest containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Danse-Flamme au sommet du Temple du Feu# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/el #Bailafuego en lo alto del Templo del Fuego# otorga #[[1]]#. + {}, + {CustomMessage("They say that the #Flare Dancer atop the volcano# guards a chest containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #danseur au sommet du volcan# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #Bailafuego en lo alto del volcán# otorga #[[1]]#. + + hintTextTable[RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = HintText(CustomMessage("They say that a #spider under a block in the Fire Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sous un bloc dans le Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #Skulltula bajo un bloque del Templo del Fuego# otorga #[[1]]#. + {}, + {CustomMessage("They say that a #spider under a block in the volcano# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée sous un bloc dans le volcan# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #Skulltula bajo el bloque de un volcán# otorga #[[1]]#. + + + hintTextTable[RHT_WATER_TEMPLE_RIVER_CHEST] = HintText(CustomMessage("They say that beyond the #river in the Water Temple# waits #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, au delà de #la rivière dans le Temple de l'Eau# se cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/tras el #río del Templo del Agua# yace #[[1]]#. + {}, + {CustomMessage("They say that beyond the #river under the lake# waits #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, au delà de #la rivière sous le lac# se cache #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/tras el #río bajo el lago# yace #[[1]]#. + + hintTextTable[RHT_WATER_TEMPLE_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that dodging #rolling boulders in the Water Temple# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, éviter des #rochers roulants dans le Temple de l'Eau# mène à #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/esquivar #rocas rondantes del Templo del Agua# conduce a #[[1]]#. + {}, + {CustomMessage("They say that dodging #rolling boulders under the lake# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, éviter des #rochers roulants sous le lac# mène à #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/esquivar #rocas rodantes bajo el lago# conduce a #[[1]]#. + + hintTextTable[RHT_WATER_TEMPLE_GS_BEHIND_GATE] = HintText(CustomMessage("They say that a spider behind a #gate in the Water Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la Skulltula derrière une #barrière dans le Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una Skulltula tras #una valla del Templo del Agua# otorga #[[1]]#. + {}, + {CustomMessage("They say that a spider behind a #gate under the lake# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'araignée derrière une #barrière sous le lac# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una Skulltula tras #una valla bajo el lago# otorga #[[1]]#. + + hintTextTable[RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY] = HintText(CustomMessage("They say that hidden in a #box in the Water Temple# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans une #boîte dans le Temple de l'Eau# gît #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/en una #caja del Templo del Agua# yace #[[1]]#. + {}, + {CustomMessage("They say that hidden in a #box under the lake# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans une #boîte sous le lac# gît #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/en una #caja bajo el lago# yace #[[1]]#. + + hintTextTable[RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = HintText(CustomMessage("They say that the #locked spider in the Water Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula emprisonnée dans le Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #Skulltula enjaulada del Templo del Agua# otorga #[[1]]#. + {}, + {CustomMessage("They say that the #locked spider under the lake# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée emprisonnée sous le lac# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/la #Skulltula enjaulada bajo el lago# otorga #[[1]]#. + + hintTextTable[RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = HintText(CustomMessage("They say that a spider behind a #gate in the Water Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une barrière dans le Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una Skulltula tras una #valla del Templo del Agua# #[[1]]#. + {}, + {CustomMessage("They say that a spider behind a #gate under the lake# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée derrière une barrière sous le lac# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una Skulltula tras una #valla bajo el lago# otorga #[[1]]#. + + hintTextTable[RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = HintText(CustomMessage("They say that those who seek #sunken silver rupees# will find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, ceux qui pêchent les #joyaux argentés# trouveront #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/aquellos que busquen las #rupias plateadas sumergidas# encontrarán + + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = HintText(CustomMessage("They say that those who seek #sunken silver rupees# will find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, ceux qui pêchent les #joyaux argentés# trouveront #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/aquellos que busquen las #rupias plateadas sumergidas# encontrarán #[[1]]#. + + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = HintText(CustomMessage("They say that the final prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la récompense ultime de #l'épreuve des voleurs# est #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/la recompensa final de la #instrucción de las bandida# brinda #[[1]]#. + + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = HintText(CustomMessage("They say that the final prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la récompense ultime de #l'épreuve des voleurs# est #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/el premio final de la #instrucción de las bandidas# brinda #[[1]]#. + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = HintText(CustomMessage("They say that #Dead Hand in the well# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Poigneur dans le Puits# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #Mano Muerta del pozo# concede #[[1]]#. + {}, + {CustomMessage("They say that the well's #grasping ghoul# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #terreur du Puits# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/en las #profundidades del pozo# se esconde #[[1]]#. + CustomMessage("They say that a #nether dweller in the well# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #spectre qui réside dans le Puits# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #temido morador del pozo# concede #[[1]]#. + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that #Dead Hand in the well# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Poigneur dans le Puits# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #Mano Muerta del pozo# concede #[[1]]#. + {}, + {CustomMessage("They say that the well's #grasping ghoul# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #terreur du Puits# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/en las #profundidades del pozo# se esconde #[[1]]#. + CustomMessage("They say that a #nether dweller in the well# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #spectre qui réside dans le Puits# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #temido morador del pozo# concede #[[1]]#. + + hintTextTable[RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = HintText(CustomMessage("They say that upon the #Colossus's right hand# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur la #main droite du colosse# repose #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/en la #mano derecha del Coloso# yace #[[1]]#. + {}, + {CustomMessage("They say that the treasure #sought by Nabooru# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le trésor que #recherche Nabooru# est #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/el #ansiado tesoro de Nabooru# brinda #[[1]]#. + + hintTextTable[RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = HintText(CustomMessage("They say that upon the #Colossus's left hand# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur la #main gauche du colosse# repose #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/en la #mano izquierda del Coloso# yace #[[1]]#. + + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = HintText(CustomMessage("They say that a #temporal paradox in the Spirit Temple# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #paradoxe temporel dans le Temple de l'Esprit# révèle #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #paradoja temporal del Coloso# conduce a #[[1]]#. + {}, + {CustomMessage("They say that a #temporal paradox in the Colossus# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #paradoxe temporel dans le colosse# révèle #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #paradoja temporal del Coloso# conduce a #[[1]]#. + + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = HintText(CustomMessage("They say that a #symphony in the Spirit Temple# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #cinq chansons du Temple de l'Esprit# révèlent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/una #sinfonía del Coloso# conduce a #[[1]]#. + {}, + {CustomMessage("They say that a #symphony in the Colossus# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #symphonie du colosse# révèle #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/una #sinfonía del Coloso# conduce a #[[1]]#. + + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = HintText(CustomMessage("They say that a #spider's symphony in the Spirit Temple# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie de la Skulltula du Temple de l'Esprit# révèle #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/la #Skulltula de la sinfonía del Coloso# otorga #[[1]]#. + {}, + {CustomMessage("They say that a #spider's symphony in the Colossus# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie de l'araignée du colosse# révèle #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/la #Skulltula de la sinfonía del Coloso# otorga #[[1]]#. + + hintTextTable[RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = HintText(CustomMessage("They say that shadows in an #invisible maze# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les ombres dans le #labyrinthe invisible# protègent #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/las sombras del #laberinto misterioso# esconden #[[1]]#. + + hintTextTable[RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = HintText(CustomMessage("They say that shadows in an #invisible maze# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les ombres dans le #labyrinthe invisible# protègent #[[1]]#.", {QM_RED, QM_GREEN})), + // /*spanish*/las sombras del #laberinto invisible# esconden #[[1]]#. /*-------------------------- | ENTRANCE HINT TEXT | ---------------------------*/ - hintTable[RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "lifting a #rock in the desert# reveals", /*french*/ "soulever une #roche dans le désert# révèle", - /*spanish*/ "levantar una #roca del desierto# revela" }, - }); + hintTextTable[RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO] = HintText(CustomMessage("They say that lifting a #rock in the desert# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, soulever une #roche dans le désert# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/levantar una #roca del desierto# revela #[[1]]#. - hintTable[RHT_GV_GROTTO_LEDGE_TO_GV_OCTOROK_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a rock on #a ledge in the valley# hides", /*french*/ "soulever une #roche dans la vallée# révèle", - /*spanish*/ "levantar una #roca al borde del valle# esconde" }, - }); + hintTextTable[RHT_GV_GROTTO_LEDGE_TO_GV_OCTOROK_GROTTO] = HintText(CustomMessage("They say that a rock on #a ledge in the valley# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, soulever une #roche dans la vallée# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/levantar una #roca al borde del valle# esconde #[[1]]#. - hintTable[RHT_GC_GROTTO_PLATFORM_TO_GC_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a #pool of lava# in Goron City blocks the way to", - /*french*/ "l'#étang de lave# dans le village Goron renferme", - /*spanish*/ "un #estanque de lava# en la Ciudad Goron bloquea el paso a" }, - }); + hintTextTable[RHT_GC_GROTTO_PLATFORM_TO_GC_GROTTO] = HintText(CustomMessage("They say that a #pool of lava# in Goron City blocks the way to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#étang de lave# dans le village Goron renferme #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/un #estanque de lava# en la Ciudad Goron bloquea el paso a #[[1]]#. - hintTable[RHT_GERUDO_FORTRESS_TO_GF_STORMS_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a #storm within Gerudo's Fortress# reveals", /*french*/ "la #tempête dans la forteresse# révèle", - /*spanish*/ "una #tormenta en la Fortaleza Gerudo# revela" }, - }); - hintTable[RHT_ZORAS_DOMAIN_TO_ZD_STORMS_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a #storm within Zora's Domain# reveals", /*french*/ "la #tempête dans le Domaine Zora# révèle", - /*spanish*/ "una #tormenta en la Región de los Zora# revela" }, - }); + hintTextTable[RHT_GERUDO_FORTRESS_TO_GF_STORMS_GROTTO] = HintText(CustomMessage("They say that a #storm within Gerudo's Fortress# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #tempête dans la forteresse# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #tormenta en la Fortaleza Gerudo# revela #[[1]]#. - hintTable[RHT_HYRULE_CASTLE_GROUNDS_TO_HC_STORMS_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a #storm near the castle# reveals", /*french*/ "la #tempête près du château# révèle", - /*spanish*/ "una #tormenta junto al castillo# revela" }, - }); - hintTable[RHT_GV_FORTRESS_SIDE_TO_GV_STORMS_GROTTO] = HintText::Entrance({ - // obscure text - Text{ "a #storm in the valley# reveals", /*french*/ "la #tempête dans la vallée# révèle", - /*spanish*/ "una #tormenta en el valle# revela" }, - }); + hintTextTable[RHT_ZORAS_DOMAIN_TO_ZD_STORMS_GROTTO] = HintText(CustomMessage("They say that a #storm within Zora's Domain# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #tempête dans le Domaine Zora# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #tormenta en la Región de los Zora# revela #[[1]]#. - hintTable[RHT_DESERT_COLOSSUS_TO_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = HintText::Entrance({ - // obscure text - Text{ "a #fractured desert wall# hides", /*french*/ "le #mur fragile du désert# cache", - /*spanish*/ "una #agrietada pared del desierto# esconde" }, - }); - hintTable[RHT_GANONS_CASTLE_GROUNDS_TO_OGC_GREAT_FAIRY_FOUNTAIN] = HintText::Entrance({ - // obscure text - Text{ "a #heavy pillar# outside the castle obstructs", /*french*/ "le #rocher fragile près du château# cache", - /*spanish*/ "una #pesada columna# fuera del castillo obstruye" }, - }); + hintTextTable[RHT_HYRULE_CASTLE_GROUNDS_TO_HC_STORMS_GROTTO] = HintText(CustomMessage("They say that a #storm near the castle# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #tempête près du château# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #tormenta junto al castillo# revela #[[1]]#. - hintTable[RHT_ZORAS_FOUNTAIN_TO_ZF_GREAT_FAIRY_FOUNTAIN] = HintText::Entrance({ - // obscure text - Text{ "a #fountain wall# hides", /*french*/ "le #mur fragile du réservoir# cache", - /*spanish*/ "una #pared de la fuente# esconde" }, - }); + hintTextTable[RHT_GV_FORTRESS_SIDE_TO_GV_STORMS_GROTTO] = HintText(CustomMessage("They say that a #storm in the valley# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #tempête dans la vallée# révèle #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #tormenta en el valle# revela #[[1]]#. - hintTable[RHT_GV_FORTRESS_SIDE_TO_GV_CARPENTER_TENT] = HintText::Entrance({ - // obscure text - Text{ "a #tent in the valley# covers", /*french*/ "la #tente dans la vallée# recouvre", - /*spanish*/ "una #tienda de campaña del valle# cubre" }, - }); + hintTextTable[RHT_DESERT_COLOSSUS_TO_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("They say that a #fractured desert wall# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile du désert# cache #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #agrietada pared del desierto# esconde #[[1]]#. - hintTable[RHT_GRAVEYARD_WARP_PAD_REGION_TO_SHADOW_TEMPLE_ENTRYWAY] = HintText::Entrance({ - // obscure text - Text{ "at the #back of the Graveyard#, there is", /*french*/ "#derrière le Cimetière# gît", - /*spanish*/ "en la #parte trasera del cementerio# se halla" }, - }); + hintTextTable[RHT_GANONS_CASTLE_GROUNDS_TO_OGC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("They say that a #heavy pillar# outside the castle obstructs #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #rocher fragile près du château# cache #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #pesada columna# fuera del castillo obstruye #[[1]]#. - hintTable[RHT_LAKE_HYLIA_TO_WATER_TEMPLE_LOBBY] = HintText::Entrance({ - // obscure text - Text{ "deep #under a vast lake#, one can find", /*french*/ "#sous le lac# gît", - /*spanish*/ "en las #profundidades de un lago inmenso# se halla" }, - }); - hintTable[RHT_GERUDO_FORTRESS_TO_GERUDO_TRAINING_GROUNDS_LOBBY] = HintText::Entrance({ - // obscure text - Text{ "paying a #fee to the Gerudos# grants access to", - /*french*/ "l'#entrée payante des Gerudo# donne accès à", - /*spanish*/ "pagarle una #tasa a las gerudo# da acceso a" }, - }); + hintTextTable[RHT_ZORAS_FOUNTAIN_TO_ZF_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("They say that a #fountain wall# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile du réservoir# cache #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #pared de la fuente# esconde #[[1]]#. - hintTable[RHT_ZORAS_FOUNTAIN_TO_JABU_JABUS_BELLY_BEGINNING] = HintText::Entrance({ - // obscure text - Text{ "inside #Jabu-Jabu#, one can find", /*french*/ "#dans Jabu-Jabu# se trouve", - /*spanish*/ "dentro de #Jabu-Jabu# se halla" }, - }); + hintTextTable[RHT_GV_FORTRESS_SIDE_TO_GV_CARPENTER_TENT] = HintText(CustomMessage("They say that a #tent in the valley# covers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #tente dans la vallée# recouvre #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/una #tienda de campaña del valle# cubre #[[1]]#. - hintTable[RHT_KAKARIKO_VILLAGE_TO_BOTTOM_OF_THE_WELL] = HintText::Entrance({ - // obscure text - Text{ "a #village well# leads to", /*french*/ "dans le fond du #Puits du village# gît", - /*spanish*/ "el #pozo de un pueblo# conduce a" }, - }); + hintTextTable[RHT_GRAVEYARD_WARP_PAD_REGION_TO_SHADOW_TEMPLE_ENTRYWAY] = HintText(CustomMessage("They say that at the #back of the Graveyard#, there is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière le Cimetière# gît #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/en la #parte trasera del cementerio# se halla #[[1]]#. + + + hintTextTable[RHT_LAKE_HYLIA_TO_WATER_TEMPLE_LOBBY] = HintText(CustomMessage("They say that deep #under a vast lake#, one can find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #sous le lac# gît #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/en las #profundidades de un lago inmenso# se halla #[[1]]#. + + + hintTextTable[RHT_GERUDO_FORTRESS_TO_GERUDO_TRAINING_GROUNDS_LOBBY] = HintText(CustomMessage("They say that paying a #fee to the Gerudos# grants access to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#entrée payante des Gerudo# donne accès à #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/pagarle una #tasa a las gerudo# da acceso a #[[1]]#. + + hintTextTable[RHT_ZORAS_FOUNTAIN_TO_JABU_JABUS_BELLY_BEGINNING] = HintText(CustomMessage("They say that inside #Jabu-Jabu#, one can find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans Jabu-Jabu# se trouve #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/dentro de #Jabu-Jabu# se halla #[[1]]#. + + hintTextTable[RHT_KAKARIKO_VILLAGE_TO_BOTTOM_OF_THE_WELL] = HintText(CustomMessage("They say that a #village well# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans le fond du #Puits du village# gît #[[1]]#.", {QM_RED, QM_BLUE})), + // /*spanish*/el #pozo de un pueblo# conduce a #[[1]]#. /*-------------------------- | EXIT HINT TEXT | ---------------------------*/ - // maybe make a new type for this? I'm not sure if it really matters - hintTable[RHT_LINKS_POCKET] = HintText::Exclude({ - // obscure text - Text{ "Link's Pocket", /*french*/ "les Poches de @", /*spanish*/ "el bolsillo de @" }, - }); + hintTextTable[RHT_LINKS_POCKET] = HintText(CustomMessage("Link's Pocket", + /*german*/ "", + /*french*/ "les Poches de @")); + // /*spanish*/el bolsillo de @ - hintTable[RHT_KOKIRI_FOREST] = HintText::Exclude({ - // obscure text - Text{ "Kokiri Forest", /*french*/ "la Forêt Kokiri", /*spanish*/ "el Bosque Kokiri" }, - }); + hintTextTable[RHT_KOKIRI_FOREST] = HintText(CustomMessage("Kokiri Forest", + /*german*/ "", + /*french*/ "la Forêt Kokiri")); + // /*spanish*/el Bosque Kokiri - hintTable[RHT_THE_LOST_WOODS] = HintText::Exclude({ - // obscure text - Text{ "the Lost Woods", /*french*/ "les Bois Perdus", /*spanish*/ "el Bosque Perdido" }, - }); + hintTextTable[RHT_THE_LOST_WOODS] = HintText(CustomMessage("the Lost Woods", + /*german*/ "", + /*french*/ "les Bois Perdus")); + // /*spanish*/el Bosque Perdido + hintTextTable[RHT_SACRED_FOREST_MEADOW] = HintText(CustomMessage("Sacred Forest Meadow", + /*german*/ "", + /*french*/ "le Bosquet Sacré")); + // /*spanish*/la pradera sagrada del bosque - hintTable[RHT_SACRED_FOREST_MEADOW] = HintText::Exclude({ - // obscure text - Text{ "Sacred Forest Meadow", /*french*/ "le Bosquet Sacré", /*spanish*/ "la pradera sagrada del bosque" }, - }); + hintTextTable[RHT_HYRULE_FIELD] = HintText(CustomMessage("Hyrule Field", + /*german*/ "", + /*french*/ "la Plaine d'Hyrule")); + // /*spanish*/la Llanura de Hyrule - hintTable[RHT_HYRULE_FIELD] = HintText::Exclude({ - // obscure text - Text{ "Hyrule Field", /*french*/ "la Plaine d'Hyrule", /*spanish*/ "la Llanura de Hyrule" }, - }); + hintTextTable[RHT_LAKE_HYLIA] = HintText(CustomMessage("Lake Hylia", + /*german*/ "", + /*french*/ "le Lac Hylia")); + // /*spanish*/el Lago Hylia - hintTable[RHT_LAKE_HYLIA] = HintText::Exclude({ - // obscure text - Text{ "Lake Hylia", /*french*/ "le Lac Hylia", /*spanish*/ "el Lago Hylia" }, - }); + hintTextTable[RHT_GERUDO_VALLEY] = HintText(CustomMessage("Gerudo Valley", + /*german*/ "", + /*french*/ "la Vallée Gerudo")); + // /*spanish*/el Valle Gerudo - hintTable[RHT_GERUDO_VALLEY] = HintText::Exclude({ - // obscure text - Text{ "Gerudo Valley", /*french*/ "la Vallée Gerudo", /*spanish*/ "el Valle Gerudo" }, - }); + hintTextTable[RHT_GERUDO_FORTRESS] = HintText(CustomMessage("Gerudo's Fortress", + /*german*/ "", + /*french*/ "le Repaire des Voleurs")); + // /*spanish*/la Fortaleza Gerudo - hintTable[RHT_GERUDO_FORTRESS] = HintText::Exclude({ - // obscure text - Text{ "Gerudo's Fortress", /*french*/ "le Repaire des Voleurs", /*spanish*/ "la Fortaleza Gerudo" }, - }); + hintTextTable[RHT_HAUNTED_WASTELAND] = HintText(CustomMessage("Haunted Wasteland", + /*german*/ "", + /*french*/ "le Désert Hanté")); + // /*spanish*/el desierto encantado - hintTable[RHT_HAUNTED_WASTELAND] = HintText::Exclude({ - // obscure text - Text{ "Haunted Wasteland", /*french*/ "le Désert Hanté", /*spanish*/ "el desierto encantado" }, - }); + hintTextTable[RHT_DESERT_COLOSSUS] = HintText(CustomMessage("Desert Colossus", + /*german*/ "", + /*french*/ "le Colosse du Désert")); + // /*spanish*/el Coloso del Desierto - hintTable[RHT_DESERT_COLOSSUS] = HintText::Exclude({ - // obscure text - Text{ "Desert Colossus", /*french*/ "le Colosse du Désert", /*spanish*/ "el Coloso del Desierto" }, - }); + hintTextTable[RHT_THE_MARKET] = HintText(CustomMessage("the Market", + /*german*/ "", + /*french*/ "la Place du Marché")); + // /*spanish*/la plaza del mercado - hintTable[RHT_THE_MARKET] = HintText::Exclude({ - // obscure text - Text{ "the Market", /*french*/ "la Place du Marché", /*spanish*/ "la plaza del mercado" }, - }); + hintTextTable[RHT_TEMPLE_OF_TIME] = HintText(CustomMessage("Temple of Time", + /*german*/ "", + /*french*/ "le Temple du Temps")); + // /*spanish*/el Templo del Tiempo + hintTextTable[RHT_CASTLE_GROUNDS] = HintText(CustomMessage("the Castle Grounds", + /*german*/ "", + /*french*/ "le Château d'Hyrule")); + // /*spanish*/ + hintTextTable[RHT_HYRULE_CASTLE] = HintText(CustomMessage("Hyrule Castle", + /*german*/ "", + /*french*/ "le Château d'Hyrule")); + // /*spanish*/el Castillo de Hyrule - hintTable[RHT_TEMPLE_OF_TIME] = HintText::Exclude({ - // obscure text - Text{ "Temple of Time", /*french*/ "le Temple du Temps", /*spanish*/ "el Templo del Tiempo" }, - }); + hintTextTable[RHT_OUTSIDE_GANONS_CASTLE] = HintText(CustomMessage("outside Ganon's Castle", + /*german*/ "", + /*french*/ "les alentours du Château de Ganon")); + // /*spanish*/el exterior del Castillo de Ganon - hintTable[RHT_CASTLE_GROUNDS] = HintText::Exclude({ - // obscure text - Text{ "the Castle Grounds", /*french*/ "le Château d'Hyrule", /*spanish*/ "" }, - }); + hintTextTable[RHT_CASTLE_GROUNDS] = HintText(CustomMessage("the Castle Grounds", + /*german*/ "", + /*french*/ "le Château d'Hyrule")); + // /*spanish*/ + hintTextTable[RHT_KAKARIKO_VILLAGE] = HintText(CustomMessage("Kakariko Village", + /*german*/ "", + /*french*/ "le Village Cocorico")); + // /*spanish*/Kakariko - hintTable[RHT_HYRULE_CASTLE] = HintText::Exclude({ - // obscure text - Text{ "Hyrule Castle", /*french*/ "le Château d'Hyrule", /*spanish*/ "el Castillo de Hyrule" }, - }); + hintTextTable[RHT_THE_GRAVEYARD] = HintText(CustomMessage("the Graveyard", + /*german*/ "", + /*french*/ "le Cimetière")); + // /*spanish*/el cementerio - hintTable[RHT_OUTSIDE_GANONS_CASTLE] = HintText::Exclude({ - // obscure text - Text{ "outside Ganon's Castle", /*french*/ "les alentours du Château de Ganon", - /*spanish*/ "el exterior del Castillo de Ganon" }, - }); + hintTextTable[RHT_DEATH_MOUNTAIN_TRAIL] = HintText(CustomMessage("Death Mountain Trail", + /*german*/ "", + /*french*/ "le Chemin du Péril")); + // /*spanish*/el sendero de la Montaña de la Muerte - hintTable[RHT_CASTLE_GROUNDS] = HintText::Exclude({ - // obscure text - Text{ "the Castle Grounds", /*french*/ "le Château d'Hyrule", /*spanish*/ "" }, - }); + hintTextTable[RHT_GORON_CITY] = HintText(CustomMessage("Goron City", + /*german*/ "", + /*french*/ "le Village Goron")); + // /*spanish*/la Ciudad Goron - hintTable[RHT_KAKARIKO_VILLAGE] = HintText::Exclude({ - // obscure text - Text{ "Kakariko Village", /*french*/ "le Village Cocorico", /*spanish*/ "Kakariko" }, - }); + hintTextTable[RHT_DEATH_MOUNTAIN_CRATER] = HintText(CustomMessage("Death Mountain Crater", + /*german*/ "", + /*french*/ "le Cratère du Péril")); + // /*spanish*/el cráter de la Montaña de la Muerte - hintTable[RHT_THE_GRAVEYARD] = HintText::Exclude({ - // obscure text - Text{ "the Graveyard", /*french*/ "le Cimetière", /*spanish*/ "el cementerio" }, - }); + hintTextTable[RHT_ZORAS_RIVER] = HintText(CustomMessage("Zora's River", + /*german*/ "", + /*french*/ "la Rivière Zora")); + // /*spanish*/el Río Zora - hintTable[RHT_DEATH_MOUNTAIN_TRAIL] = HintText::Exclude({ - // obscure text - Text{ "Death Mountain Trail", /*french*/ "le Chemin du Péril", - /*spanish*/ "el sendero de la Montaña de la Muerte" }, - }); + hintTextTable[RHT_ZORAS_DOMAIN] = HintText(CustomMessage("Zora's Domain", + /*german*/ "", + /*french*/ "le Domaine Zora")); + // /*spanish*/la Región de los Zora - hintTable[RHT_GORON_CITY] = HintText::Exclude({ - // obscure text - Text{ "Goron City", /*french*/ "le Village Goron", /*spanish*/ "la Ciudad Goron" }, - }); - - hintTable[RHT_DEATH_MOUNTAIN_CRATER] = HintText::Exclude({ - // obscure text - Text{ "Death Mountain Crater", /*french*/ "le Cratère du Péril", - /*spanish*/ "el cráter de la Montaña de la Muerte" }, - }); - - hintTable[RHT_ZORAS_RIVER] = HintText::Exclude({ - // obscure text - Text{ "Zora's River", /*french*/ "la Rivière Zora", /*spanish*/ "el Río Zora" }, - }); - - hintTable[RHT_ZORAS_DOMAIN] = HintText::Exclude({ - // obscure text - Text{ "Zora's Domain", /*french*/ "le Domaine Zora", /*spanish*/ "la Región de los Zora" }, - }); - - hintTable[RHT_ZORAS_FOUNTAIN] = HintText::Exclude({ - // obscure text - Text{ "Zora's Fountain", /*french*/ "la Fontaine Zora", /*spanish*/ "la Fuente Zora" }, - }); - - hintTable[RHT_LON_LON_RANCH] = HintText::Exclude({ - // obscure text - Text{ "Lon Lon Ranch", /*french*/ "le Ranch Lon Lon", /*spanish*/ "el Rancho Lon Lon" }, - }); + hintTextTable[RHT_ZORAS_FOUNTAIN] = HintText(CustomMessage("Zora's Fountain", + /*german*/ "", + /*french*/ "la Fontaine Zora")); + // /*spanish*/la Fuente Zora + hintTextTable[RHT_LON_LON_RANCH] = HintText(CustomMessage("Lon Lon Ranch", + /*german*/ "", + /*french*/ "le Ranch Lon Lon")); + // /*spanish*/el Rancho Lon Lon /*-------------------------- | REGION HINT TEXT | ---------------------------*/ - hintTable[RHT_KF_LINKS_HOUSE] = HintText::Region({ - // obscure text - Text{ "Link's House", /*french*/ "la #maison de @#", /*spanish*/ "la casa de @" }, - }); - - // hintTable[RHT_TOT_MAIN] = HintText::Region({ - // //obscure text - // Text{"the #Temple of Time#", /*french*/"le #Temple du Temps#", /*spanish*/"el Templo del - // Tiempo"}, - // }); - - hintTable[RHT_KF_MIDOS_HOUSE] = HintText::Region({ - // obscure text - Text{ "Mido's house", /*french*/ "la Cabane du Grand Mido", /*spanish*/ "la casa de Mido" }, - }); - - hintTable[RHT_KF_SARIAS_HOUSE] = HintText::Region({ - // obscure text - Text{ "Saria's House", /*french*/ "la Cabane de Saria", /*spanish*/ "la casa de Saria" }, - }); - - hintTable[RHT_KF_HOUSE_OF_TWINS] = HintText::Region({ - // obscure text - Text{ "the #House of Twins#", /*french*/ "la Cabane des Jumelles", /*spanish*/ "la casa de las gemelas" }, - }); - - hintTable[RHT_KF_KNOW_IT_ALL_HOUSE] = HintText::Region({ - // obscure text - Text{ "Know-It-All Brothers' House", /*french*/ "la Cabane des frères Je-Sais-Tout", - /*spanish*/ "la casa de los hermanos Sabelotodo" }, - }); - - hintTable[RHT_KF_KOKIRI_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Kokiri Shop#", /*french*/ "le #Magasin Kokiri#", /*spanish*/ "la tienda kokiri" }, - }); - - hintTable[RHT_LH_LAB] = HintText::Region({ - // obscure text - Text{ "the #Lakeside Laboratory#", /*french*/ "le #Laboratoire du Lac#", - /*spanish*/ "el laboratorio del lago" }, - }); - - hintTable[RHT_LH_FISHING_HOLE] = HintText::Region({ - // obscure text - Text{ "the #Fishing Pond#", /*french*/ "l'#Étang#", /*spanish*/ "el estanque" }, - }); - - hintTable[RHT_GV_CARPENTER_TENT] = HintText::Region({ - // obscure text - Text{ "the #Carpenters' tent#", /*french*/ "la #Tente des charpentiers#", - /*spanish*/ "la #tienda de campaña de los carpinteros#" }, - }); - - hintTable[RHT_MARKET_GUARD_HOUSE] = HintText::Region({ - // obscure text - Text{ "the #Guard House#", /*french*/ "le #poste de garde#", /*spanish*/ "la caseta de guardia" }, - }); - - hintTable[RHT_MARKET_MASK_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Happy Mask Shop#", /*french*/ "la #Foire Aux Masques#", - /*spanish*/ "la tienda de La Máscara Feliz" }, - }); - - hintTable[RHT_MARKET_BOMBCHU_BOWLING] = HintText::Region({ - // obscure text - Text{ "the #Bombchu Bowling Alley#", /*french*/ "le #Bowling Teigneux#", /*spanish*/ "la Bolera Bombchu" }, - }); - - hintTable[RHT_MARKET_POTION_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Market Potion Shop#", /*french*/ "l'#apothicaire de la Place du Marché#", - /*spanish*/ "la tienda de pociones de la plaza del mercado" }, - }); - - hintTable[RHT_MARKET_TREASURE_CHEST_GAME] = HintText::Region({ - // obscure text - Text{ "the #Treasure Chest Shop#", /*french*/ "la #Chasse-aux-Trésors#", /*spanish*/ "el Cofre del Tesoro" }, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Bombchu Shop#", /*french*/ "le #Magasin de Missiles#", /*spanish*/ "la Tienda Bombchu" }, - }); - - hintTable[RHT_MARKET_MAN_IN_GREEN_HOUSE] = HintText::Region({ - // obscure text - Text{ "Man in Green's House", /*french*/ "la #Maison de l'Homme en Vert#", - /*spanish*/ "la casa del hombre de verde" }, - }); - - hintTable[RHT_KAK_WINDMILL] = HintText::Region({ - // obscure text - Text{ "the #Windmill#", /*french*/ "le #Moulin#", /*spanish*/ "el #molino#" }, - }); - - hintTable[RHT_KAK_CARPENTER_BOSS_HOUSE] = HintText::Region({ - // obscure text - Text{ "the #Carpenters' Boss House#", /*french*/ "la #Maison du Chef des ouvriers#", - /*spanish*/ "la casa del capataz de los carpinteros" }, - }); - - hintTable[RHT_KAK_HOUSE_OF_SKULLTULA] = HintText::Region({ - // obscure text - Text{ "the #House of Skulltula#", /*french*/ "la #Maison des Skulltulas#", - /*spanish*/ "la casa de las Skulltulas" }, - }); - - hintTable[RHT_KAK_IMPAS_HOUSE] = HintText::Region({ - // obscure text - Text{ "Impa's House", /*french*/ "la #Maison d'Impa#", /*spanish*/ "la casa de Impa" }, - }); - - hintTable[RHT_KAK_IMPAS_HOUSE_BACK] = HintText::Region({ - // obscure text - Text{ "Impa's cow cage", /*french*/ "la #cage à vache d'Impa#", /*spanish*/ "la jaula de la vaca de Impa" }, - }); - - hintTable[RHT_KAK_ODD_POTION_BUILDING] = HintText::Region({ - // obscure text - Text{ "Granny's Potion Shop", /*french*/ "la #maison bleue de Cocorico#", - /*spanish*/ "la tienda de pociones de la abuela" }, - }); - - hintTable[RHT_GRAVEYARD_DAMPES_HOUSE] = HintText::Region({ - // obscure text - Text{ "Dampé's Hut", /*french*/ "la #Cabane du Fossoyeur#", /*spanish*/ "la cabaña de Dampé" }, - }); - - hintTable[RHT_GC_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Goron Shop#", /*french*/ "la #Boutique Goron#", /*spanish*/ "la #tienda goron#" }, - }); - - hintTable[RHT_ZD_SHOP] = HintText::Region({ - // obscure text - Text{ "the #Zora Shop#", /*french*/ "la #Boutique Zora#", /*spanish*/ "la #tienda zora#" }, - }); - - hintTable[RHT_LLR_TALONS_HOUSE] = HintText::Region({ - // obscure text - Text{ "Talon's House", /*french*/ "la #Maison de Talon#", /*spanish*/ "la casa de Talon" }, - }); - - hintTable[RHT_LLR_STABLES] = HintText::Region({ - // obscure text - Text{ "a #stable#", /*french*/ "l'#Étable#", /*spanish*/ "el establo" }, - }); - - hintTable[RHT_LLR_TOWER] = HintText::Region({ - // obscure text - Text{ "the #Lon Lon Tower#", /*french*/ "le #silo du Ranch Lon Lon#", /*spanish*/ "la torre Lon Lon" }, - }); - - hintTable[RHT_MARKET_BAZAAR] = HintText::Region({ - // obscure text - Text{ "the #Market Bazaar#", /*french*/ "le #Bazar de la Place du Marché#", - /*spanish*/ "el bazar de la plaza del mercado" }, - }); - - hintTable[RHT_MARKET_SHOOTING_GALLERY] = HintText::Region({ - // obscure text - Text{ "a #Slingshot Shooting Gallery#", /*french*/ "le #Jeu d'Adresse de la Place du Marché#", - /*spanish*/ "el Tiro al Blanco con tirachinas" }, - }); - - hintTable[RHT_KAK_BAZAAR] = HintText::Region({ - // obscure text - Text{ "the #Kakariko Bazaar#", /*french*/ "le #Bazar de Cocorico#", /*spanish*/ "el bazar de Kakariko" }, - }); - - hintTable[RHT_KAK_POTION_SHOP_FRONT] = HintText::Region({ - // obscure text - Text{ "the #Kakariko Potion Shop#", /*french*/ "l'#apothicaire de Cocorico#", - /*spanish*/ "la tienda de pociones de Kakariko" }, - }); - - hintTable[RHT_KAK_POTION_SHOP_BACK] = HintText::Region({ - // obscure text - Text{ "the #Kakariko Potion Shop#", /*french*/ "l'#apothicaire de Cocorico#", - /*spanish*/ "la tienda de pociones de Kakariko" }, - }); - - hintTable[RHT_KAK_SHOOTING_GALLERY] = HintText::Region({ - // obscure text - Text{ "a #Bow Shooting Gallery#", /*french*/ "le #jeu d'adresse de Cocorico#", - /*spanish*/ "el Tiro al Blanco con arco" }, - }); - - hintTable[RHT_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_HC_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_OGC_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_DMC_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_DMT_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_ZF_GREAT_FAIRY_FOUNTAIN] = HintText::Region({ - // obscure text - Text{ "a #Great Fairy Fountain#", /*french*/ "une #Fontaine Royale des Fées#", - /*spanish*/ "una fuente de la Gran Hada" }, - }); - - hintTable[RHT_GRAVEYARD_SHIELD_GRAVE] = HintText::Region({ - // obscure text - Text{ "a #grave with a free chest#", /*french*/ "le #tombeau avec un trésor#", - /*spanish*/ "la #tumba con un cofre#" }, - }); - - hintTable[RHT_GRAVEYARD_HEART_PIECE_GRAVE] = HintText::Region({ - // obscure text - Text{ "a chest spawned by #Sun's Song#", /*french*/ "un #coffre apparaît avec le Chant du Soleil#", - /*spanish*/ "la #tumba de la Canción del Sol#" }, - }); - - hintTable[RHT_GRAVEYARD_COMPOSERS_GRAVE] = HintText::Region({ - // obscure text - Text{ "the #Composers' Grave#", /*french*/ "la #Tombe royale#", /*spanish*/ "el #Panteón Real#" }, - }); - - hintTable[RHT_GRAVEYARD_DAMPES_GRAVE] = HintText::Region({ - // obscure text - Text{ "Dampé's Grave", /*french*/ "la #Tombe d'Igor#", /*spanish*/ "la #tumba de Dampé#" }, - }); - - hintTable[RHT_DMT_COW_GROTTO] = HintText::Region({ - // obscure text - Text{ "a solitary #Cow#", /*french*/ "la #grotte avec une vache#", /*spanish*/ "una #vaca# solitaria" }, - }); - - hintTable[RHT_HC_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a sandy grotto with #fragile walls#", /*french*/ "la #grotte avec des murs fragiles#", - /*spanish*/ "la arenosa gruta de #frágiles paredes#" }, - }); - - hintTable[RHT_HF_TEKTITE_GROTTO] = HintText::Region({ - // obscure text - Text{ "a pool guarded by a #Tektite#", /*french*/ "l'#étang sous-terrain avec un Araknon#", - /*spanish*/ "un charco custodiado por un #Tektite#" }, - }); - - hintTable[RHT_HF_NEAR_KAK_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #Big Skulltula# guarding a Gold one", /*french*/ "la #grotte d'araignées#", - /*spanish*/ "una #gran Skulltula# custodiando una dorada" }, - }); - - hintTable[RHT_HF_COW_GROTTO] = HintText::Region({ - // obscure text - Text{ "a grotto full of #spider webs#", /*french*/ "la #grotte couverte de toiles d'araignées#", - /*spanish*/ "una gruta llena de #telarañas#" }, - }); - - hintTable[RHT_KAK_REDEAD_GROTTO] = HintText::Region({ - // obscure text - Text{ "#ReDeads# guarding a chest", /*french*/ "le tombeau de #deux morts#", - /*spanish*/ "los #ReDeads# que custodian un cofre" }, - }); - - hintTable[RHT_SFM_WOLFOS_GROTTO] = HintText::Region({ - // obscure text - Text{ "#Wolfos# guarding a chest", /*french*/ "la #grotte iridescente#", - /*spanish*/ "los #Wolfos# que custodian un cofre" }, - }); - - hintTable[RHT_GV_OCTOROK_GROTTO] = HintText::Region({ - // obscure text - Text{ "an #Octorok# guarding a rich pool", /*french*/ "un #étang sous-terrain avec un Octorok#", - /*spanish*/ "un #Octorok# que custodia un lujoso charco" }, - }); - - hintTable[RHT_DEKU_THEATER] = HintText::Region({ - // obscure text - Text{ "the #Lost Woods Stage#", /*french*/ "le #théâtre sylvestre#", - /*spanish*/ "el #escenario del Bosque Perdido#" }, - }); - - hintTable[RHT_ZR_OPEN_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_DMC_UPPER_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_DMT_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_KAK_OPEN_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_HF_NEAR_MARKET_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_HF_OPEN_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_HF_SOUTHEAST_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_KF_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_LW_NEAR_SHORTCUTS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #generic grotto#", /*french*/ "une #grotte avec un trésor#", /*spanish*/ "una #cueva genérica#" }, - }); - - hintTable[RHT_HF_INSIDE_FENCE_GROTTO] = HintText::Region({ - // obscure text - Text{ "a #single Upgrade Deku Scrub#", /*french*/ "une #grotte avec une peste Mojo#", - /*spanish*/ "una cueva con un #solitario mercader deku#" }, - }); - - hintTable[RHT_LW_SCRUBS_GROTTO] = HintText::Region({ - // obscure text - Text{ "#2 Deku Scrubs# including an Upgrade one", /*french*/ "une #grotte avec deux pestes Mojo#", - /*spanish*/ "una cueva con #dos mercaderes deku#" }, - }); - - hintTable[RHT_COLOSSUS_GROTTO] = HintText::Region({ - // obscure text - Text{ "2 Deku Scrubs", /*french*/ "une #grotte avec deux pestes Mojo#", - /*spanish*/ "una cueva con #dos mercaderes deku#" }, - }); - - hintTable[RHT_ZR_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "2 Deku Scrubs", /*french*/ "une #grotte avec deux pestes Mojo#", - /*spanish*/ "una cueva con #dos mercaderes deku#" }, - }); - - hintTable[RHT_SFM_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "2 Deku Scrubs", /*french*/ "une #grotte avec deux pestes Mojo#", - /*spanish*/ "una cueva con #dos mercaderes deku#" }, - }); - - hintTable[RHT_GV_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "2 Deku Scrubs", /*french*/ "une #grotte avec deux pestes Mojo#", - /*spanish*/ "una cueva con #dos mercaderes deku#" }, - }); - - hintTable[RHT_LH_GROTTO] = HintText::Region({ - // obscure text - Text{ "3 Deku Scrubs", /*french*/ "une #grotte avec trois pestes Mojo#", - /*spanish*/ "una cueva con #tres mercaderes deku#" }, - }); - - hintTable[RHT_DMC_HAMMER_GROTTO] = HintText::Region({ - // obscure text - Text{ "3 Deku Scrubs", /*french*/ "une #grotte avec trois pestes Mojo#", - /*spanish*/ "una cueva con #tres mercaderes deku#" }, - }); - - hintTable[RHT_GC_GROTTO] = HintText::Region({ - // obscure text - Text{ "3 Deku Scrubs", /*french*/ "une #grotte avec trois pestes Mojo#", - /*spanish*/ "una cueva con #tres mercaderes deku#" }, - }); - - hintTable[RHT_LLR_GROTTO] = HintText::Region({ - // obscure text - Text{ "3 Deku Scrubs", /*french*/ "une #grotte avec trois pestes Mojo#", - /*spanish*/ "una cueva con #tres mercaderes deku#" }, - }); - - hintTable[RHT_ZR_FAIRY_GROTTO] = HintText::Region({ - // obscure text - Text{ "a small #Fairy Fountain#", /*french*/ "une #fontaine de fées#", - /*spanish*/ "una pequeña #fuente de hadas#" }, - }); - - hintTable[RHT_HF_FAIRY_GROTTO] = HintText::Region({ - // obscure text - Text{ "a small #Fairy Fountain#", /*french*/ "une #fontaine de fées#", - /*spanish*/ "una pequeña #fuente de hadas#" }, - }); - - hintTable[RHT_SFM_FAIRY_GROTTO] = HintText::Region({ - // obscure text - Text{ "a small #Fairy Fountain#", /*french*/ "une #fontaine de fées#", - /*spanish*/ "una pequeña #fuente de hadas#" }, - }); - - hintTable[RHT_ZD_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a small #Fairy Fountain#", /*french*/ "une #fontaine de fées#", - /*spanish*/ "una pequeña #fuente de hadas#" }, - }); - - hintTable[RHT_GF_STORMS_GROTTO] = HintText::Region({ - // obscure text - Text{ "a small #Fairy Fountain#", /*french*/ "une #fontaine de fées#", - /*spanish*/ "una pequeña #fuente de hadas#" }, - }); + hintTextTable[RHT_KF_LINKS_HOUSE] = HintText(CustomMessage("Link's House", + /*german*/ "", + /*french*/ "la #maison de @#")); + // /*spanish*/la casa de @ + + hintTextTable[RHT_KF_MIDOS_HOUSE] = HintText(CustomMessage("Mido's house", + /*german*/ "", + /*french*/ "la Cabane du Grand Mido")); + // /*spanish*/la casa de Mido + hintTextTable[RHT_KF_SARIAS_HOUSE] = HintText(CustomMessage("Saria's House", + /*german*/ "", + /*french*/ "la Cabane de Saria")); + // /*spanish*/la casa de Saria + + hintTextTable[RHT_KF_HOUSE_OF_TWINS] = HintText(CustomMessage("the #House of Twins#", + /*german*/ "", + /*french*/ "la Cabane des Jumelles")); + // /*spanish*/la casa de las gemelas + + hintTextTable[RHT_KF_KNOW_IT_ALL_HOUSE] = HintText(CustomMessage("Know-It-All Brothers' House", + /*german*/ "", + /*french*/ "la Cabane des frères Je-Sais-Tout")); + // /*spanish*/la casa de los hermanos Sabelotodo + + hintTextTable[RHT_KF_KOKIRI_SHOP] = HintText(CustomMessage("the #Kokiri Shop#", + /*german*/ "", + /*french*/ "le #Magasin Kokiri#")); + // /*spanish*/la tienda kokiri + hintTextTable[RHT_LH_LAB] = HintText(CustomMessage("the #Lakeside Laboratory#", + /*german*/ "", + /*french*/ "le #Laboratoire du Lac#")); + // /*spanish*/el laboratorio del lago + + hintTextTable[RHT_LH_FISHING_HOLE] = HintText(CustomMessage("the #Fishing Pond#", + /*german*/ "", + /*french*/ "l'#Étang#")); + // /*spanish*/el estanque + + hintTextTable[RHT_GV_CARPENTER_TENT] = HintText(CustomMessage("the #Carpenters' tent#", + /*german*/ "", + /*french*/ "la #Tente des charpentiers#")); + // /*spanish*/la #tienda de campaña de los carpinteros# + + hintTextTable[RHT_MARKET_GUARD_HOUSE] = HintText(CustomMessage("the #Guard House#", + /*german*/ "", + /*french*/ "le #poste de garde#")); + // /*spanish*/la caseta de guardia + + hintTextTable[RHT_MARKET_MASK_SHOP] = HintText(CustomMessage("the #Happy Mask Shop#", + /*german*/ "", + /*french*/ "la #Foire Aux Masques#")); + // /*spanish*/la tienda de La Máscara Feliz + + hintTextTable[RHT_MARKET_BOMBCHU_BOWLING] = HintText(CustomMessage("the #Bombchu Bowling Alley#", + /*german*/ "", + /*french*/ "le #Bowling Teigneux#")); + // /*spanish*/la Bolera Bombchu + + hintTextTable[RHT_MARKET_POTION_SHOP] = HintText(CustomMessage("the #Market Potion Shop#", + /*german*/ "", + /*french*/ "l'#apothicaire de la Place du Marché#")); + // /*spanish*/la tienda de pociones de la plaza del mercado + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME] = HintText(CustomMessage("the #Treasure Chest Shop#", + /*german*/ "", + /*french*/ "la #Chasse-aux-Trésors#")); + // /*spanish*/el Cofre del Tesoro + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP] = HintText(CustomMessage("the #Bombchu Shop#", + /*german*/ "", + /*french*/ "le #Magasin de Missiles#")); + // /*spanish*/la Tienda Bombchu + + hintTextTable[RHT_MARKET_MAN_IN_GREEN_HOUSE] = HintText(CustomMessage("Man in Green's House", + /*german*/ "", + /*french*/ "la #Maison de l'Homme en Vert#")); + // /*spanish*/la casa del hombre de verde + + hintTextTable[RHT_KAK_WINDMILL] = HintText(CustomMessage("the #Windmill#", + /*german*/ "", + /*french*/ "le #Moulin#")); + // /*spanish*/el #molino# + + hintTextTable[RHT_KAK_CARPENTER_BOSS_HOUSE] = HintText(CustomMessage("the #Carpenters' Boss House#", + /*german*/ "", + /*french*/ "la #Maison du Chef des ouvriers#")); + // /*spanish*/la casa del capataz de los carpinteros + + hintTextTable[RHT_KAK_HOUSE_OF_SKULLTULA] = HintText(CustomMessage("the #House of Skulltula#", + /*german*/ "", + /*french*/ "la #Maison des Skulltulas#")); + // /*spanish*/la casa de las Skulltulas + + hintTextTable[RHT_KAK_IMPAS_HOUSE] = HintText(CustomMessage("Impa's House", + /*german*/ "", + /*french*/ "la #Maison d'Impa#")); + // /*spanish*/la casa de Impa + + hintTextTable[RHT_KAK_IMPAS_HOUSE_BACK] = HintText(CustomMessage("Impa's cow cage", + /*german*/ "", + /*french*/ "la #cage à vache d'Impa#")); + // /*spanish*/la jaula de la vaca de Impa + + hintTextTable[RHT_KAK_ODD_POTION_BUILDING] = HintText(CustomMessage("Granny's Potion Shop", + /*german*/ "", + /*french*/ "la #maison bleue de Cocorico#")); + // /*spanish*/la tienda de pociones de la abuela + + hintTextTable[RHT_GRAVEYARD_DAMPES_HOUSE] = HintText(CustomMessage("Dampé's Hut", + /*german*/ "", + /*french*/ "la #Cabane du Fossoyeur#")); + // /*spanish*/la cabaña de Dampé + + hintTextTable[RHT_GC_SHOP] = HintText(CustomMessage("the #Goron Shop#", + /*german*/ "", + /*french*/ "la #Boutique Goron#")); + // /*spanish*/la #tienda goron# + + hintTextTable[RHT_ZD_SHOP] = HintText(CustomMessage("the #Zora Shop#", + /*german*/ "", + /*french*/ "la #Boutique Zora#")); + // /*spanish*/la #tienda zora# + + hintTextTable[RHT_LLR_TALONS_HOUSE] = HintText(CustomMessage("Talon's House", + /*german*/ "", + /*french*/ "la #Maison de Talon#")); + // /*spanish*/la casa de Talon + + hintTextTable[RHT_LLR_STABLES] = HintText(CustomMessage("a #stable#", + /*german*/ "", + /*french*/ "l'#Étable#")); + // /*spanish*/el establo + + hintTextTable[RHT_LLR_TOWER] = HintText(CustomMessage("the #Lon Lon Tower#", + /*german*/ "", + /*french*/ "le #silo du Ranch Lon Lon#")); + // /*spanish*/la torre Lon Lon + + hintTextTable[RHT_MARKET_BAZAAR] = HintText(CustomMessage("the #Market Bazaar#", + /*german*/ "", + /*french*/ "le #Bazar de la Place du Marché#")); + // /*spanish*/el bazar de la plaza del mercado + + hintTextTable[RHT_MARKET_SHOOTING_GALLERY] = HintText(CustomMessage("a #Slingshot Shooting Gallery#", + /*german*/ "", + /*french*/ "le #Jeu d'Adresse de la Place du Marché#")); + // /*spanish*/el Tiro al Blanco con tirachinas + + hintTextTable[RHT_KAK_BAZAAR] = HintText(CustomMessage("the #Kakariko Bazaar#", + /*german*/ "", + /*french*/ "le #Bazar de Cocorico#")); + // /*spanish*/el bazar de Kakariko + + hintTextTable[RHT_KAK_POTION_SHOP_FRONT] = HintText(CustomMessage("the #Kakariko Potion Shop#", + /*german*/ "", + /*french*/ "l'#apothicaire de Cocorico#")); + // /*spanish*/la tienda de pociones de Kakariko + + hintTextTable[RHT_KAK_POTION_SHOP_BACK] = HintText(CustomMessage("the #Kakariko Potion Shop#", + /*german*/ "", + /*french*/ "l'#apothicaire de Cocorico#")); + // /*spanish*/la tienda de pociones de Kakariko + + hintTextTable[RHT_KAK_SHOOTING_GALLERY] = HintText(CustomMessage("a #Bow Shooting Gallery#", + /*german*/ "", + /*french*/ "le #jeu d'adresse de Cocorico#")); + // /*spanish*/el Tiro al Blanco con arco + + hintTextTable[RHT_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_HC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_OGC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_DMC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_DMT_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_ZF_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", + /*german*/ "", + /*french*/ "une #Fontaine Royale des Fées#")); + // /*spanish*/una fuente de la Gran Hada + + hintTextTable[RHT_GRAVEYARD_SHIELD_GRAVE] = HintText(CustomMessage("a #grave with a free chest#", + /*german*/ "", + /*french*/ "le #tombeau avec un trésor#")); + // /*spanish*/la #tumba con un cofre# + + hintTextTable[RHT_GRAVEYARD_HEART_PIECE_GRAVE] = HintText(CustomMessage("a chest spawned by #Sun's Song#", + /*german*/ "", + /*french*/ "un #coffre apparaît avec le Chant du Soleil#")); + // /*spanish*/la #tumba de la Canción del Sol# + + hintTextTable[RHT_GRAVEYARD_COMPOSERS_GRAVE] = HintText(CustomMessage("the #Composers' Grave#", + /*german*/ "", + /*french*/ "la #Tombe royale#")); + // /*spanish*/el #Panteón Real# + + hintTextTable[RHT_GRAVEYARD_DAMPES_GRAVE] = HintText(CustomMessage("Dampé's Grave", + /*german*/ "", + /*french*/ "la #Tombe d'Igor#")); + // /*spanish*/la #tumba de Dampé# + + hintTextTable[RHT_DMT_COW_GROTTO] = HintText(CustomMessage("a solitary #Cow#", + /*german*/ "", + /*french*/ "la #grotte avec une vache#")); + // /*spanish*/una #vaca# solitaria + hintTextTable[RHT_HC_STORMS_GROTTO] = HintText(CustomMessage("a sandy grotto with #fragile walls#", + /*german*/ "", + /*french*/ "la #grotte avec des murs fragiles#")); + // /*spanish*/la arenosa gruta de #frágiles paredes# + + hintTextTable[RHT_HF_TEKTITE_GROTTO] = HintText(CustomMessage("a pool guarded by a #Tektite#", + /*german*/ "", + /*french*/ "l'#étang sous-terrain avec un Araknon#")); + // /*spanish*/un charco custodiado por un #Tektite# + + hintTextTable[RHT_HF_NEAR_KAK_GROTTO] = HintText(CustomMessage("a #Big Skulltula# guarding a Gold one", + /*german*/ "", + /*french*/ "la #grotte d'araignées#")); + // /*spanish*/una #gran Skulltula# custodiando una dorada + + hintTextTable[RHT_HF_COW_GROTTO] = HintText(CustomMessage("a grotto full of #spider webs#", + /*german*/ "", + /*french*/ "la #grotte couverte de toiles d'araignées#")); + // /*spanish*/una gruta llena de #telarañas# + + hintTextTable[RHT_KAK_REDEAD_GROTTO] = HintText(CustomMessage("#ReDeads# guarding a chest", + /*german*/ "", + /*french*/ "le tombeau de #deux morts#")); + // /*spanish*/los #ReDeads# que custodian un cofre + + hintTextTable[RHT_SFM_WOLFOS_GROTTO] = HintText(CustomMessage("#Wolfos# guarding a chest", + /*german*/ "", + /*french*/ "la #grotte iridescente#")); + // /*spanish*/los #Wolfos# que custodian un cofre + + hintTextTable[RHT_GV_OCTOROK_GROTTO] = HintText(CustomMessage("an #Octorok# guarding a rich pool", + /*german*/ "", + /*french*/ "un #étang sous-terrain avec un Octorok#")); + // /*spanish*/un #Octorok# que custodia un lujoso charco + + hintTextTable[RHT_DEKU_THEATER] = HintText(CustomMessage("the #Lost Woods Stage#", + /*german*/ "", + /*french*/ "le #théâtre sylvestre#")); + // /*spanish*/el #escenario del Bosque Perdido# + + hintTextTable[RHT_ZR_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + hintTextTable[RHT_DMC_UPPER_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_DMT_STORMS_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_KAK_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_HF_NEAR_MARKET_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_HF_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + hintTextTable[RHT_HF_SOUTHEAST_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_KF_STORMS_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_LW_NEAR_SHORTCUTS_GROTTO] = HintText(CustomMessage("a #generic grotto#", + /*german*/ "", + /*french*/ "une #grotte avec un trésor#")); + // /*spanish*/una #cueva genérica# + + hintTextTable[RHT_HF_INSIDE_FENCE_GROTTO] = HintText(CustomMessage("a #single Upgrade Deku Scrub#", + /*german*/ "", + /*french*/ "une #grotte avec une peste Mojo#")); + // /*spanish*/una cueva con un #solitario mercader deku# + + hintTextTable[RHT_LW_SCRUBS_GROTTO] = HintText(CustomMessage("#2 Deku Scrubs# including an Upgrade one", + /*german*/ "", + /*french*/ "une #grotte avec deux pestes Mojo#")); + // /*spanish*/una cueva con #dos mercaderes deku# + + hintTextTable[RHT_COLOSSUS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec deux pestes Mojo#")); + // /*spanish*/una cueva con #dos mercaderes deku# + + hintTextTable[RHT_ZR_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec deux pestes Mojo#")); + // /*spanish*/una cueva con #dos mercaderes deku# + + hintTextTable[RHT_SFM_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec deux pestes Mojo#")); + // /*spanish*/una cueva con #dos mercaderes deku# + + hintTextTable[RHT_GV_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec deux pestes Mojo#")); + // /*spanish*/una cueva con #dos mercaderes deku# + + hintTextTable[RHT_LH_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec trois pestes Mojo#")); + // /*spanish*/una cueva con #tres mercaderes deku# + + hintTextTable[RHT_DMC_HAMMER_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec trois pestes Mojo#")); + // /*spanish*/una cueva con #tres mercaderes deku# + + hintTextTable[RHT_GC_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec trois pestes Mojo#")); + // /*spanish*/una cueva con #tres mercaderes deku# + + hintTextTable[RHT_LLR_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", + /*german*/ "", + /*french*/ "une #grotte avec trois pestes Mojo#")); + // /*spanish*/una cueva con #tres mercaderes deku# + + hintTextTable[RHT_ZR_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", + /*german*/ "", + /*french*/ "une #fontaine de fées#")); + // /*spanish*/una pequeña #fuente de hadas# + + hintTextTable[RHT_HF_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", + /*german*/ "", + /*french*/ "une #fontaine de fées#")); + // /*spanish*/una pequeña #fuente de hadas# + + hintTextTable[RHT_SFM_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", + /*german*/ "", + /*french*/ "une #fontaine de fées#")); + // /*spanish*/una pequeña #fuente de hadas# + + hintTextTable[RHT_ZD_STORMS_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", + /*german*/ "", + /*french*/ "une #fontaine de fées#")); + // /*spanish*/una pequeña #fuente de hadas# + + hintTextTable[RHT_GF_STORMS_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", + /*german*/ "", + /*french*/ "une #fontaine de fées#")); + // /*spanish*/una pequeña #fuente de hadas# /*-------------------------- | JUNK HINT TEXT | ---------------------------*/ - hintTable[RHT_JUNK02] = HintText::Junk({ - // obscure text - Text{ "They say you must read the names of \"Special Deal\" shop items carefully.", - /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!", - /*spanish*/ "Según dicen, se debería prestar atención a los nombres de las ofertas especiales." }, - }); - - hintTable[RHT_JUNK03] = HintText::Junk({ - // obscure text - Text{ "They say that Zelda is a poor leader.", /*french*/ "Selon moi, Zelda ne ferait pas un bon monarque.", - /*spanish*/ "Según dicen, Zelda es mala líder." }, - }); - - hintTable[RHT_JUNK04] = HintText::Junk({ - // obscure text - Text{ "These hints can be quite useful. This is an exception.", - /*french*/ "Ces indices sont très utiles, à l'exception de celui-ci.", - /*spanish*/ "Las pistas suelen servir de ayuda. En cambio, esta no." }, - }); - - hintTable[RHT_JUNK05] = HintText::Junk({ - // obscure text - Text{ "They say that the Lizalfos in Dodongo's Cavern like to play in lava.", - /*french*/ "Selon moi, les Lézalfos de la Caverne Dodongo aiment patauger dans la lave.", - /*spanish*/ "Según dicen, a los Lizalfos de la Cueva de los Dodongos les gusta jugar en la lava." }, - }); - - hintTable[RHT_JUNK06] = HintText::Junk({ - // obscure text - Text{ "They say that all the Zora drowned in Wind Waker.", - /*french*/ "Selon moi, les Zoras se sont noyés dans Wind Waker.", - /*spanish*/ "Según dicen, en Wind Waker todos los zora se ahogaron." }, - }); - - hintTable[RHT_JUNK07] = HintText::Junk({ - // obscure text - Text{ "If Gorons eat rocks, does that mean I'm in danger?", - /*french*/ "Ne dis pas au Gorons que je suis ici. Ils mangent des roches, tu sais!", - /*spanish*/ "Si los Goron se tragan las piedras, ¿no me hace ser una especia vulnarable o algo así" }, - }); - - hintTable[RHT_JUNK08] = HintText::Junk({ - // obscure text - Text{ - "'Member when Ganon was a blue pig?^I 'member.", - /*french*/ "Dans mon temps, Ganon était un cochon bleu...^Pff! Les jeunes de nos jours, et leur Ganondorf!", - /*spanish*/ "¿T'acuerdas cuando Ganon era un cerdo azul?^Qué tiempos, chico." }, - }); - - hintTable[RHT_JUNK09] = HintText::Junk({ - // obscure text - Text{ "One who does not have Triforce can't go in.", /*french*/ "Ceux sans Triforce doivent rebrousser chemin.", - /*spanish*/ "Aquel que no porte la Trifuerza no podrá pasar." }, - }); - - hintTable[RHT_JUNK10] = HintText::Junk({ - // obscure text - Text{ "Save your future, end the Happy Mask Salesman.", - /*french*/ "Selon moi, tu t'éviteras des jours de malheur si tu vaincs le vendeur de masques...", - /*spanish*/ "Salva tu futuro, acaba con el dueño de La Máscara Feliz." }, - }); - - hintTable[RHT_JUNK11] = HintText::Junk({ - // obscure text - Text{ "Glitches are a pathway to many abilities some consider to be... Unnatural.", /*french*/ - "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire " - "à la nature.", - /*spanish*/ "Los glitches son el camino a muchas habilidades que varios consideran... nada natural." }, - }); - - hintTable[RHT_JUNK12] = HintText::Junk({ - // obscure text - Text{ "I'm stoned. Get it?", /*french*/ "Allez, roche, papier, ciseau...&Roche.", - /*spanish*/ "Me he quedado de piedra. ¿Lo pillas?" }, - }); - - hintTable[RHT_JUNK13] = HintText::Junk({ - // obscure text - Text{ "Hoot! Hoot! Would you like me to repeat that?", /*french*/ "Hou hou! Veux-tu que je répète tout ça?", - /*spanish*/ "¡Buuu, buuu! ¿Te lo vuelvo a repetir?" }, - }); - - hintTable[RHT_JUNK14] = HintText::Junk({ - // obscure text - Text{ "Gorons are stupid. They eat rocks.", /*french*/ "Les Gorons sont des vraies têtes dures.", - /*spanish*/ "Los Goron son tontos. Se comen las piedras." }, - }); - - hintTable[RHT_JUNK15] = HintText::Junk({ - // obscure text - Text{ "They say that Lon Lon Ranch prospered under Ingo.", - /*french*/ "Selon moi, le Ranch Lon Lon était plus prospère sous Ingo.", - /*spanish*/ "Según dicen, el Rancho Lon Lon prosperó gracias a Ingo." }, - }); - - hintTable[RHT_JUNK16] = HintText::Junk({ - // obscure text - Text{ "The single rupee is a unique item.", /*french*/ "Nul objet n'est plus unique que le rubis vert.", - /*spanish*/ "La rupia de uno es un objeto singular." }, - }); - - hintTable[RHT_JUNK17] = HintText::Junk({ - // obscure text - Text{ "Without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!", - /*french*/ "Gagner la Chasse-aux-Trésors est 1 chance sur 32.^Bonne chance!", /*spanish*/ - "Sin la Lupa de la Verdad, ganarías 1/32 veces en el Cofre del Tesoro.^¡Buena suerte con ello!" }, - }); - - hintTable[RHT_JUNK18] = HintText::Junk({ - // obscure text - Text{ "Use bombs wisely.", /*french*/ "Utilise les bombes avec précaution.", - /*spanish*/ "No desperdicies las bombas." }, - }); - - hintTable[RHT_JUNK19] = HintText::Junk({ - // obscure text - Text{ "They say that Volvagia hates splinters", /*french*/ "Selon moi, Volvagia déteste les échardes.", - /*spanish*/ "Según dicen, Volvagia le teme a las astillas." }, - }); - - hintTable[RHT_JUNK20] = HintText::Junk({ - // obscure text - Text{ "They say that funky monkeys can be spotted on Friday.", - /*french*/ "Selon moi, des capucins coquins sortent le vendredi.", - /*spanish*/ "Según dicen, en los viernes puedes hallar monos marchosos." }, - }); - - hintTable[RHT_JUNK21] = HintText::Junk({ - // obscure text - Text{ "I found you, faker!", /*french*/ "Ah-ha! Je t'ai trouvé!", /*spanish*/ "¡Ahí estás, impostor!" }, - }); - - hintTable[RHT_JUNK22] = HintText::Junk({ - // obscure text - Text{ "They say the Groose is loose.", /*french*/ "Selon moi, Hergo est le vrai héros.", - /*spanish*/ "Según dicen, Malton es un espanto." }, - }); - - hintTable[RHT_JUNK23] = HintText::Junk({ - // obscure text - Text{ - "They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"", - /*french*/ "Selon moi, ceux qui utilisent les contrôles gyroscopiques sont les VRAIS joueurs.", /*spanish*/ - "Según dicen, aquellos que juegan usando el control por movimiento son los verdaderos jugadores de " - "Zelda." }, - }); - - hintTable[RHT_JUNK24] = HintText::Junk({ - // obscure text - Text{ "What happened to Sheik?", /*french*/ "Donc... Qu'est-ce qui arrive avec Sheik?", - /*spanish*/ "¿Qué la habrá pasado a Sheik?" }, - }); - - hintTable[RHT_JUNK25] = HintText::Junk({ - // obscure text - Text{ "L2P @.", /*french*/ "Arrête de lire les indices et joue comme un grand, @.", - /*spanish*/ "Mira que eres novato, @." }, - }); - - hintTable[RHT_JUNK26] = HintText::Junk({ - // obscure text - Text{ "I've heard you can cheat at Sploosh Kaboom.", - /*french*/ "Selon moi, il y a une carte aux trésors à Mercantîle... Duh!", - /*spanish*/ "He oído por ahí que puedes hacer trampa en el Sploosh Kaboom." }, - }); - - hintTable[RHT_JUNK27] = HintText::Junk({ - // obscure text - Text{ "I'm Lonk from Pennsylvania.", /*french*/ "Je suis Lonk, le héros de Pennsylvanie!", - /*spanish*/ "Soy Lonk, de Pensilvania." }, - }); - - hintTable[RHT_JUNK28] = HintText::Junk({ - // obscure text - Text{ "I bet you'd like to have more bombs.", /*french*/ "Je parie que tu veux plus de bombes.", - /*spanish*/ "Me apuesto a que quisieras tener más bombas." }, - }); - - hintTable[RHT_JUNK29] = HintText::Junk({ - // obscure text - Text{ "When all else fails, use Fire.", /*french*/ "Quand rien ne marche, utilise le feu.", - /*spanish*/ "Cuando nada funcione, usa el fuego." }, - }); - - hintTable[RHT_JUNK30] = HintText::Junk({ - // obscure text - Text{ "Here's a hint, @. Don't be bad.", /*french*/ "Selon moi, la #Triforce# n'est pas dans le jeu... Duh!", - /*spanish*/ "Aquí tienes una pista, @: deja de ser manco." }, - }); - - hintTable[RHT_JUNK31] = HintText::Junk({ - // obscure text - Text{ "Game Over. Return of Ganon.", /*french*/ "Partie terminée. RETour de Ganon.", - /*spanish*/ "Fin de la partida. El regreso de Ganon." }, - }); - - hintTable[RHT_JUNK32] = HintText::Junk({ - // obscure text - Text{ "May the way of the Hero lead to the Triforce.", - /*french*/ "Que le chemin du héros te mène à la Triforce.", - /*spanish*/ "Puede que la senda del héroe te lleve hacia la Trifuerza." }, - }); - - hintTable[RHT_JUNK33] = HintText::Junk({ - // obscure text - Text{ "Can't find an item? Scan an Amiibo.", /*french*/ "Tu cherches de quoi? Utilise un Amiibo!", - /*spanish*/ "¿No encuentras algo? Escanea un amiibo." }, - }); - - hintTable[RHT_JUNK34] = HintText::Junk({ - // obscure text - Text{ "They say this game has just a few glitches.", - /*french*/ "Selon moi, ce jeu est complètement exempt de glitchs.", - /*spanish*/ "Dicen que este juego apenas tiene glitches." }, - }); - - hintTable[RHT_JUNK35] = HintText::Junk({ - // obscure text - Text{ "BRRING BRRING This is Ulrira. Wrong number?", - /*french*/ "DRING DRING!! Pépé le Ramollo à l'appareil... Quoi? Faux numéro?", - /*spanish*/ "¡Ring! ¡Ring! Al habla Ulrira. ¿Me he equivocado de número?" }, - }); - - hintTable[RHT_JUNK36] = HintText::Junk({ - // obscure text - Text{ "Tingle Tingle Kooloo Limpah!", /*french*/ "Tingle! Tingle! Kooloolin... Pah!", - /*spanish*/ "Tingle, Tingle, Kurulín... ¡PA!" }, - }); - - hintTable[RHT_JUNK37] = HintText::Junk({ - // obscure text - Text{ "L is real 2401", /*french*/ "L is real 2401", /*spanish*/ "L es real 2401." }, - }); - - hintTable[RHT_JUNK38] = HintText::Junk({ - // obscure text - Text{ "They say that Ganondorf will appear in the next Mario Tennis.", - /*french*/ "Selon moi, Ganondorf sera la nouvelle recrue dans Mario Tennis.", - /*spanish*/ "Según dicen, Ganondorf estará en el próximo Mario Tennis." }, - }); - - hintTable[RHT_JUNK39] = HintText::Junk({ - // obscure text - Text{ "Medigoron sells the earliest Breath of the Wild demo.", - /*french*/ "Selon moi, Medigoron vend une démo de #Breath of the Wild#.", - /*spanish*/ "Medigoron vende la primera demo del Breath of the Wild." }, - }); - - hintTable[RHT_JUNK40] = HintText::Junk({ - // obscure text - Text{ "Can you move me? I don't get great service here.", - /*french*/ "Peux-tu me déplacer? J'ai pas une bonne réception ici.", - /*spanish*/ "¿Puedes llevarme a otro lado? Aquí nadie me presta atención." }, - }); - - hintTable[RHT_JUNK41] = HintText::Junk({ - // obscure text - Text{ "They say if you use Strength on the truck, you can find Mew.", - /*french*/ "Selon moi, #Mew# se trouve dessous le camion... Duh!", - /*spanish*/ "Según dicen, puedes hallar un Mew usando Fuerza contra el camión de Ciudad Carmín." }, - }); - - hintTable[RHT_JUNK42] = HintText::Junk({ - // obscure text - Text{ "I'm a helpful hint Gossip Stone!^See, I'm helping.", - /*french*/ "Salut! Je suis une pierre de bons conseils!^Tiens, tu vois? J'aide bien, hein?", - /*spanish*/ "Soy una Piedra Sheikah muy útil.^¡Mira cómo te ayudo!" }, - }); - - hintTable[RHT_JUNK43] = HintText::Junk({ - // obscure text - Text{ - "Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.", /*french*/ - "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda", - /*spanish*/ - "Querido @: Por favor, ven al castillo. He hecho una tarta para ti.&Sinceramente tuya: Princesa Zelda." }, - }); - - hintTable[RHT_JUNK44] = HintText::Junk({ - // obscure text - Text{ "They say all toasters toast toast.", /*french*/ "Selon moi, les grille-pains grillent du pain.", - /*spanish*/ "Según dicen, todas las tostadoras tostan tostadas tostadas." }, - }); - - hintTable[RHT_JUNK45] = HintText::Junk({ - // obscure text - Text{ "You thought it would be a useful hint, but it was me, junk hint!", - /*french*/ "Tu t'attendais à un bon indice... Mais c'était moi, un mauvais indice!", /*spanish*/ - "Je... Creeías que iba a ser una piedra de utilidad, ¡pero no, era yo, la piedra de la agonía!" }, - }); - - hintTable[RHT_JUNK46] = HintText::Junk({ - // obscure text - Text{ "They say that quest guidance can be found at a talking rock.", - /*french*/ "Selon moi, des #indices# se trouvent auprès d'une pierre parlante... Duh!", - /*spanish*/ "Según dicen, puedes consultarle ayuda a rocas parlanchinas." }, - }); - - hintTable[RHT_JUNK47] = HintText::Junk({ - // obscure text - Text{ "They say that the final item you're looking for can be found somewhere in Hyrule.", - /*french*/ "Selon moi, le #dernier objet# se trouve quelque part dans Hyrule... Duh!", - /*spanish*/ "Según dicen, el último objeto que te falte puede estar en cualquier rincón de Hyrule." }, - }); - - hintTable[RHT_JUNK48] = HintText::Junk({ - // obscure text - Text{ "Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.", - /*french*/ "Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.", - /*spanish*/ "Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep." }, - }); - - hintTable[RHT_JUNK49] = HintText::Junk({ - // obscure text - Text{ "They say that Barinade fears Deku Nuts.", /*french*/ "Selon moi, Barinade a la frousse des noix Mojo.", - /*spanish*/ "Según dicen, lo que más teme a Barinade son las nueces deku." }, - }); - - hintTable[RHT_JUNK50] = HintText::Junk({ - // obscure text - Text{ "They say that Flare Dancers do not fear Goron-crafted blades.", - /*french*/ "Selon moi, le danse-flamme n'a pas peur des armes de Goron.", - /*spanish*/ "Según dicen, los Bailafuegos no le temen a las armas forjadas por Gorons." }, - }); - - hintTable[RHT_JUNK51] = HintText::Junk({ - // obscure text - Text{ "They say that Morpha is easily trapped in a corner.", - /*french*/ "Selon moi, Morpha est facilement coincé.", - /*spanish*/ "Según dicen, puedes atrapar a Morpha con facilidad en una esquina." }, - }); - - hintTable[RHT_JUNK52] = HintText::Junk({ - // obscure text - Text{ "They say that Bongo Bongo really hates the cold.", - /*french*/ "Selon moi, Bongo Bongo a facilement froid aux doigts.", - /*spanish*/ "Según dicen, Bongo Bongo odia a muerte el frío." }, - }); - - hintTable[RHT_JUNK53] = HintText::Junk({ - // obscure text - Text{ "They say that your sword is most powerful when you put it away.", - /*french*/ "Selon moi, ton épée est à pleine puissance quand tu la rengaines.", - /*spanish*/ "Según dicen, tu espada se vuelve más poderosa si la guardas." }, - }); - - hintTable[RHT_JUNK54] = HintText::Junk({ - // obscure text - Text{ "They say that bombing the hole Volvagia last flew into can be rewarding.", - /*french*/ "Selon moi, le trou où se creuse Volvagia est vulnérable aux bombes.", /*spanish*/ - "Según dicen, trae buena suerte colocar una bomba en el último agujero de donde salió Volvagia." }, - }); - - hintTable[RHT_JUNK55] = HintText::Junk({ - // obscure text - Text{ "They say that invisible ghosts can be exposed with Deku Nuts.", - /*french*/ "Selon moi, des fantômes invisibles apparaissent avec des noix Mojo.", - /*spanish*/ "Según dicen, puedes exponer a los espectros invisibles con nueces deku." }, - }); - - hintTable[RHT_JUNK56] = HintText::Junk({ - // obscure text - Text{ "They say that the real Phantom Ganon is bright and loud.", - /*french*/ "Selon moi, le vrai spectre de Ganon est clair et bruyant.", - /*spanish*/ "Según dicen, el verdadero Ganon Fantasma es brillante y ruidoso." }, - }); - - hintTable[RHT_JUNK57] = HintText::Junk({ - // obscure text - Text{ "They say that walking backwards is very fast.", - /*french*/ "Selon moi, tu fais marche arrière très rapidement pour un héros.", - /*spanish*/ "Según dicen, es más rápido caminar hacia atrás." }, - }); - - hintTable[RHT_JUNK58] = HintText::Junk({ - // obscure text - Text{ - "They say that leaping above the Market entrance enriches most children.", - /*french*/ "Selon moi, les enfants riches se pavanent en haut du pont-levis.", - /*spanish*/ "Según dicen, saltar por las cadenas a la entrada de la plaza enriquece a muchos chiquillos." }, - }); - - hintTable[RHT_JUNK59] = HintText::Junk({ - // obscure text - Text{ "They say Ingo is not very good at planning ahead.", - /*french*/ "Selon moi, Ingo ne fait pas un très bon geôlier.", - /*spanish*/ "Según dicen, a Ingo no se le da especialmente bien planificar con antelación." }, - }); - - hintTable[RHT_JUNK60] = HintText::Junk({ - // obscure text - Text{ "You found a spiritual Stone! By which I mean, I worship Nayru.", - /*french*/ "Vous avez trouvé une Pierre Ancestrale! En effet, je vénère la déesse Hylia.", - /*spanish*/ "¡Has encontrado una piedra espiritual! Es que le rindo culto a Nayru..." }, - }); - - hintTable[RHT_JUNK61] = HintText::Junk({ - // obscure text - Text{ "They say that a flying strike with a Deku Stick is no stronger than a grounded one.", - /*french*/ "Selon moi, un coup de bâton sauté n'est pas meilleur qu'au sol.", - /*spanish*/ "Según dicen, los golpes aéreos con palos deku son tan fuertes como los normales." }, - }); - - hintTable[RHT_JUNK62] = HintText::Junk({ - // obscure text - Text{ "Open your eyes.^Open your eyes.^Wake up, @.", - /*french*/ "Réveille-toi...^Réveille-toi.^Ouvre les yeux, @.", - /*spanish*/ "Abre los ojos...^Abre los ojos...^Despierta, @..." }, - }); - - hintTable[RHT_JUNK63] = HintText::Junk({ - // obscure text - Text{ "They say that the Nocturne of Shadow can bring you very close to Ganon.", - /*french*/ "Selon moi, le nocturne de l'ombre peut t'amener très près de Ganon.", - /*spanish*/ "Según dicen, el Nocturno de la sombra te puede acercar mucho a Ganon." }, - }); - - hintTable[RHT_JUNK64] = HintText::Junk({ - // obscure text - Text{ "They say that Twinrova always casts the same spell the first three times.", - /*french*/ "Selon moi, Twinrova lance toujours les mêmes trois premiers sorts.", - /*spanish*/ "Según dicen, Birova siempre lanza el mismo hechizo las tres primeras veces." }, - }); - - hintTable[RHT_JUNK65] = HintText::Junk({ - // obscure text - Text{ "They say that the nightly builds may be unstable.", - /*french*/ "Selon moi, les \"nightly builds\" peuvent être instables.", - /*spanish*/ "Según dicen, las últimas nightlies pueden llegar a ser algo inestables." }, - }); - - hintTable[RHT_JUNK66] = HintText::Junk({ - // obscure text - Text{ "You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!", - /*french*/ "Tu joues à un randomizer. Je suis aléatoire!^Voici un nombre aléatoire: #4#.&Bonne partie!", - /*spanish*/ - "¡Estás jugando un Randomizer! ¡Yo también estoy aleatorizada!^Aquí tienes un número aleatorio: " - "#8#.&¡Diviértete!" }, - }); - - hintTable[RHT_JUNK67] = HintText::Junk({ - // obscure text - Text{ "They say Ganondorf's bolts can be reflected with glass or steel.", - /*french*/ "Selon moi, les éclairs de Ganon se reflètent sur l'acier et le verre.", - /*spanish*/ "Según dicen, puedes reflejar las esferas de energía de Ganondorf con cristal y acero." }, - }); - - hintTable[RHT_JUNK68] = HintText::Junk({ - // obscure text - Text{ "They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, " - "boomerangs...^...rods, shovels, iron balls, angry bees...", - /*french*/ - "Selon moi, la queue de Ganon est vulnérable aux noix, flèches, épées, bombes, marteaux...^...bâtons, " - "graines, boomerangs...^...baguettes, pelles, boulets de fer, abeilles enragées...", - /*spanish*/ - "Según dicen, la cola de Ganon es vulnerable a nueces, flechas, espadas, explosivos, " - "martillos...^...palos, semillas, bumeráns...^...cetros, palas, bolas de hierro, abejas..." }, - }); - - hintTable[RHT_JUNK69] = HintText::Junk({ - // obscure text - Text{ - "They say that you're wasting time reading this hint, but I disagree. Talk to me again!", - /*french*/ "Selon moi... tu sais quoi? Parle-moi encore, et je te le dirai!", /*spanish*/ - "Según dicen, pierdes el tiempo en leer esta pista, pero no pienso igual. ¡Vuelve a hablarme, ya verás!" }, - }); - - hintTable[RHT_JUNK70] = HintText::Junk({ - // obscure text - Text{ "They say Ganondorf knows where to find the instrument of his doom.", - /*french*/ "Selon moi, Ganondorf sait où il a caché son point faible.", - /*spanish*/ "Según dicen, Ganondorf sabe dónde hallar el instrumento de su perdición." }, - }); - - hintTable[RHT_JUNK71] = HintText::Junk({ - // obscure text - Text{ "I heard @ is pretty good at Zelda.", /*french*/ "Apparemment, @ est super bon à Zelda.", - /*spanish*/ "He oído que a @ se le dan muy bien los Zelda." }, - }); - - hintTable[RHT_JUNK72] = HintText::Junk({ - // obscure text - Text{ "Hi @, we've been trying to reach you about your car's extended warranty. ", - /*french*/ "Bonjour, @. Vous avez une voiture? Vous savez, nous offrons des assurances abordables...", - /*spanish*/ - "Buenas, @. Le llamamos para ofrecerle un nuevo seguro de hogar que puede pagar en cómodos plazos, sin " - "intereses ni comisiones." }, - }); - - hintTable[RHT_JUNK73] = HintText::Junk({ - // obscure text - Text{ "They say that the best weapon against Iron Knuckles is item 176.", - /*french*/ "Selon moi, les hache-viandes sont vulnérables contre l'objet 176.", - /*spanish*/ "Según dicen, la mejor arma para enfrentarse a los Nudillos de hierro es el objeto 176." }, - }); - - hintTable[RHT_JUNK74] = HintText::Junk({ - // obscure text - Text{ "They say that it's actually possible to beat the running man.", - /*french*/ "Selon moi, il est possible de battre le coureur.&Donc, tu prends ton arc, et...", - /*spanish*/ "Según dicen, con mucha perseverancia puedes ganarle al corredor con la capucha de conejo." }, - }); - - hintTable[RHT_JUNK75] = HintText::Junk({ - // obscure text - Text{ "They say that the stone-cold guardian of the Well is only present during work hours.", - /*french*/ "Selon moi, le gardien de pierre du Puits quitte le soir pour aller se coucher.", - /*spanish*/ "Según dicen, la inmensa roca que bloquea el pozo solo trabaja en horas laborales." }, - }); - - hintTable[RHT_JUNK76] = HintText::Junk({ - // obscure text - Text{ - "They say this hint makes more sense in other languages.", - /*french*/ "Selon moi, ces indices auraient pu être mieux traduits... Duh!", - /*spanish*/ "Según dicen, esta pista revela algo de vital importancia si cambias el idioma del juego..." }, - }); - - hintTable[RHT_JUNK77] = HintText::Junk({ - // obscure text - Text{ "BOK? No way.", /*french*/ "BD'accord? Hors de question.", /*spanish*/ "¿BVale? Ni hablar." }, - }); + hintTextTable[RHT_JUNK02] = HintText(CustomMessage("They say you must read the names of \"Special Deal\" shop items carefully.", + /*german*/ "", + /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!")); + // /*spanish*/"Según dicen, se debería prestar atención a los nombres de las ofertas especiales." + + + hintTextTable[RHT_JUNK03] = HintText(CustomMessage("They say that Zelda is a poor leader.", + /*german*/ "", + /*french*/ "Selon moi, Zelda ne ferait pas un bon monarque.")); + // /*spanish*/Según dicen, Zelda es mala líder. + + hintTextTable[RHT_JUNK04] = HintText(CustomMessage("These hints can be quite useful. This is an exception.", + /*german*/ "", + /*french*/ "Ces indices sont très utiles, à l'exception de celui-ci.")); + // /*spanish*/Las pistas suelen servir de ayuda. En cambio, esta no. + + hintTextTable[RHT_JUNK05] = HintText(CustomMessage("They say that the Lizalfos in Dodongo's Cavern like to play in lava.", + /*german*/ "", + /*french*/ "Selon moi, les Lézalfos de la Caverne Dodongo aiment patauger dans la lave.")); + // /*spanish*/Según dicen, a los Lizalfos de la Cueva de los Dodongos les gusta jugar en la lava. + + hintTextTable[RHT_JUNK06] = HintText(CustomMessage("They say that all the Zora drowned in Wind Waker.", + /*german*/ "", + /*french*/ "Selon moi, les Zoras se sont noyés dans Wind Waker.")); + // /*spanish*/Según dicen, en Wind Waker todos los zora se ahogaron. + + hintTextTable[RHT_JUNK07] = HintText(CustomMessage("If Gorons eat rocks, does that mean I'm in danger?", + /*german*/ "", + /*french*/ "Ne dis pas au Gorons que je suis ici. Ils mangent des roches, tu sais!")); + // /*spanish*/Si los Goron se tragan las piedras, ¿no me hace ser una especia vulnarable o algo así + + hintTextTable[RHT_JUNK08] = HintText(CustomMessage("'Member when Ganon was a blue pig?^I 'member.", + /*german*/ "", + /*french*/ "Dans mon temps, Ganon était un cochon bleu...^Pff! Les jeunes de nos jours, et leur Ganondorf!")); + // /*spanish*/¿T'acuerdas cuando Ganon era un cerdo azul?^Qué tiempos, chico. + + hintTextTable[RHT_JUNK09] = HintText(CustomMessage("One who does not have Triforce can't go in.", + /*german*/ "", + /*french*/ "Ceux sans Triforce doivent rebrousser chemin.")); + // /*spanish*/Aquel que no porte la Trifuerza no podrá pasar. + + hintTextTable[RHT_JUNK10] = HintText(CustomMessage("Save your future, end the Happy Mask Salesman.", + /*german*/ "", + /*french*/ "Selon moi, tu t'éviteras des jours de malheur si tu vaincs le vendeur de masques...")); + // /*spanish*/Salva tu futuro, acaba con el dueño de La Máscara Feliz. + + hintTextTable[RHT_JUNK11] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.", + /*german*/ "Los glitches son el camino a muchas habilidades que varios consideran... nada natural.", + /*french*/ "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire ")); + // /*spanish*/à la nature. + + hintTextTable[RHT_JUNK12] = HintText(CustomMessage("I'm stoned. Get it?", + /*german*/ "", + /*french*/ "Allez, roche, papier, ciseau...&Roche.")); + // /*spanish*/Me he quedado de piedra. ¿Lo pillas? + + hintTextTable[RHT_JUNK13] = HintText(CustomMessage("Hoot! Hoot! Would you like me to repeat that?", + /*german*/ "", + /*french*/ "Hou hou! Veux-tu que je répète tout ça?")); + // /*spanish*/¡Buuu, buuu! ¿Te lo vuelvo a repetir? + + hintTextTable[RHT_JUNK14] = HintText(CustomMessage("Gorons are stupid. They eat rocks.", + /*german*/ "", + /*french*/ "Les Gorons sont des vraies têtes dures.")); + // /*spanish*/Los Goron son tontos. Se comen las piedras. + + hintTextTable[RHT_JUNK15] = HintText(CustomMessage("They say that Lon Lon Ranch prospered under Ingo.", + /*german*/ "", + /*french*/ "Selon moi, le Ranch Lon Lon était plus prospère sous Ingo.")); + // /*spanish*/Según dicen, el Rancho Lon Lon prosperó gracias a Ingo. + + hintTextTable[RHT_JUNK16] = HintText(CustomMessage("The single rupee is a unique item.", + /*german*/ "", + /*french*/ "Nul objet n'est plus unique que le rubis vert.")); + // /*spanish*/La rupia de uno es un objeto singular. + + hintTextTable[RHT_JUNK17] = HintText(CustomMessage("Without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!", + /*german*/ "", + /*french*/ "Gagner la Chasse-aux-Trésors est 1 chance sur 32.^Bonne chance!")); + // /*spanish*/Sin la Lupa de la Verdad, ganarías 1/32 veces en el Cofre del Tesoro.^¡Buena suerte con ello! + + hintTextTable[RHT_JUNK18] = HintText(CustomMessage("Use bombs wisely.", + /*german*/ "", + /*french*/ "Utilise les bombes avec précaution.")); + // /*spanish*/No desperdicies las bombas. + + hintTextTable[RHT_JUNK19] = HintText(CustomMessage("They say that Volvagia hates splinters", + /*german*/ "", + /*french*/ "Selon moi, Volvagia déteste les échardes.")); + // /*spanish*/Según dicen, Volvagia le teme a las astillas. + + hintTextTable[RHT_JUNK20] = HintText(CustomMessage("They say that funky monkeys can be spotted on Friday.", + /*german*/ "", + /*french*/ "Selon moi, des capucins coquins sortent le vendredi.")); + // /*spanish*/Según dicen, en los viernes puedes hallar monos marchosos. + + hintTextTable[RHT_JUNK21] = HintText(CustomMessage("I found you, faker!", + /*german*/ "", + /*french*/ "Ah-ha! Je t'ai trouvé!")); + // /*spanish*/¡Ahí estás, impostor! + + hintTextTable[RHT_JUNK22] = HintText(CustomMessage("They say the Groose is loose.", + /*german*/ "", + /*french*/ "Selon moi, Hergo est le vrai héros.")); + // /*spanish*/Según dicen, Malton es un espanto. + + hintTextTable[RHT_JUNK23] = HintText(CustomMessage("They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"", + /*german*/ "", + /*french*/ "Selon moi, ceux qui utilisent les contrôles gyroscopiques sont les VRAIS joueurs.")); + // /*spanish*/ "Según dicen, aquellos que juegan usando el control por movimiento son los verdaderos jugadores de Zelda." + + hintTextTable[RHT_JUNK24] = HintText(CustomMessage("What happened to Sheik?", + /*german*/ "", + /*french*/ "Donc... Qu'est-ce qui arrive avec Sheik?")); + // /*spanish*/¿Qué la habrá pasado a Sheik? + + hintTextTable[RHT_JUNK25] = HintText(CustomMessage("L2P @.", + /*german*/ "", + /*french*/ "Arrête de lire les indices et joue comme un grand, @.")); + // /*spanish*/Mira que eres novato, @. + + hintTextTable[RHT_JUNK26] = HintText(CustomMessage("I've heard you can cheat at Sploosh Kaboom.", + /*german*/ "", + /*french*/ "Selon moi, il y a une carte aux trésors à Mercantîle... Duh!")); + // /*spanish*/He oído por ahí que puedes hacer trampa en el Sploosh Kaboom. + + hintTextTable[RHT_JUNK27] = HintText(CustomMessage("I'm Lonk from Pennsylvania.", + /*german*/ "", + /*french*/ "Je suis Lonk, le héros de Pennsylvanie!")); + // /*spanish*/Soy Lonk, de Pensilvania. + + hintTextTable[RHT_JUNK28] = HintText(CustomMessage("I bet you'd like to have more bombs.", + /*german*/ "", + /*french*/ "Je parie que tu veux plus de bombes.")); + // /*spanish*/Me apuesto a que quisieras tener más bombas. + + hintTextTable[RHT_JUNK29] = HintText(CustomMessage("When all else fails, use Fire.", + /*german*/ "", + /*french*/ "Quand rien ne marche, utilise le feu.")); + // /*spanish*/Cuando nada funcione, usa el fuego. + + hintTextTable[RHT_JUNK30] = HintText(CustomMessage("Here's a hint, @. Don't be bad.", + /*german*/ "", + /*french*/ "Selon moi, la #Triforce# n'est pas dans le jeu... Duh!")); + // /*spanish*/Aquí tienes una pista, @: deja de ser manco. + + hintTextTable[RHT_JUNK31] = HintText(CustomMessage("Game Over. Return of Ganon.", + /*german*/ "", + /*french*/ "Partie terminée. RETour de Ganon.")); + // /*spanish*/Fin de la partida. El regreso de Ganon. + + hintTextTable[RHT_JUNK32] = HintText(CustomMessage("May the way of the Hero lead to the Triforce.", + /*german*/ "", + /*french*/ "Que le chemin du héros te mène à la Triforce.")); + // /*spanish*/Puede que la senda del héroe te lleve hacia la Trifuerza. + + hintTextTable[RHT_JUNK33] = HintText(CustomMessage("Can't find an item? Scan an Amiibo.", + /*german*/ "", + /*french*/ "Tu cherches de quoi? Utilise un Amiibo!")); + // /*spanish*/¿No encuentras algo? Escanea un amiibo. + + hintTextTable[RHT_JUNK34] = HintText(CustomMessage("They say this game has just a few glitches.", + /*german*/ "", + /*french*/ "Selon moi, ce jeu est complètement exempt de glitchs.")); + // /*spanish*/Dicen que este juego apenas tiene glitches. + + hintTextTable[RHT_JUNK35] = HintText(CustomMessage("BRRING BRRING This is Ulrira. Wrong number?", + /*german*/ "", + /*french*/ "DRING DRING!! Pépé le Ramollo à l'appareil... Quoi? Faux numéro?")); + // /*spanish*/¡Ring! ¡Ring! Al habla Ulrira. ¿Me he equivocado de número? + + hintTextTable[RHT_JUNK36] = HintText(CustomMessage("Tingle Tingle Kooloo Limpah!", + /*german*/ "", + /*french*/ "Tingle! Tingle! Kooloolin... Pah!")); + // /*spanish*/Tingle, Tingle, Kurulín... ¡PA! + + hintTextTable[RHT_JUNK37] = HintText(CustomMessage("L is real 2401", + /*german*/ "", + /*french*/ "L is real 2401")); + // /*spanish*/L es real 2401. + + hintTextTable[RHT_JUNK38] = HintText(CustomMessage("They say that Ganondorf will appear in the next Mario Tennis.", + /*german*/ "", + /*french*/ "Selon moi, Ganondorf sera la nouvelle recrue dans Mario Tennis.")); + // /*spanish*/Según dicen, Ganondorf estará en el próximo Mario Tennis. + + hintTextTable[RHT_JUNK39] = HintText(CustomMessage("Medigoron sells the earliest Breath of the Wild demo.", + /*german*/ "", + /*french*/ "Selon moi, Medigoron vend une démo de #Breath of the Wild#.")); + // /*spanish*/Medigoron vende la primera demo del Breath of the Wild. + + hintTextTable[RHT_JUNK40] = HintText(CustomMessage("Can you move me? I don't get great service here.", + /*german*/ "", + /*french*/ "Peux-tu me déplacer? J'ai pas une bonne réception ici.")); + // /*spanish*/¿Puedes llevarme a otro lado? Aquí nadie me presta atención. + + hintTextTable[RHT_JUNK41] = HintText(CustomMessage("They say if you use Strength on the truck, you can find Mew.", + /*german*/ "", + /*french*/ "Selon moi, #Mew# se trouve dessous le camion... Duh!")); + // /*spanish*/Según dicen, puedes hallar un Mew usando Fuerza contra el camión de Ciudad Carmín. + + hintTextTable[RHT_JUNK42] = HintText(CustomMessage("I'm a helpful hint Gossip Stone!^See, I'm helping.", + /*german*/ "", + /*french*/ "Salut! Je suis une pierre de bons conseils!^Tiens, tu vois? J'aide bien, hein?")); + // /*spanish*/Soy una Piedra Sheikah muy útil.^¡Mira cómo te ayudo! + + hintTextTable[RHT_JUNK43] = HintText(CustomMessage("Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.", + /*german*/ "", + /*french*/ "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda")); + // /*spanish*/Querido @: Por favor, ven al castillo. He hecho una tarta para ti.&Sinceramente tuya: Princesa Zelda. + + hintTextTable[RHT_JUNK44] = HintText(CustomMessage("They say all toasters toast toast.", + /*german*/ "", + /*french*/ "Selon moi, les grille-pains grillent du pain.")); + // /*spanish*/Según dicen, todas las tostadoras tostan tostadas tostadas. + + hintTextTable[RHT_JUNK45] = HintText(CustomMessage("You thought it would be a useful hint, but it was me, junk hint!", + /*german*/ "", + /*french*/ "Tu t'attendais à un bon indice... Mais c'était moi, un mauvais indice!")); + // /*spanish*/Je... Creeías que iba a ser una piedra de utilidad, ¡pero no, era yo, la piedra de la agonía! + + hintTextTable[RHT_JUNK46] = HintText(CustomMessage("They say that quest guidance can be found at a talking rock.", + /*german*/ "", + /*french*/ "Selon moi, des #indices# se trouvent auprès d'une pierre parlante... Duh!")); + // /*spanish*/Según dicen, puedes consultarle ayuda a rocas parlanchinas. + + hintTextTable[RHT_JUNK47] = HintText(CustomMessage("They say that the final item you're looking for can be found somewhere in Hyrule.", + /*german*/ "", + /*french*/ "Selon moi, le #dernier objet# se trouve quelque part dans Hyrule... Duh!")); + // /*spanish*/Según dicen, el último objeto que te falte puede estar en cualquier rincón de Hyrule. + + hintTextTable[RHT_JUNK48] = HintText(CustomMessage("Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.", + /*german*/ "", + /*french*/ "Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.")); + // /*spanish*/Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep. + + hintTextTable[RHT_JUNK49] = HintText(CustomMessage("They say that Barinade fears Deku Nuts.", + /*german*/ "", + /*french*/ "Selon moi, Barinade a la frousse des noix Mojo.")); + // /*spanish*/Según dicen, lo que más teme a Barinade son las nueces deku. + + hintTextTable[RHT_JUNK50] = HintText(CustomMessage("They say that Flare Dancers do not fear Goron-crafted blades.", + /*german*/ "", + /*french*/ "Selon moi, le danse-flamme n'a pas peur des armes de Goron.")); + // /*spanish*/Según dicen, los Bailafuegos no le temen a las armas forjadas por Gorons. + + hintTextTable[RHT_JUNK51] = HintText(CustomMessage("They say that Morpha is easily trapped in a corner.", + /*german*/ "", + /*french*/ "Selon moi, Morpha est facilement coincé.")); + // /*spanish*/Según dicen, puedes atrapar a Morpha con facilidad en una esquina. + + hintTextTable[RHT_JUNK52] = HintText(CustomMessage("They say that Bongo Bongo really hates the cold.", + /*german*/ "", + /*french*/ "Selon moi, Bongo Bongo a facilement froid aux doigts.")); + // /*spanish*/Según dicen, Bongo Bongo odia a muerte el frío. + + hintTextTable[RHT_JUNK53] = HintText(CustomMessage("They say that your sword is most powerful when you put it away.", + /*german*/ "", + /*french*/ "Selon moi, ton épée est à pleine puissance quand tu la rengaines.")); + // /*spanish*/Según dicen, tu espada se vuelve más poderosa si la guardas. + + hintTextTable[RHT_JUNK54] = HintText(CustomMessage("They say that bombing the hole Volvagia last flew into can be rewarding.", + /*german*/ "", + /*french*/ "Selon moi, le trou où se creuse Volvagia est vulnérable aux bombes.")); + // /*spanish*/Según dicen, trae buena suerte colocar una bomba en el último agujero de donde salió Volvagia. + + hintTextTable[RHT_JUNK55] = HintText(CustomMessage("They say that invisible ghosts can be exposed with Deku Nuts.", + /*german*/ "", + /*french*/ "Selon moi, des fantômes invisibles apparaissent avec des noix Mojo.")); + // /*spanish*/Según dicen, puedes exponer a los espectros invisibles con nueces deku. + + hintTextTable[RHT_JUNK56] = HintText(CustomMessage("They say that the real Phantom Ganon is bright and loud.", + /*german*/ "", + /*french*/ "Selon moi, le vrai spectre de Ganon est clair et bruyant.")); + // /*spanish*/Según dicen, el verdadero Ganon Fantasma es brillante y ruidoso. + + hintTextTable[RHT_JUNK57] = HintText(CustomMessage("They say that walking backwards is very fast.", + /*german*/ "", + /*french*/ "Selon moi, tu fais marche arrière très rapidement pour un héros.")); + // /*spanish*/Según dicen, es más rápido caminar hacia atrás. + + hintTextTable[RHT_JUNK58] = HintText(CustomMessage("They say that leaping above the Market entrance enriches most children.", + /*german*/ "", + /*french*/ "Selon moi, les enfants riches se pavanent en haut du pont-levis.")); + // /*spanish*/Según dicen, saltar por las cadenas a la entrada de la plaza enriquece a muchos chiquillos. + + hintTextTable[RHT_JUNK59] = HintText(CustomMessage("They say Ingo is not very good at planning ahead.", + /*german*/ "", + /*french*/ "Selon moi, Ingo ne fait pas un très bon geôlier.")); + // /*spanish*/Según dicen, a Ingo no se le da especialmente bien planificar con antelación. + + hintTextTable[RHT_JUNK60] = HintText(CustomMessage("You found a spiritual Stone! By which I mean, I worship Nayru.", + /*german*/ "", + /*french*/ "Vous avez trouvé une Pierre Ancestrale! En effet, je vénère la déesse Hylia.")); + // /*spanish*/¡Has encontrado una piedra espiritual! Es que le rindo culto a Nayru... + + hintTextTable[RHT_JUNK61] = HintText(CustomMessage("They say that a flying strike with a Deku Stick is no stronger than a grounded one.", + /*german*/ "", + /*french*/ "Selon moi, un coup de bâton sauté n'est pas meilleur qu'au sol.")); + // /*spanish*/Según dicen, los golpes aéreos con palos deku son tan fuertes como los normales. + + hintTextTable[RHT_JUNK62] = HintText(CustomMessage("Open your eyes.^Open your eyes.^Wake up, @.", + /*german*/ "", + /*french*/ "Réveille-toi...^Réveille-toi.^Ouvre les yeux, @.")); + // /*spanish*/Abre los ojos...^Abre los ojos...^Despierta, @... + + hintTextTable[RHT_JUNK63] = HintText(CustomMessage("They say that the Nocturne of Shadow can bring you very close to Ganon.", + /*german*/ "", + /*french*/ "Selon moi, le nocturne de l'ombre peut t'amener très près de Ganon.")); + // /*spanish*/Según dicen, el Nocturno de la sombra te puede acercar mucho a Ganon. + + hintTextTable[RHT_JUNK64] = HintText(CustomMessage("They say that Twinrova always casts the same spell the first three times.", + /*german*/ "", + /*french*/ "Selon moi, Twinrova lance toujours les mêmes trois premiers sorts.")); + // /*spanish*/Según dicen, Birova siempre lanza el mismo hechizo las tres primeras veces. + + hintTextTable[RHT_JUNK65] = HintText(CustomMessage("They say that the nightly builds may be unstable.", + /*german*/ "", + /*french*/ "Selon moi, les \"nightly builds\" peuvent être instables.")); + // /*spanish*/Según dicen, las últimas nightlies pueden llegar a ser algo inestables. + + hintTextTable[RHT_JUNK66] = HintText(CustomMessage("You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!", + /*german*/ "", + /*french*/ "Tu joues à un randomizer. Je suis aléatoire!^Voici un nombre aléatoire: #4#.&Bonne partie!")); + // /*spanish*/¡Estás jugando un Randomizer! ¡Yo también estoy aleatorizada!^Aquí tienes un número aleatorio: #8#.&¡Diviértete! + + hintTextTable[RHT_JUNK67] = HintText(CustomMessage("They say Ganondorf's bolts can be reflected with glass or steel.", + /*german*/ "", + /*french*/ "Selon moi, les éclairs de Ganon se reflètent sur l'acier et le verre.")); + // /*spanish*/Según dicen, puedes reflejar las esferas de energía de Ganondorf con cristal y acero. + + hintTextTable[RHT_JUNK68] = HintText(CustomMessage("They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, " + "boomerangs...^...rods, shovels, iron balls, angry bees...", + /*german*/ "", + /*french*/ "Selon moi, la queue de Ganon est vulnérable aux noix, flèches, épées, bombes, marteaux...^...bâtons, " + "graines, boomerangs...^...baguettes, pelles, boulets de fer, abeilles enragées...")); + // /*spanish*/Según dicen, la cola de Ganon es vulnerable a nueces, flechas, espadas, explosivos, + // martillos...^...palos, semillas, bumeráns...^...cetros, palas, bolas de hierro, abejas... + + hintTextTable[RHT_JUNK69] = HintText(CustomMessage("They say that you're wasting time reading this hint, but I disagree. Talk to me again!", + /*german*/ "", + /*french*/ "Selon moi... tu sais quoi? Parle-moi encore, et je te le dirai!")); + // /*spanish*/Según dicen, pierdes el tiempo en leer esta pista, pero no pienso igual. ¡Vuelve a hablarme, ya verás! + + hintTextTable[RHT_JUNK70] = HintText(CustomMessage("They say Ganondorf knows where to find the instrument of his doom.", + /*german*/ "", + /*french*/ "Selon moi, Ganondorf sait où il a caché son point faible.")); + // /*spanish*/Según dicen, Ganondorf sabe dónde hallar el instrumento de su perdición. + + hintTextTable[RHT_JUNK71] = HintText(CustomMessage("I heard @ is pretty good at Zelda.", + /*german*/ "", + /*french*/ "Apparemment, @ est super bon à Zelda.")); + // /*spanish*/He oído que a @ se le dan muy bien los Zelda. + + hintTextTable[RHT_JUNK72] = HintText(CustomMessage("Hi @, we've been trying to reach you about your car's extended warranty. ", + /*german*/ "", + /*french*/ "Bonjour, @. Vous avez une voiture? Vous savez, nous offrons des assurances abordables...")); + // /*spanish*/Buenas, @. Le llamamos para ofrecerle un nuevo seguro de hogar que puede pagar en cómodos plazos, sin + // intereses ni comisiones. + + hintTextTable[RHT_JUNK73] = HintText(CustomMessage("They say that the best weapon against Iron Knuckles is item 176.", + /*german*/ "", + /*french*/ "Selon moi, les hache-viandes sont vulnérables contre l'objet 176.")); + // /*spanish*/Según dicen, la mejor arma para enfrentarse a los Nudillos de hierro es el objeto 176. + + hintTextTable[RHT_JUNK74] = HintText(CustomMessage("They say that it's actually possible to beat the running man.", + /*german*/ "", + /*french*/ "Selon moi, il est possible de battre le coureur.&Donc, tu prends ton arc, et...")); + // /*spanish*/Según dicen, con mucha perseverancia puedes ganarle al corredor con la capucha de conejo. + + hintTextTable[RHT_JUNK75] = HintText(CustomMessage("They say that the stone-cold guardian of the Well is only present during work hours.", + /*german*/ "", + /*french*/ "Selon moi, le gardien de pierre du Puits quitte le soir pour aller se coucher.")); + // /*spanish*/Según dicen, la inmensa roca que bloquea el pozo solo trabaja en horas laborales. + + hintTextTable[RHT_JUNK76] = HintText(CustomMessage("They say this hint makes more sense in other languages.", + /*german*/ "", + /*french*/ "Selon moi, ces indices auraient pu être mieux traduits... Duh!")); + // /*spanish*/Según dicen, esta pista revela algo de vital importancia si cambias el idioma del juego... + + hintTextTable[RHT_JUNK77] = HintText(CustomMessage("BOK? No way.", + /*german*/ "", + /*french*/ "BD'accord? Hors de question.")); + // /*spanish*/¿BVale? Ni hablar. // ^ junk hints above are from 3drando // v junk hints below are new to soh rando @@ -2087,1436 +1777,1103 @@ void HintTable_Init() { #define HINT_TEXT_NEEDS_TRANSLATION_FR \ "Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!" - hintTable[RHT_JUNK78] = HintText::Junk({ - //obscure text - Text{"They say blarg...^...or at least briaguya does.", /*french*/"Tout ce que j'ai à dire, c'est blarg...^... 'fin c'est plutôt ce que briaguya dirait.", /*spanish*/"blarg"}, - }); - - hintTable[RHT_JUNK79] = HintText::Junk({ - //obscure text - Text{"They say this peace is what all true warriors strive for.", /*french*/"Selon moi, cette paix est ce pour quoi luttent tous les vrais guerriers.", /*spanish*/"blarg"}, - }); - - hintTable[RHT_JUNK80] = HintText::Junk({ - //obscure text - Text{"They say this ship is what all true gamers strive for.", /*french*/"Selon moi, cette version du port est ce pour quoi luttent tous les vrais gamers.", /*spanish*/"blarg"}, - }); - - hintTable[RHT_JUNK81] = HintText::Junk({ - //obscure text - Text{"They say that Glowsticks can be found in the Raveyard.", /*french*/"On peut trouver des Bâtons Lumineux sur le dancefloor du cimetière.", /*spanish*/"blarg"}, - }); - - hintTable[RHT_JUNK_WTC_1] = HintText::Junk({ - Text{ "They say %rthere are no more than 18&people on this island.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_2] = HintText::Junk({ - Text{ "They say I am one yet many", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_3] = HintText::Junk({ - Text{ "They say its all in the name of guiding&humanity down the right path.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_4] = HintText::Junk({ - Text{ "They say \"Repetition requested\"", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_5] = HintText::Junk({ - Text{ "They say %rThe red tells only the truth!", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_6] = HintText::Junk({ - Text{ "They say good tidings to you^my traitorous @", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_7] = HintText::Junk({ - Text{ "They say when the seagulls cried,&none were left alive.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_7] = HintText::Junk({ - Text{ "They say when the seagulls cried,&none were left alive.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_8] = HintText::Junk({ - Text{ "They say she is lying with the red letters!", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_9] = HintText::Junk({ - Text{ "They say we'll meet again,&when something else cries.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_10] = HintText::Junk({ - Text{ "They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of " - "the script...&will be me.\"", - HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_11] = HintText::Junk({ - Text{ "They say tea is best enjoyed...^\"\"With your fellow monsters.\"\"", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_WTC_12] = HintText::Junk({ - Text{ "They say I shall make you some black tea. With my own hands, not magic.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_1] = HintText::Junk({ - Text{ "They say you know I've kiboshed before...^and I will kibosh again.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_2] = HintText::Junk({ - Text{ "They say if relationship @ walks through that door,^they will KILL independent @.", - HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_3] = HintText::Junk({ - Text{ "They say you gotta have the BIG Salad.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_4] = HintText::Junk({ - Text{ "They say it's a festivus miracle", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_5] = HintText::Junk({ - Text{ "They say there are no houses in Tuscany to rent.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_6] = HintText::Junk({ - Text{ "They say my last boyfriend had a real&Kroner comprehension problem.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_7] = HintText::Junk({ - Text{ "They say it's a festivus miracle.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_8] = HintText::Junk({ - Text{ "They say Louis quit the importing&to focus on the exporting.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_9] = HintText::Junk({ - Text{ "They say no thanks, I can't drink coffee&late at night, it keeps me up.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_10] = HintText::Junk({ - Text{ "They say it's not a lie if you believe it.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_11] = HintText::Junk({ - Text{ "They say there was a second spitter.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_12] = HintText::Junk({ - Text{ "They say there was a second spitter.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_13] = HintText::Junk({ - Text{ "They say the jerk store called,^they're running out of YOU.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_14] = HintText::Junk({ - Text{ "They say when you look annoyed all the time,&people thing you are busy.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_15] = HintText::Junk({ - Text{ "They say when you look annoyed all the time,&people think you are busy.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_16] = HintText::Junk({ - Text{ "They say he fires people like its a bodily function.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_17] = HintText::Junk({ - Text{ "They say he threatened to move the ship to New Jersey&just to upset people.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_18] = HintText::Junk({ - Text{ "They say there was significant shrinkage.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_19] = HintText::Junk({ - Text{ "They say if it wasn't for the toilet there'd be no books.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_20] = HintText::Junk({ - Text{ "They say if it wasn't for the toilet there'd be no books.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_21] = HintText::Junk({ - Text{ "They say don't trust men in capes.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_22] = HintText::Junk({ - Text{ "They say @'s uncle works for Nintendo.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_23] = HintText::Junk({ - Text{ "They say @'s stole the marble rye.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_24] = HintText::Junk({ - Text{ "They say there is no better harmony&than the black and white cookie.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_25] = HintText::Junk({ - Text{ "They say @ hasn't vomited since 1983.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_26] = HintText::Junk({ - Text{ "They say you gotta have the early bird special.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_27] = HintText::Junk({ - Text{ "They say a donation has been made in your name&to the human fund.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_28] = HintText::Junk({ - Text{ "They say you want to be my latex salesman.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SEI_29] = HintText::Junk({ - Text{ "They say if every instinct you have is wrong...^... then the opposite would have to be right.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_OTR_MEANS_1] = HintText::Junk({ - Text{ "They say OTR stands for&Over the Rainbow", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_2] = HintText::Junk({ - Text{ "They say that OTR stands for&Onions, Tomatoes, and Radishes", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_3] = HintText::Junk({ - Text{ "They say that OTR stands for&Ocarina of Time Resources", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_4] = HintText::Junk({ - Text{ "They say that OTR stands for&Over the Road", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_5] = HintText::Junk({ - Text{ "They say that OTR stands for&Off the Record", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_6] = HintText::Junk({ - Text{ "They say that OTR stands for&Office of Tax and Revenue", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_7] = HintText::Junk({ - Text{ "They say OTR stands for&Over the Rainbow", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_8] = HintText::Junk({ - Text{ "They say that OTR stands for&Office of Trade Relations", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_9] = HintText::Junk({ - Text{ "They say that OTR stands for&Original Theatrical Release", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_10] = HintText::Junk({ - Text{ "They say that OTR stands for&Operational Test Requirement", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_11] = HintText::Junk({ - Text{ "They say that OTR stands for&Operational Trouble Report", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_12] = HintText::Junk({ - Text{ "They say that OTR stands for&Oxygen Transmission Rate", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_13] = HintText::Junk({ - Text{ "They say that OTR stands for&One Touch Recording", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_14] = HintText::Junk({ - Text{ "They say that OTR stands for&Olympic Torch Relay", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_15] = HintText::Junk({ - Text{ "They say that OTR stands for&Off the Rack", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_16] = HintText::Junk({ - Text{ "They say that OTR stands for&Overhead Transfer Rate", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_17] = HintText::Junk({ - Text{ "They say that OTR stands for&Operational TurnaRound", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_18] = HintText::Junk({ - Text{ "They say that OTR stands for&Opportunity to Recall", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_19] = HintText::Junk({ - Text{ "They say that OTR stands for&Operability Test Report", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_20] = HintText::Junk({ - Text{ "They say that OTR stands for&Overall Tuning Range", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_21] = HintText::Junk({ - Text{ "They say that OTR stands for&One Time Requisition", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_22] = HintText::Junk({ - Text{ "They say that OTR stands for&Oblivious to Reality", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_23] = HintText::Junk({ - Text{ "They say that OTR stands for&On the Run", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_24] = HintText::Junk({ - Text{ "They say that OTR stands for&On Time Reporting", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_25] = HintText::Junk({ - Text{ "They say that OTR stands for&Order to Receipt", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_26] = HintText::Junk({ - Text{ "They say that OTR stands for&Other Terrestrial Radio", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_27] = HintText::Junk({ - Text{ "They say that OTR stands for&On Target Reports", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_28] = HintText::Junk({ - Text{ "They say that OTR stands for&One Time Repair", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_29] = HintText::Junk({ - Text{ "They say that OTR stands for&Own the Room", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - hintTable[RHT_JUNK_OTR_MEANS_30] = HintText::Junk({ - Text{ "They say that OTR stands for&Online Text Repository", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_1] = HintText::Junk({ - Text{ "They say %gKenix%w isn't a developer...^...Just a PR guy", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_2] = HintText::Junk({ - Text {"They say... No", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg"}, - }); - - hintTable[RHT_JUNK_MISC_3] = HintText::Junk({ - Text{ "They say BIG RIGS: OTR", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" } - }); - - hintTable[RHT_JUNK_MISC_4] = HintText::Junk({ - Text{ "They say you wanted to see me %pMr. Kenix%w?", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_5] = HintText::Junk({ - Text{ "They say Louis once saw an&equals not get set equals", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_6] = HintText::Junk({ - Text{ "They say only you can find your rom.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_7] = HintText::Junk({ - Text{ "They say ZAPD is good software.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_8] = HintText::Junk({ - Text{ "They say you can encounter&a parascode in tall grass.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_9] = HintText::Junk({ - Text{ "They say the ship sails on March 32nd.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_10] = HintText::Junk({ - Text{ "They say bombing dodongos is fun.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_11] = HintText::Junk({ - Text{ "They say shopkeepers don't give credits.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_12] = HintText::Junk({ - Text{ "They say shopkeepers don't give credits.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_13] = HintText::Junk({ - Text{ "They say Malon is glitched.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_14] = HintText::Junk({ - Text{ "They say do I look like I know&what a DList is?", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_15] = HintText::Junk({ - Text{ "They say do I look like I know&what an AList is?", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_16] = HintText::Junk({ - Text{ "They say the king drinks enthusiastically", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_MISC_17] = HintText::Junk({ - Text{ "They say Rubies are on the path to&Lamp Oil, Rope, and Bombs", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_1] = HintText::Junk({ - Text{ "They say %rError. Human is dead, mismatch.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_2] = HintText::Junk({ - Text{ "They say this is the choice of the&steins gate.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_3] = HintText::Junk({ - Text{ "They say el psy kongroo.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_4] = HintText::Junk({ - Text{ "They say tutturu~.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - - hintTable[RHT_JUNK_SG_5] = HintText::Junk({ - Text{ "They say im not Christina!.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_6] = HintText::Junk({ - Text{ "They say you know where to find an IBN5100.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); - - hintTable[RHT_JUNK_SG_7] = HintText::Junk({ - Text{ "They say when you're on a chicken bender&grab a box of chicken tenders.", HINT_TEXT_NEEDS_TRANSLATION_FR, "blarg" }, - }); + hintTextTable[RHT_JUNK78] = HintText(CustomMessage("They say blarg...^...or at least briaguya does.", + /*german*/ "", + /*french*/ "Tout ce que j'ai à dire, c'est blarg...^... 'fin c'est plutôt ce que briaguya dirait.")); + // /*spanish*/blarg + + hintTextTable[RHT_JUNK79] = HintText(CustomMessage("They say this peace is what all true warriors strive for.", + /*german*/ "", + /*french*/ "Selon moi, cette paix est ce pour quoi luttent tous les vrais guerriers.")); + // /*spanish*/blarg - hintTable[RHT_JUNK_SG_8] = HintText::Junk({ - Text{ "Juicy Chicken #1! Wow!.", HINT_TEXT_NEEDS_TRANSLATION_FR, - "blarg" }, - }); + hintTextTable[RHT_JUNK80] = HintText(CustomMessage("They say this ship is what all true gamers strive for.", + /*german*/ "", + /*french*/ "Selon moi, cette version du port est ce pour quoi luttent tous les vrais gamers.")); + // /*spanish*/blarg + + hintTextTable[RHT_JUNK81] = HintText(CustomMessage("They say that Glowsticks can be found in the Raveyard.", + /*german*/ "", + /*french*/ "On peut trouver des Bâtons Lumineux sur le dancefloor du cimetière.")); + // /*spanish*/blarg + + hintTextTable[RHT_JUNK_WTC_1] = HintText(CustomMessage("They say %rthere are no more than 18&people on this island.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_2] = HintText(CustomMessage("They say I am one yet many", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_3] = HintText(CustomMessage("They say its all in the name of guiding&humanity down the right path.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_4] = HintText(CustomMessage("They say \"Repetition requested\"", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_5] = HintText(CustomMessage("They say %rThe red tells only the truth!", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_6] = HintText(CustomMessage("They say good tidings to you^my traitorous @", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_7] = HintText(CustomMessage("They say when the seagulls cried,&none were left alive.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_8] = HintText(CustomMessage("They say she is lying with the red letters!", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_9] = HintText(CustomMessage("They say we'll meet again,&when something else cries.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_10] = HintText(CustomMessage("They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of " + "the script...&will be me.\"", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_WTC_11] = HintText(CustomMessage("They say tea is best enjoyed...^\"\"With your fellow monsters.\"\"", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + + hintTextTable[RHT_JUNK_WTC_12] = HintText(CustomMessage("They say I shall make you some black tea. With my own hands, not magic.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_1] = HintText(CustomMessage("They say you know I've kiboshed before...^and I will kibosh again.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_2] = HintText(CustomMessage("They say if relationship @ walks through that door,^they will KILL independent @.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_3] = HintText(CustomMessage("They say you gotta have the BIG Salad.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_4] = HintText(CustomMessage("They say it's a festivus miracle", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_5] = HintText(CustomMessage("They say there are no houses in Tuscany to rent.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_6] = HintText(CustomMessage("They say my last boyfriend had a real&Kroner comprehension problem.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_7] = HintText(CustomMessage("They say it's a festivus miracle.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_8] = HintText(CustomMessage("They say Louis quit the importing&to focus on the exporting.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_9] = HintText(CustomMessage("They say no thanks, I can't drink coffee&late at night, it keeps me up.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_10] = HintText(CustomMessage("They say it's not a lie if you believe it.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_11] = HintText(CustomMessage("They say there was a second spitter.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_12] = HintText(CustomMessage("They say there was a second spitter.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_13] = HintText(CustomMessage("They say the jerk store called,^they're running out of YOU.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_14] = HintText(CustomMessage("They say when you look annoyed all the time,&people thing you are busy.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_15] = HintText(CustomMessage("They say when you look annoyed all the time,&people think you are busy.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_16] = HintText(CustomMessage("They say he fires people like its a bodily function.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_17] = HintText(CustomMessage("They say he threatened to move the ship to New Jersey&just to upset people.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_18] = HintText(CustomMessage("They say there was significant shrinkage.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_19] = HintText(CustomMessage("They say if it wasn't for the toilet there'd be no books.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_20] = HintText(CustomMessage("They say if it wasn't for the toilet there'd be no books.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_21] = HintText(CustomMessage("They say don't trust men in capes.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_22] = HintText(CustomMessage("They say @'s uncle works for Nintendo.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_23] = HintText(CustomMessage("They say @'s stole the marble rye.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_24] = HintText(CustomMessage("They say there is no better harmony&than the black and white cookie.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_25] = HintText(CustomMessage("They say @ hasn't vomited since 1983.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_26] = HintText(CustomMessage("They say you gotta have the early bird special.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_27] = HintText(CustomMessage("They say a donation has been made in your name&to the human fund.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_28] = HintText(CustomMessage("They say you want to be my latex salesman.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SEI_29] = HintText(CustomMessage("They say if every instinct you have is wrong...^... then the opposite would have to be right.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_1] = HintText(CustomMessage("They say OTR stands for&Over the Rainbow", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_2] = HintText(CustomMessage("They say that OTR stands for&Onions, Tomatoes, and Radishes", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_3] = HintText(CustomMessage("They say that OTR stands for&Ocarina of Time Resources", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_4] = HintText(CustomMessage("They say that OTR stands for&Over the Road", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_5] = HintText(CustomMessage("They say that OTR stands for&Off the Record", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_6] = HintText(CustomMessage("They say that OTR stands for&Office of Tax and Revenue", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_7] = HintText(CustomMessage("They say OTR stands for&Over the Rainbow", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_8] = HintText(CustomMessage("They say that OTR stands for&Office of Trade Relations", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_9] = HintText(CustomMessage("They say that OTR stands for&Original Theatrical Release", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_10] = HintText(CustomMessage("They say that OTR stands for&Operational Test Requirement", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_11] = HintText(CustomMessage("They say that OTR stands for&Operational Trouble Report", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_12] = HintText(CustomMessage("They say that OTR stands for&Oxygen Transmission Rate", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_13] = HintText(CustomMessage("They say that OTR stands for&One Touch Recording", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_14] = HintText(CustomMessage("They say that OTR stands for&Olympic Torch Relay", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_15] = HintText(CustomMessage("They say that OTR stands for&Off the Rack", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_16] = HintText(CustomMessage("They say that OTR stands for&Overhead Transfer Rate", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_17] = HintText(CustomMessage("They say that OTR stands for&Operational TurnaRound", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_18] = HintText(CustomMessage("They say that OTR stands for&Opportunity to Recall", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_19] = HintText(CustomMessage("They say that OTR stands for&Operability Test Report", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_20] = HintText(CustomMessage("They say that OTR stands for&Overall Tuning Range", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_21] = HintText(CustomMessage("They say that OTR stands for&One Time Requisition", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_22] = HintText(CustomMessage("They say that OTR stands for&Oblivious to Reality", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_23] = HintText(CustomMessage("They say that OTR stands for&On the Run", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_24] = HintText(CustomMessage("They say that OTR stands for&On Time Reporting", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_25] = HintText(CustomMessage("They say that OTR stands for&Order to Receipt", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_26] = HintText(CustomMessage("They say that OTR stands for&Other Terrestrial Radio", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_27] = HintText(CustomMessage("They say that OTR stands for&On Target Reports", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_28] = HintText(CustomMessage("They say that OTR stands for&One Time Repair", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_29] = HintText(CustomMessage("They say that OTR stands for&Own the Room", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_OTR_MEANS_30] = HintText(CustomMessage("They say that OTR stands for&Online Text Repository", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_1] = HintText(CustomMessage("They say #Kenix# isn't a developer...^...Just a PR guy", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR, + {QM_GREEN})); + + hintTextTable[RHT_JUNK_MISC_2] = HintText(CustomMessage("They say... No", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_3] = HintText(CustomMessage("They say BIG RIGS: OTR", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_4] = HintText(CustomMessage("They say you wanted to see me #Mr. Kenix#?", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR, + {QM_PINK})); + + hintTextTable[RHT_JUNK_MISC_5] = HintText(CustomMessage("They say Louis once saw an&equals not get set equals", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_6] = HintText(CustomMessage("They say only you can find your rom.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_7] = HintText(CustomMessage("They say ZAPD is good software.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_8] = HintText(CustomMessage("They say you can encounter&a parascode in tall grass.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_9] = HintText(CustomMessage("They say the ship sails on March 32nd.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_10] = HintText(CustomMessage("They say bombing dodongos is fun.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_11] = HintText(CustomMessage("They say shopkeepers don't give credits.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_12] = HintText(CustomMessage("They say shopkeepers don't give credits.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_13] = HintText(CustomMessage("They say Malon is glitched.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_14] = HintText(CustomMessage("They say do I look like I know&what a DList is?", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_15] = HintText(CustomMessage("They say do I look like I know&what an AList is?", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_16] = HintText(CustomMessage("They say the king drinks enthusiastically", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_MISC_17] = HintText(CustomMessage("They say Rubies are on the path to&Lamp Oil, Rope, and Bombs", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_1] = HintText(CustomMessage("They say %rError. Human is dead, mismatch.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_2] = HintText(CustomMessage("They say this is the choice of the&steins gate.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_3] = HintText(CustomMessage("They say el psy kongroo.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_4] = HintText(CustomMessage("They say tutturu~.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_5] = HintText(CustomMessage("They say im not Christina!.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_6] = HintText(CustomMessage("They say you know where to find an IBN5100.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_7] = HintText(CustomMessage("They say when you're on a chicken bender&grab a box of chicken tenders.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); + + hintTextTable[RHT_JUNK_SG_8] = HintText(CustomMessage("Juicy Chicken #1! Wow!.", + /*german*/ "", + /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR)); /*-------------------------- | DUNGEON HINT TEXT | ---------------------------*/ - hintTable[RHT_DEKU_TREE] = HintText::DungeonName( - { - // obscure text - Text{ "an ancient tree", /*french*/ "le vieil arbre", /*spanish*/ "un ancestral árbol" }, - }, - {}, - // clear text - Text{ "Deku Tree", /*french*/ "l'Arbre Mojo", /*spanish*/ "el Gran Árbol Deku" }); + + hintTextTable[RHT_DEKU_TREE] = HintText(CustomMessage("Deku Tree", + /*german*/ "", + /*french*/ "l'Arbre Mojo"), + // /*spanish*/el Gran Árbol Deku + {}, + {CustomMessage("an ancient tree", + /*german*/ "", + /*french*/ "le vieil arbre")}); + // /*spanish*/un ancestral árbol - hintTable[RHT_DODONGOS_CAVERN] = HintText::DungeonName( - { - // obscure text - Text{ "an immense cavern", /*french*/ "l'immense caverne", /*spanish*/ "una descomunal cueva" }, - }, - {}, - // clear text - Text{ "Dodongo's Cavern", /*french*/ "la Caverne Dodongo", /*spanish*/ "la Cueva de los Dodongos" }); + hintTextTable[RHT_DODONGOS_CAVERN] = HintText(CustomMessage("Dodongo's Cavern", + /*german*/ "", + /*french*/ "la Caverne Dodongo"), + // /*spanish*/la Cueva de los Dodongos + {}, + {CustomMessage("an immense cavern", + /*german*/ "", + /*french*/ "l'immense caverne")}); + // /*spanish*/una descomunal cueva - hintTable[RHT_JABU_JABUS_BELLY] = HintText::DungeonName( - { - // obscure text - Text{ "the belly of a deity", /*french*/ "le ventre d'un gardien", - /*spanish*/ "la tripa de cierta deidad" }, - }, - {}, - // clear text - Text{ "Jabu-Jabu's Belly", /*french*/ "le Ventre de Jabu-Jabu", /*spanish*/ "tripa de Jabu-Jabu" }); + hintTextTable[RHT_JABU_JABUS_BELLY] = HintText(CustomMessage("Jabu-Jabu's Belly", + /*german*/ "", + /*french*/ "le Ventre de Jabu-Jabu"), + // /*spanish*/tripa de Jabu-Jabu + {}, + {CustomMessage("the belly of a deity", + /*german*/ "", + /*french*/ "le ventre d'un gardien")}); + // /*spanish*/la tripa de cierta deidad - hintTable[RHT_FOREST_TEMPLE] = HintText::DungeonName( - { - // obscure text - Text{ "a deep forest", /*french*/ "la profonde forêt", /*spanish*/ "las profundidades del bosque" }, - }, - {}, - // clear text - Text{ "Forest Temple", /*french*/ "le Temple de la Forêt", /*spanish*/ "el Templo del Bosque" }); + hintTextTable[RHT_FOREST_TEMPLE] = HintText(CustomMessage("Forest Temple", + /*german*/ "", + /*french*/ "le Temple de la Forêt"), + // /*spanish*/el Templo del Bosque + {}, + {CustomMessage("a deep forest", + /*german*/ "", + /*french*/ "la profonde forêt")}); + // /*spanish*/las profundidades del bosque - hintTable[RHT_FIRE_TEMPLE] = HintText::DungeonName( - { - // obscure text - Text{ "a high mountain", /*french*/ "la grande montagne", /*spanish*/ "una alta montaña" }, - }, - {}, - // clear text - Text{ "Fire Temple", /*french*/ "le Temple du Feu", /*spanish*/ "el Templo del Fuego" }); + hintTextTable[RHT_FIRE_TEMPLE] = HintText(CustomMessage("Fire Temple", + /*german*/ "", + /*french*/ "le Temple du Feu"), + // /*spanish*/el Templo del Fuego + {}, + {CustomMessage("a high mountain", + /*german*/ "", + /*french*/ "la grande montagne")}); + // /*spanish*/una alta montaña - hintTable[RHT_WATER_TEMPLE] = HintText::DungeonName( - { - // obscure text - Text{ "a vast lake", /*french*/ "le vaste lac", /*spanish*/ "un lago inmenso" }, - }, - {}, - // clear text - Text{ "Water Temple", /*french*/ "le Temple de l'Eau", /*spanish*/ "el Templo del Agua" }); + hintTextTable[RHT_WATER_TEMPLE] = HintText(CustomMessage("Water Temple", + /*german*/ "", + /*french*/ "le Temple de l'Eau"), + // /*spanish*/el Templo del Agua + {}, + {CustomMessage("a vast lake", + /*german*/ "", + /*french*/ "le vaste lac")}); + // /*spanish*/un lago inmenso - hintTable[RHT_SPIRIT_TEMPLE] = HintText::DungeonName( - { - // obscure text - Text{ "the goddess of the sand", /*french*/ "la déesse des sables", /*spanish*/ "la diosa de las arenas" }, - }, - {}, - // clear text - Text{ "Spirit Temple", /*french*/ "le Temple de l'Esprit", /*spanish*/ "el Templo del Espíritu" } + hintTextTable[RHT_SPIRIT_TEMPLE] = HintText(CustomMessage("Spirit Temple", + /*german*/ "", + /*french*/ "le Temple de l'Esprit"), + // /*spanish*/el Templo del Espíritu + {}, + {CustomMessage("the goddess of the sand", + /*german*/ "", + /*french*/ "la déesse des sables")}); + // /*spanish*/la diosa de las arenas - ); + hintTextTable[RHT_SHADOW_TEMPLE] = HintText(CustomMessage("Shadow Temple", + /*german*/ "", + /*french*/ "le Temple de l'Ombre"), + // /*spanish*/el Templo de las Sombras + {}, + {CustomMessage("the house of the dead", + /*german*/ "", + /*french*/ "la maison des morts")}); + // /*spanish*/la casa de la muerte - hintTable[RHT_SHADOW_TEMPLE] = HintText::DungeonName( - { - // obscure text - Text{ "the house of the dead", /*french*/ "la maison des morts", /*spanish*/ "la casa de la muerte" }, - }, - {}, - // clear text - Text{ "Shadow Temple", /*french*/ "le Temple de l'Ombre", /*spanish*/ "el Templo de las Sombras" }); + hintTextTable[RHT_ICE_CAVERN] = HintText(CustomMessage("Ice Cavern", + /*german*/ "", + /*french*/ "la caverne de glace"), + // /*spanish*/la caverna de hielo + {}, + {CustomMessage("a frozen maze", + /*german*/ "", + /*french*/ "le dédale glacé")}); + // /*spanish*/un gélido laberinto - hintTable[RHT_ICE_CAVERN] = HintText::DungeonName( - { - // obscure text - Text{ "a frozen maze", /*french*/ "le dédale glacé", /*spanish*/ "un gélido laberinto" }, - }, - {}, - // clear text - Text{ "Ice Cavern", /*french*/ "la caverne de glace", /*spanish*/ "la caverna de hielo" }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL] = HintText(CustomMessage("Bottom of the Well", + /*german*/ "", + /*french*/ "le fonds du Puits"), + // /*spanish*/el fondo del pozo + {}, + {CustomMessage("a shadow\'s prison", + /*german*/ "", + /*french*/ "la prison d'une ombre")}); + // /*spanish*/la prisión de las sombras - hintTable[RHT_BOTTOM_OF_THE_WELL] = HintText::DungeonName( - { - // obscure text - Text{ "a shadow\'s prison", /*french*/ "la prison d'une ombre", /*spanish*/ "la prisión de las sombras" }, - }, - {}, - // clear text - Text{ "Bottom of the Well", /*french*/ "le fonds du Puits", /*spanish*/ "el fondo del pozo" }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND] = HintText(CustomMessage("Gerudo Training Grounds", + /*german*/ "", + /*french*/ "le Gymnase Gerudo"), + // /*spanish*/el Centro de Instrucción Gerudo + {}, + {CustomMessage("the test of thieves", + /*german*/ "", + /*french*/ "l'épreuve des voleurs")}); + // /*spanish*/la prueba de las bandidas - hintTable[RHT_GERUDO_TRAINING_GROUND] = HintText::DungeonName( - { - // obscure text - Text{ "the test of thieves", /*french*/ "l'épreuve des voleurs", /*spanish*/ "la prueba de las bandidas" }, - }, - {}, - // clear text - Text{ "Gerudo Training Grounds", /*french*/ "le Gymnase Gerudo", - /*spanish*/ "el Centro de Instrucción Gerudo" }); - - hintTable[RHT_GANONS_CASTLE] = HintText::DungeonName( - { - // obscure text - Text{ "a conquered citadel", /*french*/ "la citadelle assiégée", /*spanish*/ "una conquistada ciudadela" }, - }, - {}, - // clear text - Text{ "Inside Ganon's Castle", /*french*/ "l'intérieur du Château de Ganon", - /*spanish*/ "el interior del Castillo de Ganon" }); + hintTextTable[RHT_GANONS_CASTLE] = HintText(CustomMessage("Inside Ganon's Castle", + /*german*/ "", + /*french*/ "l'intérieur du Château de Ganon"), + // /*spanish*/el interior del Castillo de Ganon + {}, + {CustomMessage("a conquered citadel", + /*german*/ "", + /*french*/ "la citadelle assiégée")}); + // /*spanish*/una conquistada ciudadela /*-------------------------- | BOSS HINT TEXT | ---------------------------*/ - hintTable[RHT_QUEEN_GOHMA] = HintText::Boss({ - // obscure text - Text{"the #Parasitic Armored Arachnid# holds", /*french*/"le #monstre insectoïde géant# possède", /*spanish*/"el #arácnido parasitario acorazado# porta"}, - }, {}, - //clear text - Text{"#Queen Gohma# holds", /*french*/"la #Reine Gohma# possède", /*spanish*/"la #Reina Goma# porta"}); + hintTextTable[RHT_QUEEN_GOHMA] = HintText(CustomMessage("#Queen Gohma# holds", + /*german*/ "", + /*french*/ "la #Reine Gohma# possède"), + // /*spanish*/la #Reina Goma# porta + {}, + {CustomMessage("the #Parasitic Armored Arachnid# holds", + /*german*/ "", + /*french*/ "le #monstre insectoïde géant# possède")}); + // /*spanish*/el #arácnido parasitario acorazado# porta - hintTable[RHT_KING_DODONGO] = HintText::Boss({ - //obscure text - Text{"the #Infernal Dinosaur# holds", /*french*/"le #dinosaure infernal# possède", /*spanish*/"el #dinosaurio infernal# porta"}, - }, {}, - //clear text - Text{"#King Dodongo# holds", /*french*/"le #Roi Dodongo# possède", /*spanish*/"el #Rey Dodongo# porta"}); + hintTextTable[RHT_KING_DODONGO] = HintText(CustomMessage("#King Dodongo# holds", + /*german*/ "", + /*french*/ "le #Roi Dodongo# possède"), + // /*spanish*/el #Rey Dodongo# porta + {}, + {CustomMessage("the #Infernal Dinosaur# holds", + /*german*/ "", + /*french*/ "le #dinosaure infernal# possède")}); + // /*spanish*/el #dinosaurio infernal# porta - hintTable[RHT_BARINADE] = HintText::Boss({ - //obscure text - Text{"the #Bio-Electric Anemone# holds", /*french*/"l'#anémone bioélectrique# possède", /*spanish*/"la #anémona bioeléctrica# porta"}, - }, {}, - //clear text - Text{"#Barinade# holds", /*french*/"#Barinade# possède", /*spanish*/"#Barinade# porta"}); + hintTextTable[RHT_BARINADE] = HintText(CustomMessage("#Barinade# holds", + /*german*/ "", + /*french*/ "#Barinade# possède"), + // /*spanish*/#Barinade# porta + {}, + {CustomMessage("the #Bio-Electric Anemone# holds", + /*german*/ "", + /*french*/ "l'#anémone bioélectrique# possède")}); + // /*spanish*/la #anémona bioeléctrica# porta - hintTable[RHT_PHANTOM_GANON] = HintText::Boss({ - //obscure text - Text{"the #Evil Spirit from Beyond# holds", /*french*/"l'#esprit maléfique de l'au-delà# possède", /*spanish*/"el #espíritu maligno de ultratumba# porta"}, - }, {}, - //clear text - Text{"#Phantom Ganon# holds", /*french*/"#Ganon Spectral# possède", /*spanish*/"#Ganon Fantasma# porta"}); + hintTextTable[RHT_PHANTOM_GANON] = HintText(CustomMessage("#Phantom Ganon# holds", + /*german*/ "", + /*french*/ "#Ganon Spectral# possède"), + // /*spanish*/#Ganon Fantasma# porta + {}, + {CustomMessage("the #Evil Spirit from Beyond# holds", + /*german*/ "", + /*french*/ "l'#esprit maléfique de l'au-delà# possède")}); + // /*spanish*/el #espíritu maligno de ultratumba# porta - hintTable[RHT_VOLVAGIA] = HintText::Boss({ - //obscure text - Text{"the #Subterranean Lava Dragon# holds", /*french*/"le #dragon des profondeurs# possède", /*spanish*/"el #dragón de lava subterráneo# porta"}, - }, {}, - //clear text - Text{"#Volvagia# holds", /*french*/"#Volvagia# possède", /*spanish*/"#Volvagia# porta"}); + hintTextTable[RHT_VOLVAGIA] = HintText(CustomMessage("#Volvagia# holds", + /*german*/ "", + /*french*/ "#Volvagia# possède"), + // /*spanish*/#Volvagia# porta + {}, + {CustomMessage("the #Subterranean Lava Dragon# holds", + /*german*/ "", + /*french*/ "le #dragon des profondeurs# possède")}); + // /*spanish*/el #dragón de lava subterráneo# porta - hintTable[RHT_MORPHA] = HintText::Boss({ - //obscure text - Text{"the #Giant Aquatic Amoeba# holds", /*french*/"l'#amibe aquatique géante# possède", /*spanish*/"la #ameba acuática gigante# porta"}, - }, {}, - //clear text - Text{"#Morpha# holds", /*french*/"#Morpha# possède", /*spanish*/"#Morpha# porta"}); + hintTextTable[RHT_MORPHA] = HintText(CustomMessage("#Morpha# holds", + /*german*/ "", + /*french*/ "#Morpha# possède"), + // /*spanish*/#Morpha# porta + {}, + {CustomMessage("the #Giant Aquatic Amoeba# holds", + /*german*/ "", + /*french*/ "l'#amibe aquatique géante# possède")}); + // /*spanish*/la #ameba acuática gigante# porta - hintTable[RHT_BONGO_BONGO] = HintText::Boss({ - //obscure text - Text{"the #Phantom Shadow Beast# holds", /*french*/"le #monstre de l'ombre# possède", /*spanish*/"la #alimaña oscura espectral# porta"}, - }, {}, - //clear text - Text{"#Bongo Bongo# holds", /*french*/"#Bongo Bongo# possède", /*spanish*/"#Bongo Bongo# porta"}); - - hintTable[RHT_TWINROVA] = HintText::Boss({ - //obscure text - Text{"the #Sorceress Sisters# hold", /*french*/"#les sorcières jumelles# possède", /*spanish*/"las #hermanas hechiceras# portan"}, - }, {}, - //clear text - Text{"#Twinrova# holds", /*french*/"#Twinrova# possède", /*spanish*/"#Birova# porta"}); - // - // [RHT_LINKS_POCKET_BOSS] = HintText::Boss({ - // //obscure text - // Text{"#@'s pocket# rewards", /*french*/"#@ débute avec#", /*spanish*/"el #bolsillo de @# - // premia con"}, - // }, - // //clear text - // Text{"#@ already has#", /*french*/"#@ a déjà#", /*spanish*/"el #bolsillo de @ ya - // tiene#"} - // ); + hintTextTable[RHT_BONGO_BONGO] = HintText(CustomMessage("#Bongo Bongo# holds", + /*german*/ "", + /*french*/ "#Bongo Bongo# possède"), + // /*spanish*/#Bongo Bongo# porta + {}, + {CustomMessage("the #Phantom Shadow Beast# holds", + /*german*/ "", + /*french*/ "le #monstre de l'ombre# possède")}); + // /*spanish*/la #alimaña oscura espectral# porta + hintTextTable[RHT_TWINROVA] = HintText(CustomMessage("#Twinrova# holds", + /*german*/ "", + /*french*/ "#Twinrova# possède"), + // /*spanish*/#Birova# porta + {}, + {CustomMessage("the #Sorceress Sisters# hold", + /*german*/ "", + /*french*/ "#les sorcières jumelles# possède")}); + // /*spanish*/las #hermanas hechiceras# portan /*-------------------------- | BRIDGE HINT TEXT | ---------------------------*/ - hintTable[RHT_BRIDGE_OPEN_HINT] = HintText::Bridge({ - // obscure text - Text{ "The awakened ones have #already created a bridge# to the castle where the evil dwells.", - /*french*/ "Les êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.", - /*spanish*/ "Los sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.", - /*german*/"Die Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloss gelegt#..." }, - }); + hintTextTable[RHT_BRIDGE_OPEN_HINT] = HintText(CustomMessage("$lThe awakened ones have #already created a bridge# to the castle where the evil dwells.^", + /*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloss gelegt#...^", + /*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^", + {QM_LBLUE})); + // /*spanish*/$lLos sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.^ - hintTable[RHT_BRIDGE_VANILLA_HINT] = HintText::Bridge({ - // obscure text - Text{ "The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.", - /*french*/ - "Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.", - /*spanish*/ - "Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto " - "a la #flecha de luz#.", - /*german*/"Die Weisen werden darauf warten, dass der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt." }, - }); - hintTable[RHT_BRIDGE_STONES_HINT] = HintText::Bridge({ - // obscure text singular plural - Text{ - "The awakened ones will await for the Hero to collect #%d |Spiritual Stone|Spiritual Stones|#.", - /*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Pierre Ancestrale|Pierres Ancestrales|#.", - /*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |piedra espiritual|piedras espirituales|#.", - /*german*/"Die Weisen werden darauf warten, dass der Held #%d |Heiligen Stein|Heilige Steine|# sammelt." }, - }); + hintTextTable[RHT_BRIDGE_VANILLA_HINT] = HintText(CustomMessage("$6The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.^", + /*german*/ "$6Die Weisen werden darauf warten, dass der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt.^", + /*french*/ "$6Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.^", + {QM_RED, QM_YELLOW})); + // /*spanish*/$6Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto + // a la #flecha de luz#.^ - hintTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText::Bridge({ - // obscure text singular plural - Text{ "The awakened ones will await for the Hero to collect #%d |Medallion|Medallions|#.", - /*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Médaillon|Médaillons|#.", - /*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |medallón|medallones|#.", - /*german*/"Die Weisen werden darauf warten, dass der Held #%d |Amulett|Amulette|# sammelt." }, - }); + hintTextTable[RHT_BRIDGE_STONES_HINT] = HintText(CustomMessage("$0The awakened ones will await for the Hero to collect #[[d]] Spiritual Stone||s|#.^", + /*german*/ "$0Die Weisen werden darauf warten, dass der Held #[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^", + /*french*/ "$0Les êtres de sagesse attendront le héros muni de #[[d]] |Pierre Ancestrale|Pierres Ancestrales|#.^", + {QM_BLUE})); + // /*spanish*/$0Los sabios aguardarán a que el héroe&obtenga #[[d]] |piedra espiritual|piedras espirituales|#.^ - hintTable[RHT_BRIDGE_REWARDS_HINT] = HintText::Bridge({ - // obscure text singular plural - Text{ "The awakened ones will await for the Hero to collect #%d |Spiritual Stone or Medallion|Spiritual Stones " - "and Medallions|#.", - /*french*/ - "Les êtres de sagesse attendront le héros muni de #%d |Pierre Ancestrale ou Médaillon|Pierres Ancestrales ou Médaillons|#.", - /*spanish*/ - "Los sabios aguardarán a que el héroe obtenga #%d |piedra espiritual o medallón|piedras espirtuales y " - "medallones|#.", - /*german*/"Die Weisen werden darauf warten, dass der Held #%d |Heiligen Stein oder Amulett|Heilige Steine oder Amulette|# sammelt." }, - }); + hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText(CustomMessage("$8The awakened ones will await for the Hero to collect #[[d]] Medallion||s|#.^", + /*german*/ "$8Die Weisen werden darauf warten, dass der Held #[[d]] Amulett||e|# sammelt.^", + /*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^", + {QM_RED})); + // /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^ - hintTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText::Bridge({ - // obscure text singular plural - Text{ "The awakened ones will await for the Hero to conquer #%d |Dungeon|Dungeons|#.", - /*french*/ "Les êtres de sagesse attendront la conquête de #%d |Donjon|Donjons|#.", - /*spanish*/ "Los sabios aguardarán a que el héroe complete #%d |mazmorra|mazmorras|#.", - /*german*/"Die Weisen werden darauf warten, dass der Held #%d |Labyrinth|Labyrinthe|# abschließt." }, - }); + hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|" + "#Spiritual Stones# and #Medallions#|.^", + /*german*/ "$CDie Weisen werden darauf warten, dass der Held #[[d]]# |#Heiligen Stein# oder #Amulett#|" + "#Heilige Steine# oder #Amulette#| sammelt.^", + /*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#" + "|#Pierres Ancestrales# ou #Médaillons#|.^", + {QM_YELLOW, QM_BLUE, QM_RED})); + // /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#| + //#piedras espirtuales# y #medallones#|.^ - hintTable[RHT_BRIDGE_TOKENS_HINT] = HintText::Bridge({ - // obscure text - Text{ "The awakened ones will await for the Hero to collect #%d |Gold Skulltula Token|Gold Skulltula Tokens|#.", - /*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Symbole|Symboles| de Skulltula d'or#.", - /*spanish*/ "Los sabios aguardarán a que el héroe obtenga #%d |símbolo|símbolos| de skulltula dorada#.", - /*german*/"Die Weisen werden darauf warten, dass der Held #%d |Skulltula-Symbol|Skulltula-Symbole|# sammelt." }, - }); + hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^", + /*german*/ "$mDie Weisen werden darauf warten, dass der Held #[[d]] Labyrinth||e|# abschließt.^", + /*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^", + {QM_PINK})); + // /*spanish*/$mLos sabios aguardarán a que el héroe complete #[[d]] mazmorra||s|#.^ + + hintTextTable[RHT_BRIDGE_TOKENS_HINT] = HintText(CustomMessage("$sThe awakened ones will await for the Hero to collect #[[d]] Gold Skulltula Token||s|#.^", + /*german*/ "$sDie Weisen werden darauf warten, dass der Held #[[d]] Skulltula-Symbol||e|# sammelt.^", + /*french*/ "$sLes êtres de sagesse attendront le héros muni de #[[d]] Symbole||s| de Skulltula d'or#.^", + {QM_YELLOW})); + // /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^ + + hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^", + {QM_GREEN})); - hintTable[RHT_BRIDGE_GREG_HINT] = HintText::Bridge({ - // obscure text - Text{ "The awakened ones will await for the Hero to find %gGreg%w.", - /*french*/ "The awakened ones will await for the Hero to find %gGreg%w.", - /*spanish*/ "The awakened ones will await for the Hero to find %gGreg%w." }, - }); /*-------------------------- | GANON BOSS KEY HINT TEXT | ---------------------------*/ - hintTable[RHT_GANON_BK_START_WITH_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be #given from the start#.", - /*french*/ "Aussi, la #clé du Malin# sera #possession même du héros#.", - /*spanish*/ "Y obtendrás la llave del #señor del mal# desde el #inicio#.", - /*german*/"Und der #Schlüssel des Bösen#, wird #von Anfang an, im Besitz des Helden# sein." }, - }); + hintTextTable[RHT_GANON_BK_START_WITH_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be #given from the start#.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird #von Anfang an, im Besitz des Helden# sein.^", + /*french*/ "$bAussi, la #clé du Malin# sera #possession même du héros#.^", + {QM_PINK, QM_LBLUE})); + // /*spanish*/$bY obtendrás la llave del #señor del mal# desde el #inicio#.^ - hintTable[RHT_GANON_BK_VANILLA_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be kept in a big chest #inside its tower#.", - /*french*/ "Aussi, la #clé du Malin# sera encoffrée #dans sa tour#.", - /*spanish*/ "Y la llave del #señor del mal# aguardará en un gran cofre de #su torre#.", - /*german*/"Und der #Schlüssel des Bösen#, wird in der großen Truhe #im Teufelsturm# zu finden sein." }, - }); + hintTextTable[RHT_GANON_BK_VANILLA_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be kept in a big chest #inside its tower#.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird in der großen Truhe #im Teufelsturm# zu finden sein.^", + /*french*/ "$bAussi, la #clé du Malin# sera encoffrée #dans sa tour#.^", + {QM_PINK, QM_LBLUE})); + // /*spanish*/$bY la llave del #señor del mal# aguardará en un gran cofre de #su torre#.^ - hintTable[RHT_GANON_BK_OWN_DUNGEON_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be hidden somewhere #inside its castle#.", - /*french*/ "Aussi, la #clé du Malin# sera cachée #dans son vaste château#.", - /*spanish*/ "Y la llave del #señor del mal# aguardará en #algún lugar de su castillo#.", - /*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Ganons Schloss# zu finden sein." }, - }); + hintTextTable[RHT_GANON_BK_OWN_DUNGEON_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be hidden somewhere #inside its castle#.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Ganons Schloss# zu finden sein.^", + /*french*/ "$bAussi, la #clé du Malin# sera cachée #dans son vaste château#.^", + {QM_PINK, QM_PINK})); + // /*spanish*/$bY la llave del #señor del mal# aguardará en #algún lugar de su castillo#.^ - hintTable[RHT_GANON_BK_OVERWORLD_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be hidden #outside of dungeons# in Hyrule.", - /*french*/ "Aussi, la #clé du Malin# se trouve #hors des donjons# d'Hyrule.", - /*spanish*/ "Y la llave del #señor del mal# aguardará #fuera de las mazmorras# de Hyrule.", - /*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, außerhalb von Labyrinthen# zu finden sein." }, - }); + hintTextTable[RHT_GANON_BK_OVERWORLD_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be hidden #outside of dungeons# in Hyrule.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, außerhalb von Labyrinthen# zu finden sein.^", + /*french*/ "$bAussi, la #clé du Malin# se trouve #hors des donjons# d'Hyrule.^", + {QM_PINK, QM_GREEN})); + // /*spanish*/$bY la llave del #señor del mal# aguardará #fuera de las mazmorras# de Hyrule.^ - hintTable[RHT_GANON_BK_ANY_DUNGEON_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be hidden #inside a dungeon# in Hyrule.", - /*french*/ "Aussi, la #clé du Malin# se trouve #dans un donjon# d'Hyrule.", - /*spanish*/ "Y la llave del #señor del mal# aguardará #en una mazmorra# de Hyrule.", - /*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, innerhalb eines Labyrinths# zu finden sein." }, - }); + hintTextTable[RHT_GANON_BK_ANY_DUNGEON_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be hidden #inside a dungeon# in Hyrule.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, innerhalb eines Labyrinths# zu finden sein.^", + /*french*/ "$bAussi, la #clé du Malin# se trouve #dans un donjon# d'Hyrule.^", + {QM_PINK, QM_PINK})); + // /*spanish*/$bY la llave del #señor del mal# aguardará #en una mazmorra# de Hyrule.^ - hintTable[RHT_GANON_BK_ANYWHERE_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be hidden somewhere&#in Hyrule#.", - /*french*/ "Aussi, la #clé du Malin# se trouve quelque part #dans Hyrule#.", - /*spanish*/ "Y la llave del #señor del mal# aguardará en #cualquier lugar de Hyrule#.", - /*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule# zu finden sein." }, - }); + hintTextTable[RHT_GANON_BK_ANYWHERE_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be hidden somewhere&#in Hyrule#.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Hyrule# zu finden sein.^", + /*french*/ "$bAussi, la #clé du Malin# se trouve quelque part #dans Hyrule#.^", + {QM_PINK, QM_BLUE})); + // /*spanish*/$bY la llave del #señor del mal# aguardará en #cualquier lugar de Hyrule#.^ - hintTable[RHT_GANON_BK_TRIFORCE_HINT] = HintText::GanonsBossKey({ - // obscure text - Text{ "And the #evil one#'s key will be given to the Hero once the #Triforce## is completed.", - /*french*/ "Aussi, la #clé du Malin# se&révèlera une fois la #Triforce#&assemblée.", - /*spanish*/ "Y el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#.", - /*german*/"Und der #Schlüssel des Bösen# wird verliehen, sobald das #Triforce# vervollständigt wurde." }, - }); + hintTextTable[RHT_GANON_BK_TRIFORCE_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be given to the Hero once the #Triforce## is completed.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird verliehen, sobald das #Triforce# vervollständigt wurde.^", + /*french*/ "$bAussi, la #clé du Malin# se&révèlera une fois la #Triforce#&assemblée.^", + {QM_PINK, QM_YELLOW})); + // /*spanish*/$bY el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#.^ - hintTable[RHT_GANON_BK_SKULLTULA_HINT] = HintText::GanonsBossKey({ - // obscure text - Text { "And the #evil one#'s key will be provided by the cursed rich man once #100 Gold Skulltula Tokens# are retrieved.", - /*french*/ "Aussi, la #clé du Malin# sera&donnée par l'homme maudit une fois que #100 Symboles de Skulltula d'or# auront été trouvés.", - /*spanish*/ "Y el rico maldito entregará la llave&del #señor de mal# tras obtener&100 símbolos de skulltula dorada#."}, - }); + hintTextTable[RHT_GANON_BK_SKULLTULA_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by the cursed rich man once #100 Gold Skulltula Tokens# are retrieved.^", + /*german*/ "", + /*french*/ "$bAussi, la #clé du Malin# sera&donnée par l'homme maudit une fois que #100 Symboles de Skulltula d'or# auront été trouvés.^", + {QM_PINK, QM_YELLOW})); + // /*spanish*/$bY el rico maldito entregará la llave&del #señor de mal# tras obtener&100 símbolos de skulltula dorada#.^ - /*-------------------------- - | LACS HINT TEXT | - ---------------------------*/ + hintTextTable[RHT_LACS_VANILLA_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once the #Shadow and Spirit Medallions# are retrieved.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #die Amulette des Schattens und der Geister# geborgen wurden.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois que les #Médaillons de l'Ombre et de l'Esprit# seront récupérés.^", + {QM_PINK, QM_YELLOW, QM_RED})); + // /*spanish*/$bY #Zelda# entregará la llave del #señor del mal# tras obtener #el medallón de las sombras y del espíritu#.^ - hintTable[RHT_LACS_VANILLA_HINT] = HintText::LACS({ - // obscure text - Text{ - "And the #evil one#'s key will be provided by Zelda once the #Shadow and Spirit Medallions# are retrieved.", - /*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois que les #Médaillons de l'Ombre et de l'Esprit# seront récupérés.", - /*spanish*/ - "Y Zelda entregará la llave del #señor del mal# tras obtener #el medallón de las sombras y del " - "espíritu#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #die Amulette des Schattens und der Geister# geborgen wurden." }, - }); + hintTextTable[RHT_LACS_MEDALLIONS_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once #[[d]] Medallion|# is|s# are| retrieved.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #[[d]] Amulett|# geborgen wurde|e# geborgen wurden|.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois |qu' #[[d]] Médaillon# aura été récupéré|que #[[d]] Médaillons# auront été récupérés|.^", + {QM_PINK, QM_YELLOW, QM_RED})); + // /*spanish*/$bY #Zelda# entregará la llave&del #señor del mal# tras obtener #[[d]] |medallón|medallones|#.^ - hintTable[RHT_LACS_MEDALLIONS_HINT] = HintText::LACS({ - // obscure text singular plural - Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Medallion# is|Medallions# are| retrieved.", - /*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Médaillon# aura été récupéré|que #%d Médaillons# auront été récupérés|.", - /*spanish*/ "Y Zelda entregará la llave&del #señor del mal# tras obtener #%d |medallón|medallones|#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Amulett# geborgen wurde|Amulette# geborgen wurden|." }, - }); + hintTextTable[RHT_LACS_STONES_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once #[[d]] Spiritual Stone|# is|s# are| retrieved.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #[[d]] Heilige|r Stein# geborgen wurde| Steine# geborgen wurden|.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois |qu' #[[d]] Pierre Ancestrale# aura été&récupérée|que #[[d]] Pierres Ancestrales# auront été récupérées|.^", + {QM_PINK, QM_YELLOW, QM_BLUE})); + // /*spanish*/$bY #Zelda# entregará la llave del #señor del mal# tras obtener #[[d]] piedra| espiritual|s espirituales|#.^ - hintTable[RHT_LACS_STONES_HINT] = HintText::LACS({ - // obscure text singular plural - Text{ - "And the #evil one#'s key will be provided by Zelda once #%d |Spiritual Stone# is|Spiritual Stones# are| " - "retrieved.", - /*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Pierre Ancestrale# aura été&récupérée|que #%d Pierres Ancestrales# auront été récupérées|.", - /*spanish*/ - "Y Zelda entregará la llave del #señor del mal# tras obtener #%d |piedra espiritual|piedras " - "espirituales|#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Heiliger Stein# geborgen wurde|Heilige Steine# geborgen wurden|." }, - }); + hintTextTable[RHT_LACS_REWARDS_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once #[[d]]# #Spiritual Stone|# or #Medallion# is|s# and #Medallions# are| retrieved.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #[[d]]# #Heilige|r Stein# oder #Amulett#&geborgen wurde| Steine# oder #Amulette#&geborgen wurden|.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois qu|' #[[d]]# #Pierre Ancestrale# ou #[[d]] Médaillon# sera récupéré|e&#[[d]]# #Pierres Ancestrales# et&#Médaillons# seront récupérés|.^", + {QM_PINK, QM_YELLOW, QM_YELLOW, QM_BLUE, QM_RED})); + // /*spanish*/$bY #Zelda# entregará la llave del #señor del mal# tras obtener #[[d]]# piedra| espiritual o medallón|s espirituales o medallones|#.^ - hintTable[RHT_LACS_REWARDS_HINT] = HintText::LACS({ - // obscure text singular plural - Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Spiritual Stone or Medallion# " - "is|Spiritual Stones and Medallions# are| retrieved.", - /*french*/ - "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Pierre Ancestrale ou %d Médaillon# sera récupéré|que&#%d Pierres Ancestrales et&Médaillons# seront récupérés|.", - /*spanish*/ - "Y Zelda entregará la llave del #señor del mal# tras obtener #%d |piedra espiritual o medallón|piedras " - "espirituales o medallones|#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Heiliger Stein oder Amulett#&geborgen wurde|Heilige Steine oder Amulette#&geborgen wurden|." }, - }); + hintTextTable[RHT_LACS_DUNGEONS_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once #[[d]] Dungeon|# is|s# are| conquered.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #[[d]] Labyrinth|# abgeschlossen wurde|e# abgeschlossen wurden|.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois qu|' #[[d]] donjon #sera conquis|e #[[d]] donjons# seront conquis|.^", + {QM_PINK, QM_YELLOW, QM_PINK})); + // /*spanish*/$bY #Zelda# entregará la llave del #señor del mal# tras completar #[[d]] mazmorra||s|#.^ - hintTable[RHT_LACS_DUNGEONS_HINT] = HintText::LACS({ - // obscure text singular plural - Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Dungeon# is|Dungeons# are| conquered.", - /*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d donjon #sera conquis|que #%d donjons# seront conquis|.", - /*spanish*/ "Y Zelda entregará la llave del #señor del mal# tras completar #%d |mazmorra|mazmorras|#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Labyrinth# abgeschlossen wurde|Labyrinthe# abgeschlossen wurden|." }, - }); + hintTextTable[RHT_LACS_TOKENS_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by #Zelda# once #[[d]] Gold Skulltula Token|# is|s# are| retrieved.^", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von #Zelda# verliehen, sobald #[[d]] Skulltula-Symbol|# gesammelt wurde|e# gesammelt wurden|.^", + /*french*/ "$bAussi, la #clé du Malin# sera fournie par #Zelda# une fois |qu' #[[d]] symbole de Skulltula d'or #sera récupuéré" + "|que &#[[d]] symboles de Skulltula d'or&#seront recupérés|.^", + {QM_PINK, QM_YELLOW, QM_YELLOW})); + // /*spanish*/$bY #Zelda# entregará la llave del #señor del mal# tras obtener #[[d]] símbolo + // ||s| de skulltula dorada#.^ - hintTable[RHT_LACS_TOKENS_HINT] = HintText::LACS({ - // obscure text singular plural - Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Gold&Skulltula Token# is|Gold Skulltula " - "Tokens# are| retrieved.", - /*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d symbole de Skulltula d'or #sera récupuéré|que &#%d symboles de Skulltula d'or&#seront recupérés|.", - /*spanish*/ - "Y Zelda entregará la llave del #señor del mal# tras obtener #%d |símbolo|símbolos| de skulltula " - "dorada#.", - /*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Skulltula-Symbol# gesammelt wurde|Skulltula-Symbole# gesammelt wurden|." }, - }); /*-------------------------- | TRIAL HINT TEXT | ---------------------------*/ - hintTable[RHT_SIX_TRIALS] = HintText::Exclude({ - // obscure text - Text{ "#Ganon's Tower# is protected by a powerful barrier.", - /*french*/ "#la Tour de Ganon# est protégée par une puissante barrière", - /*spanish*/ "la #torre de Ganon# está protegida por una poderosa barrera", - /*german*/"der #Teufelsturm# sei von einer mächtigen Barriere geschützt." }, - }); + hintTextTable[RHT_SIX_TRIALS] = HintText(CustomMessage("They say that #Ganon's Tower# is protected by a powerful barrier.", + /*german*/ "Man erzählt sich, daß der #Teufelsturm# sei von einer mächtigen Barriere geschützt sei.", + /*french*/ "Selon moi, #la Tour de Ganon# est protégée par une puissante barrière", {QM_PINK})); + // /*spanish*/Según dicen, la #torre de Ganon# está protegida por una poderosa barrera - hintTable[RHT_ZERO_TRIALS] = HintText::Exclude({ - // obscure text - Text{ "Sheik dispelled the barrier around #Ganon's Tower#.", - /*french*/ "Sheik a dissipé la barrière autour de #la Tour de Ganon#", - /*spanish*/ "Sheik disipó la barrera alrededor de la #torre de Ganon#.", - /*german*/"Shiek habe die Barriere um den #Teufelsturm# aufgelöst." }, - }); + hintTextTable[RHT_ZERO_TRIALS] = HintText(CustomMessage("They say that Sheik dispelled the barrier around #Ganon's Tower#.", + /*german*/ "Man erzählt sich, Shiek habe die Barriere um den #Teufelsturm# aufgelöst sei.", + /*french*/ "Selon moi, Sheik a dissipé la barrière autour de #la Tour de Ganon#", {QM_YELLOW})); + // /*spanish*/Según dicen, Sheik disipó la barrera alrededor de la #torre de Ganon#. - hintTable[RHT_FOUR_TO_FIVE_TRIALS] = HintText::Exclude({ - // obscure text - Text{ " was dispelled by Sheik.", /*french*/ " a été dissipée par Sheik.", - /*spanish*/ " se disipó gracias a Sheik.", - /*german*/" sei von Shiek aufgelöst worden." }, - }); + hintTextTable[RHT_TRIAL_OFF] = HintText(CustomMessage("They say that #[[1]]# was dispelled by Sheik.", + /*german*/ "Man erzählt sich, daß #[[1]]# sei von Shiek aufgelöst worden sei.", + /*french*/ "Selon moi, #[[1]]# a été dissipée par Sheik.", {QM_YELLOW})); + // /*spanish*/Según dicen, #[[1]]# se disipó gracias a Sheik. - hintTable[RHT_ONE_TO_THREE_TRIALS] = HintText::Exclude({ - // obscure text - Text{ " protects Ganons Tower.", /*french*/ " protège la Tour de Ganon.", - /*spanish*/ " protege la torre de Ganon", - /*german*/" schütze den Teufelsturm." }, - }); + hintTextTable[RHT_TRIAL_ON] = HintText(CustomMessage("They say that #[[1]]# protects Ganons Tower.", + /*german*/ "Man erzählt sich, daß #[[1]]# schütze den Teufelsturm sei.", + /*french*/ "Selon moi, #[[1]]# protège la Tour de Ganon.", {QM_PINK})); + // /*spanish*/Según dicen, #[[1]]# protege la torre de Ganon + + hintTextTable[RHT_LIGHT_TRIAL] = HintText(CustomMessage("the Light Trial", + /*german*/ "", + /*french*/ "l'épreuve de la Lumière")); + // /*spanish*/la prueba de la luz + + hintTextTable[RHT_FOREST_TRIAL] = HintText(CustomMessage("the Forest Trial", + /*german*/ "", + /*french*/ "l'épreuve de la Forêt")); + // /*spanish*/la prueba del bosque + + hintTextTable[RHT_FIRE_TRIAL] = HintText(CustomMessage("the Fire Trial", + /*german*/ "", + /*french*/ "l'épreuve du Feu")); + // /*spanish*/la prueba del fuego + + hintTextTable[RHT_WATER_TRIAL] = HintText(CustomMessage("the Water Trial", + /*german*/ "", + /*french*/ "l'épreuve de l'Eau")); + // /*spanish*/la prueba del agua + + hintTextTable[RHT_SPIRIT_TRIAL] = HintText(CustomMessage("the Spirit Trial", + /*german*/ "", + /*french*/ "l'épreuve de l'Esprit")); + // /*spanish*/la prueba del espíritu + + hintTextTable[RHT_SHADOW_TRIAL] = HintText(CustomMessage("the Shadow Trial", + /*german*/ "", + /*french*/ "l'épreuve de l'Ombre")); + // /*spanish*/la prueba de las sombras /*-------------------------- | ALTAR TEXT | ---------------------------*/ - hintTable[RHT_SPIRITUAL_STONE_TEXT_START] = HintText::Altar({ - // obscure text - Text{ "3 Spiritual Stones found in Hyrule...", - /*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...", - /*spanish*/ "Tres piedras espirituales halladas por Hyrule...", - /*german*/"Drei Heilige Steine, zu finden in Hyrule..." }, - }); + hintTextTable[RHT_CHILD_ALTAR_STONES] = HintText(CustomMessage("3 Spiritual Stone's found in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", + /*german*/ "Drei Heilige Steine, zu finden in Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", + /*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", + {QM_GREEN, QM_RED, QM_BLUE}, {true, true, true})); + // /*spanish*/ Tres piedras espirituales halladas por Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^ - hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText::Altar({ - // obscure text - Text{ "Ye who may become a Hero...&The path to the future is open...", - /*french*/ "À celui qui a quête de devenir&héros...&Le futur vous accueille béant...", - /*spanish*/ "Para aquel que se convierta en el héroe...&La puerta al futuro está a su disposición...", - /*german*/"Jener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet..." }, - }); + hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText(CustomMessage("$oYe who may become a Hero...&The path to the future is open...", + /*german*/ "$oJener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet...", + /*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...")); + // /*spanish*/$oPara aquel que se convierta en el héroe...&La puerta al futuro está a su disposición... - hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText::Altar({ - // obscure text - Text{ - "Ye who may become a Hero...&Stand with the Ocarina and&play the Song of Time.", - /*french*/ "À celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.", - /*spanish*/ "Para aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo.", - /*german*/"Jener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und&spiele hier die Hymne der Zeit." }, - }); + hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText(CustomMessage("$cYe who may become a Hero...&Stand with the Ocarina and&play the Song of Time.", + /*german*/ "$cJener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und&spiele hier die Hymne der Zeit.", + /*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.")); + // /*spanish*/$cPara aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo. + + hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText(CustomMessage("$iYe who may become a Hero...&Offer the spiritual stones and&play the Song of Time.", + /*german*/ "$iJener mit den drei Heiligen Steinen&nehme seine Okarina zur Hand und&spiele hier die Hymne der Zeit.", + /*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.")); + // /*spanish*/$iPara aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del Tiempo. - hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText::Altar({ - // obscure text - Text{ "Ye who may become a Hero...&Offer the spiritual stones and&play the Song of Time.", - /*french*/ - "À celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.", - /*spanish*/ - "Para aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del " - "Tiempo.", - /*german*/"Jener mit den drei Heiligen Steinen&nehme seine Okarina zur Hand und&spiele hier die Hymne der Zeit." }, - }); + hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS] = HintText(CustomMessage("An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.^" + "$8#[[1]]#...^$3#[[2]]#...^$4#[[3]]#...^$5#[[4]]#...^$6#[[5]]#...^$7#[[6]]#...^" , + /*german*/ "Beherrscht das Böse die Welt, weilen&jene Weisen, die von der Stimme des Heiligen Reiches erweckt werden, noch&in den #fünf Tempeln#.^" + "$8#[[1]]#...^$3#[[2]]#...^$4#[[3]]#...^$5#[[4]]#...^$6#[[5]]#...^$7#[[6]]#...^", + /*french*/ "Quand le mal aura triomphé, une voix du Saint Royaume appellera ceux cachés dans les #cinq temples#, destinés^à être Sages.^" + "$8#[[1]]#...^$3#[[2]]#...^$4#[[3]]#...^$5#[[4]]#...^$6#[[5]]#...^$7#[[6]]#...^", + { QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK}, {true, true, true, true, true, true}, TEXTBOX_TYPE_BLUE)); + // /*spanish*/Cuando el mal lo impregne todo, desde el Reino Sagrado surgirá una voz que hará despertar a los sabios que moran en los #cinco templos#.^ + // $8#[[1]]#...^$3#[[2]]#...^$4#[[3]]#...^$5#[[4]]#...^$6#[[5]]#...^$7#[[6]]#...^ - hintTable[RHT_ADULT_ALTAR_TEXT_START] = HintText::Altar({ - // obscure text - Text{ "An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.", - /*french*/ - "Quand le mal aura triomphé, une voix du Saint Royaume appellera ceux cachés dans les #cinq temples#, " - "destinés^à être Sages.", - /*spanish*/ - "Cuando el mal lo impregne todo, desde el Reino Sagrado surgirá una voz que hará despertar a los sabios " - "que moran en los #cinco templos#.", - /*german*/"Beherrscht das Böse die Welt, weilen&jene Weisen, die von der Stimme des Heiligen Reiches erweckt werden, noch&in den #fünf Tempeln#." }, - }); - - hintTable[RHT_ADULT_ALTAR_TEXT_END] = HintText::Altar({ - // obscure text - Text{ - "$kTogether with the Hero of Time, the awakened ones will return the light of peace to the world...", - /*french*/ - "$kEnsemble avec le Héros du Temps, ces Sages emprisonneront le mal et réinstaureront la lumière de paix " - "dans le monde...", - /*spanish*/ - "Con el Héroe del Tiempo, aquellos&que despierten detendrán el mal y&volverán al mundo de luz la paz...", - /*german*/"$kZusammen mit dem Auserwählten wer-den diese ihre Kräfte einsetzen, um der Welt den Frieden wiederzugeben." }, - }); + hintTextTable[RHT_ADULT_ALTAR_TEXT_END] = HintText(CustomMessage("$kTogether with the Hero of Time, the awakened ones will return the light of peace to the world...", + /*german*/ "$kZusammen mit dem Auserwählten wer-den diese ihre Kräfte einsetzen, um der Welt den Frieden wiederzugeben.", + /*french*/ "$kEnsemble avec le Héros du Temps, ces Sages emprisonneront le mal et réinstaureront la lumière de paix dans le monde...")); + // /*spanish*/Con el Héroe del Tiempo, aquellos&que despierten detendrán el mal y&volverán al mundo de luz la paz... /*-------------------------- - | VALIDATION LINE TEXT | + | Static Item Hints | ---------------------------*/ - hintTable[RHT_VALIDATION_LINE] = HintText::Validation({ - // obscure text - Text{ "Hmph... Since you made it this far, I'll let you know what glorious prize of Ganon's you likely missed " - "out on in my tower.^Behold...^", - /*french*/ - "Pah! Puisque tu t'es rendu ici, je te dirai quel trésor tu as manqué dans ma tour.^Et c'est...^", - /*spanish*/ - "Mmm... Ya que has llegado hasta aquí, te diré qué preciado objeto de mi propiedad puedes haberte dejado " - "en mi torre.^He aquí...^" }, - }); + hintTextTable[RHT_GANONDORF_HINT_LA_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!", + /*german*/ "", + /*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!", + {QM_RED})); + // /*spanish*/Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de #[[1]]#! + + hintTextTable[RHT_GANONDORF_HINT_MS_ONLY] = HintText(CustomMessage("Ha ha ha... You'll never defeat me, drop a castle on me and finish me off with the sacred blade from #[[2]]#!", + /*german*/ "", + /*french*/ "", + {QM_RED})); + + hintTextTable[RHT_GANONDORF_HINT_LA_AND_MS] = HintText(CustomMessage("Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from #[[1]]#!" + "^And even if you do, you'll never find the legendary blade hidden in #[[2]]#!", + /*german*/ "", + /*french*/ "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans #[[1]]#!" + "^Et même si tu les trouves, tu ne touveras jamais l'épée de légende cachée dans #[[2]]#!", + {QM_RED, QM_RED})); + // /*spanish*/Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de #[[1]]#! + // ^E incluso si lo haces, nunca encontrarás la espada legendaria escondida en #[[2]]#! + + hintTextTable[RHT_SHEIK_HINT_LA_ONLY] = HintText(CustomMessage("I overheard Ganondorf say that he misplaced the #Light Arrows# in #[[1]]#.", + /*german*/ "", + /*french*/ "J'ai entendu dire que Ganondorf aurait caché les #Flèches de Lumière# dans #[[1]]#.", + {QM_YELLOW, QM_RED})); + + hintTextTable[RHT_DAMPE_DIARY] = HintText(CustomMessage("Whoever reads this, please enter #[[1]]#. I will let you have my #stretching, shrinking keepsake#.^I'm waiting for you.&--Dampé", + /*german*/ "Wer immer dies liest, der möge folgenden Ort aufsuchen: #[[1]]#. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris", //RANDOTODO color in whatever refers to the hookshot + /*french*/ "Toi qui lit ce journal, rends-toi dans #[[1]]#. Et peut-être auras-tu droit à mon précieux #trésor#.^Je t'attends...&--Igor", + {QM_RED, QM_RED})); + + hintTextTable[RHT_GREG_HINT] = HintText(CustomMessage("By the way, if you're interested, I saw the shiniest #Green Rupee# somewhere in #[[1]]#.^It's said to have #mysterious powers#...^But then, it could just be another regular rupee.&Oh well.", + /*german*/ "", + /*french*/ "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des #Rubis Verts# quelque part à #[[1]]#. On dit qu'il possède des pouvoirs mystérieux... Mais bon, ça pourrait juste être un autre rubis ordinaire.",//RANDOTODO color in mysterious powers + {QM_GREEN, QM_RED, QM_RED})); + + hintTextTable[RHT_SARIA_TALK_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!", + /*german*/ "", + /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#. Tu devrais aller y jeter un coup d'oeil, @!", + {QM_GREEN, QM_RED})); + + hintTextTable[RHT_SARIA_SONG_HINT] = HintText(CustomMessage("Did you feel the #surge of magic# recently? A mysterious bird told me it came from #[[1]]#.^You should check that place out, @!\x0B", + /*german*/ "", + /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#. Tu devrais aller y jeter un coup d'oeil, @!\x0B", + {QM_GREEN, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); + + hintTextTable[RHT_FISHING_POLE_HINT] = HintText(CustomMessage("^If I remember correctly, I lost it somewhere in #[[1]]#...&Let me know if you find it!", + {QM_RED})); /*-------------------------- - | LIGHT ARROW LOCATION TEXT| + | Static Entrance Hint | ---------------------------*/ - hintTable[RHT_LIGHT_ARROW_LOCATION_HINT] = HintText::OtherHint({ - // obscure text - Text{ - "Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from ", - /*french*/ - "Ha ha ha... Pauvre fou! Tu ne pourras jamais me vaincre sans les flèches que j'ai cachées dans ", - /*spanish*/ - "Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de " }, - }); - - hintTable[RHT_SHEIK_LIGHT_ARROW_HINT] = HintText::SheikLine({ - // obscure text - Text{ - "I overheard Ganondorf say that he misplaced the %yLight Arrows%w in %r", - /*french*/ - "J'ai entendu dire que Ganondorf aurait caché les %yFlèches de Lumière%w dans %r", - /*spanish*/ - ""}, - }); - + hintTextTable[RHT_WARP_SONG] = HintText(CustomMessage("Warp to&#[[1]]#?&" + TWO_WAY_CHOICE() + "#OK&No#", + /*german*/ "Zu&#[[1]]#?&" + TWO_WAY_CHOICE() + "#OK&No#", + /*french*/ "Se téléporter vers&#[[1]]#?&" + TWO_WAY_CHOICE() + "#OK!&Non#", + {QM_RED, QM_GREEN})); + /*-------------------------- - |MASTER SWORD LOCATION TEXT| + | STATIC LOCATION HINTS | ---------------------------*/ - hintTable[RHT_MASTER_SWORD_LOCATION_HINT] = HintText::MasterSword({ - // obscure text - Text{"And even if you do, you'll never find the legendary blade hidden in ", - /*french*/ - "Et même si tu les trouves, tu ne touveras jamais l'épée de légende cachée dans ", - /*spanish*/ - "E incluso si lo haces, nunca encontrarás la espada legendaria escondida en " }, - }); + hintTextTable[RHT_MEDIGORON_HINT] = HintText(CustomMessage("How about buying #[[1]]# for #200 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", + /*german*/ "Möchtest du #[[1]]# für #200 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Klar!&Nie im Leben!#", + /*french*/ "Veux-tu acheter #[[1]]# pour #200 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", + {QM_GREEN, QM_YELLOW, QM_GREEN})); + /*spanish*/ // ¿Me compras #[[1]]# por #200 rupias#?&" + TWO_WAY_CHOICE() + "#Comprar&No comprar# - hintTable[RHT_SHEIK_MASTER_SWORD_LOCATION_HINT] = HintText::SheikLine({ - // obscure text - Text{"He also stole %gthe Master Sword%w and hid it in %r", - /*french*/ - "Il aurait aussi volé %gl'épée de légende%w, qu'il aurait caché dans %r", - /*spanish*/ - "Él también robó %gla Espada Maestra%w y la escondió en %r" }, - }); + hintTextTable[RHT_CARPET_SALESMAN_DIALOG_FIRST] = HintText(CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", + /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten. Stets sonderliche und seltene Ware aus " + "aller Welt für jedermann. Das heutige Angebot bleibt...^#", + /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^")); + /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ - hintTable[RHT_YOUR_POCKET] = HintText::Exclude({ - // obscure text - Text{ "your pocket", /*french*/ "tes poches", /*spanish*/ "tu bolsillo" }, - }); + hintTextTable[RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS] = HintText(CustomMessage("Terrifying! I won't tell you what it is until I see the #money#...^How about #200 Rupees#?&&" + + TWO_WAY_CHOICE() + "#Buy&Don't buy#", + /*german*/ "Furchterregend oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #200 Rubinen#?&&" + + TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#", + /*french*/ "Un concentré de puissance! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #200 " + "rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", + {QM_RED, QM_YELLOW, QM_GREEN})); + /*spanish*/ // ¡Terrorífico! No te revelaré su nombre hasta que vea el #dinero#...^#200 rupias#, ¿qué te parece?&&" + + // TWO_WAY_CHOICE() + "#Comprar&No comprar# - /*-------------------------- - | OTHER HINT TEXT | - ---------------------------*/ + hintTextTable[RHT_CARPET_SALESMAN_DIALOG_HINTED] = HintText(CustomMessage("#[[1]]!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^" + "How about #200 Rupees#?&&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", + /*german*/ "#[[1]]#! Ich kann versichern es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich doch " + "nicht #anlügen#, oder?^Wie wär's mit #200 Rubinen#?&&" + TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#", + /*french*/ "#[[1]]!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #200 " + "rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", + {QM_GREEN, QM_YELLOW, QM_GREEN})); - hintTable[RHT_DAMPE_DIARY01] = HintText::OtherHint({ - // obscure text - Text{ - "Whoever reads this, please enter %r", - /*french*/ - "Toi qui lit ce journal, rends-toi dans %r", - /*german?*/ - "Wer immer dies liest, der möge folgenden Ort aufsuchen: %r"}, - }); + hintTextTable[RHT_BEAN_SALESMAN_HINT] = HintText(CustomMessage("I tried to be a #magic bean# salesman, but it turns out my marketing skills weren't worth " + "beans!^Anyway, want to buy #[[1]]# for #60 Rupees#?&" + TWO_WAY_CHOICE() + "#Yes&No#", + /*german*/ "Möchten Sie #[[1]]# für #60 Rubine#?&" + TWO_WAY_CHOICE() + "#Ja&Nein#", + /*french*/ "J'ai essayé d'être un vendeur de #haricots magiques#, mais j'étais mauvais au niveau du marketing et ça " + "me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter #[[1]]# pour #60 Rubis#?&" + TWO_WAY_CHOICE() + "#Oui&Non#", + {QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN})); - hintTable[RHT_DAMPE_DIARY02] = HintText::OtherHint({ - // obscure text - Text{ - "%w. I will let you have my stretching, shrinking keepsake.^I'm waiting for you.&--Dampé", - /*french*/ - "%w. Et peut-être auras-tu droit à mon précieux %rtrésor%w.^Je t'attends...&--Igor", - /*german?*/ - "%w. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris"}, - }); + hintTextTable[RHT_GRANNY_HINT] = HintText(CustomMessage("#[[1]]#! How about #100 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", + /*german*/ "#[[1]]#! Sagen wir #100 Rubine#!&" + TWO_WAY_CHOICE() + "#Gerne!&Auf keinen Fall!#", + /*french*/ "#[[1]]#! Que dis-tu de #100 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", + {QM_GREEN, QM_YELLOW, QM_GREEN}, {true})); + // /*spanish*/#[[1]]#. Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar# - hintTable[RHT_GREG_HINT01] = HintText::OtherHint({ - // obscure text - Text{ - "By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%g ", - /*french*/ - "Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des %gRubis Verts%w quelque part à %g", - /*spanish*/ - ""}, - }); + hintTextTable[RHT_HBA_HINT_SIGN] = HintText(CustomMessage("#Horseback Archery# Range Prizes:&1000: #[[1]]#&1500: #[[2]]#^@'s Record: #" + CustomMessage::POINTS(HS_HORSE_ARCHERY) + "#", + {QM_RED, QM_GREEN, QM_GREEN, QM_GREEN}, {}, TEXTBOX_TYPE_WOODEN)); - hintTable[RHT_GREG_HINT02] = HintText::OtherHint({ - // obscure text - Text{ - "%w.^It's said to have %rmysterious powers%w...^But then, it could just be another regular rupee.&Oh well.", - /*french*/ - "%w. On dit qu'il possède des pouvoirs mystérieux... Mais bon, ça pourrait juste être un autre rubis ordinaire.", - /*spanish*/ - ""}, - }); + hintTextTable[RHT_HBA_HINT_NOT_ON_HORSE] = HintText(CustomMessage("Hey, rookie!&Come back on your #horse# and take on then #Horseback Archery# challenge!^" + "Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for my #[[2]]#!", + {QM_RED, QM_RED, QM_GREEN, QM_GREEN})); - hintTable[RHT_SARIA_TEXT01] = HintText::OtherHint({ - // obscure text - Text{ - "Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %g", - /*french*/ - "As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %g", - /*spanish*/ - ""}, - }); + hintTextTable[RHT_HBA_HINT_INITIAL] = HintText(CustomMessage("Hey, rookie!&Want to take on the #Horseback Archery# challenge?^" + "Impress me with a high score of 1000 to win a #[[1]]# or score 1500 for my #[[2]]#!\x0B", + {QM_RED, QM_GREEN, QM_GREEN})); - hintTable[RHT_SARIA_TEXT02] = HintText::OtherHint({ - // obscure text - Text{ - "%w.^You should check that place out, @!$C", - /*french*/ - "%w. Tu devrais aller y jeter un coup d'oeil, @!$C", - /*spanish*/ - "%w.$C"}, - }); + hintTextTable[RHT_HBA_HINT_HAVE_1000] = HintText(CustomMessage("Hey, newcomer!&Want to take on the #Horseback Archery# challenge?^" + "Prove yourself to be a horsemaster by scoring 1500 points to win my #[[1]]#!\x0B", + {QM_RED, QM_GREEN})); - hintTable[RHT_WARP_TO] = HintText::OtherHint({ - Text{ - "Warp to&#", - "Se téléporter vers&#", - "", - "Zu&#"}, - }); - hintTable[RHT_WARP_CHOICE] = HintText::OtherHint({ - Text{ - "#?&" + TWO_WAY_CHOICE() + "#OK&No#", - "#?&" + TWO_WAY_CHOICE() + "#OK!&Non#", - "###", - "#?&" + TWO_WAY_CHOICE() + "#OK&No#" - } - }); + hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obsticle Course#!^" + "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", + {QM_RED, QM_BLUE, QM_GREEN})); - hintTable[RHT_FROGS_HINT01] = HintText::OtherHint({Text{ - "Some frogs holding #", - "Des grenouilles se trouvant sous l'eau vous fixent attentivement, tenant fermement #", - "", - "Unter Wasser gibt es Frösche, die #" - }}); - hintTable[RHT_FROGS_HINT02] = HintText::OtherHint({Text{ - "# are looking at you from underwater...", - "#.", - "", - "# bei sich haben und Dich neugierig beobachten..." - }}); + hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obsticle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" + "Challenge the #Obsticle Course?#&\x1B&#Let's go&No thanks#", + {QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN})); - hintTable[RHT_FISHING_POLE_HINT01] = HintText::OtherHint({ - // obscure text - Text{"^If I remember correctly, I lost it somewhere in %r", - /*french*/ - "", - /*spanish*/ - "" } - }); + hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obsticle Course#, and whoever gets the best time would win a #cow#!^" + "Elsie loves sharing her #[[1]]# with new people, It'll be fun!^...But Ingo won't let me...", + {QM_RED, QM_BLUE, QM_GREEN})); - hintTable[RHT_FISHING_POLE_HINT02] = HintText::OtherHint({ - // obscure text - Text{"%w...&Let me know if you find it!", - /*french*/ - "", - /*spanish*/ - "" } - }); + hintTextTable[RHT_MALON_HINT_INGO_TEMPTED] = HintText(CustomMessage("@! You should come back in the morning and try to beat my time on the #Obsticle Course#!^" + "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", + {QM_RED, QM_BLUE, QM_GREEN})); + + hintTextTable[RHT_CHICKENS_HINT] = HintText(CustomMessage("You! Please!&Bring my Cucco's back to my pen!&I'll give you my #[[1]]#!", + {QM_GREEN})); + + hintTextTable[RHT_BIG_POES_HINT] = HintText(CustomMessage("You have #\x1E\x01 Poe Points#! Reach 1000 and you'll get a #[[1]]#!", + {QM_YELLOW, QM_GREEN})); + + hintTextTable[RHT_BIGGORON_HINT] = HintText(CustomMessage("Arrrrrre you here to claim my finest #[[1]]#? Shoooooow me your #Claim Check#.", + {QM_GREEN, QM_RED})); + + hintTextTable[RHT_FROGS_HINT] = HintText(CustomMessage("Some frogs holding #[[1]]# are looking at you from underwater...", + /*german*/ "Unter Wasser gibt es Frösche, die #[[1]]# bei sich haben und Dich neugierig beobachten...", + /*french*/ "Des grenouilles se trouvant sous l'eau vous fixent attentivement, tenant fermement #[[1]]#.", + {QM_GREEN})); + + hintTextTable[RHT_SKULLS_HINT] = HintText(CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying #[[d]] Spiders of the Curse# and I will give you my #[[1]]#!", + /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du #[[d]] Skulltulas# zerstörst und ich werde dir dafür #[[1]]# geben!", + /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore #[[d]] Araignées de la Malédiction# et j'aurai quelque chose à te donner! #([[1]])#", + {QM_YELLOW, QM_GREEN})); /*-------------------------- | GANON LINE TEXT | ---------------------------*/ - hintTable[RHT_GANON_LINE01] = HintText::GanonLine({ - // obscure text - Text{ "Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?", - /*french*/ "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?", - /*spanish*/ - "¡Oh! Pero si es @.&Estaba esperando a alguien llamado Sheik. ¿Sabes qué puede haberle pasado?" }, - }); + hintTextTable[RHT_GANON_JOKE01] = HintText(CustomMessage("Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?", + /*german*/ "", + /*french*/ "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?")); + // /*spanish*/¡Oh! Pero si es @.&Estaba esperando a alguien llamado Sheik. ¿Sabes qué puede haberle pasado? - hintTable[RHT_GANON_LINE02] = HintText::GanonLine({ - // obscure text - Text{ "I knew I shouldn't have put the key on the other side of my door.", - /*french*/ "J'aurais dû garder la clé ici. Hélas...", - /*spanish*/ "Sabía que no tendría que haber dejado la llave al otro lado de la puerta." }, - }); + hintTextTable[RHT_GANON_JOKE02] = HintText(CustomMessage("I knew I shouldn't have put the key on the other side of my door.", + /*german*/ "", + /*french*/ "J'aurais dû garder la clé ici. Hélas...")); + // /*spanish*/Sabía que no tendría que haber dejado la llave al otro lado de la puerta. - hintTable[RHT_GANON_LINE03] = HintText::GanonLine({ - // obscure text - Text{ "Looks like it's time for a round of tennis.", - /*french*/ "C'est l'heure de jouer au tennis.", - /*spanish*/ "Parece que es hora de una pachanga de tenis." }, - }); + hintTextTable[RHT_GANON_JOKE03] = HintText(CustomMessage("Looks like it's time for a round of tennis.", + /*german*/ "", + /*french*/ "C'est l'heure de jouer au tennis.")); + // /*spanish*/Parece que es hora de una pachanga de tenis. - hintTable[RHT_GANON_LINE04] = HintText::GanonLine({ - // obscure text - Text{ "You'll never deflect my bolts of energy with your sword, then shoot me with those Light Arrows you " - "happen to have.", - /*french*/ - "Ne perds pas ton temps à frapper mes éclairs d'énergie avec ton épée et me tirer avec tes flèches de " - "Lumière!", - /*spanish*/ - "Nunca reflejarás mis esferas de energía con tu espada, para después dispararme con las flechas de luz " - "que tendrás." }, - }); + hintTextTable[RHT_GANON_JOKE04] = HintText(CustomMessage("You'll never deflect my bolts of energy with your sword, then shoot me with those Light Arrows you happen to have.", + /*german*/ "", + /*french*/ "Ne perds pas ton temps à frapper mes éclairs d'énergie avec ton épée et me tirer avec tes flèches de Lumière!")); + // /*spanish*/Nunca reflejarás mis esferas de energía con tu espada, para después dispararme con las flechas de luz que tendrás. - hintTable[RHT_GANON_LINE05] = HintText::GanonLine({ - // obscure text - Text{ "Why did I leave my trident back in the desert?", - /*french*/ "Sale bêtise... Et j'ai oublié mon trident dans le désert!", - /*spanish*/ "Santa Hylia... ¿Por qué me habré dejado el tridente en el desierto?" }, - }); + hintTextTable[RHT_GANON_JOKE05] = HintText(CustomMessage("Why did I leave my trident back in the desert?", + /*german*/ "", + /*french*/ "Sale bêtise... Et j'ai oublié mon trident dans le désert!")); + // /*spanish*/Santa Hylia... ¿Por qué me habré dejado el tridente en el desierto? - hintTable[RHT_GANON_LINE06] = HintText::GanonLine({ - // obscure text - Text{ "Zelda is probably going to do something stupid, like send you back to your own timeline.^So this is " - "quite meaningless. Do you really want to save this moron?", - /*french*/ - "Même si je suis vaincu... Zelda te renverra dans ton ère, et je reviendrai conquérir!^Telle est la " - "prophécie d'Hyrule Historia!", - /*spanish*/ - "Seguro que Zelda trata de hacer alguna tontería, como enviarte de vuelta a tu línea temporal.^No tiene " - "ningún sentido alguno. ¿De verdad quieres salvar a esa tonta?" }, - }); + hintTextTable[RHT_GANON_JOKE06] = HintText(CustomMessage("Zelda is probably going to do something stupid, like send you back to your own timeline.^So this is " + "quite meaningless. Do you really want to save this moron?", + /*german*/ "", + /*french*/ "Même si je suis vaincu... Zelda te renverra dans ton ère, et je reviendrai conquérir!^Telle est la " + "prophécie d'Hyrule Historia!")); + // /*spanish*/Seguro que Zelda trata de hacer alguna tontería, como enviarte de vuelta a tu línea temporal.^No tiene + // ningún sentido alguno. ¿De verdad quieres salvar a esa tonta? - hintTable[RHT_GANON_LINE07] = HintText::GanonLine({ - // obscure text - Text{ "What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the " - "hungry,&and my castle floats.", - /*french*/ - "Zelda ne sera jamais un meilleur monarque que moi!^J'ai un château volant, mes sujets sont des belles " - "amazones... et mes Moblins sont clairement plus puissants que jamais!", - /*spanish*/ - "¿Qué te hace pensar que Zelda gobierna mejor que yo?^Yo he salvado el Rancho Lon Lon,&he alimentado a " - "los hambrientos&y hasta hago que mi castillo flote." }, - }); + hintTextTable[RHT_GANON_JOKE07] = HintText(CustomMessage("What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the " + "hungry,&and my castle floats.", + /*german*/ "", + /*french*/ "Zelda ne sera jamais un meilleur monarque que moi!^J'ai un château volant, mes sujets sont des belles " + "amazones... et mes Moblins sont clairement plus puissants que jamais!")); + // /*spanish*/¿Qué te hace pensar que Zelda gobierna mejor que yo?^Yo he salvado el Rancho Lon Lon,&he alimentado a + // los hambrientos&y hasta hago que mi castillo flote. - hintTable[RHT_GANON_LINE08] = HintText::GanonLine({ - // obscure text - Text{ "I've learned this spell,&it's really neat,&I'll keep it later&for your treat!", - /*french*/ - "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu " - "subiras!", - /*spanish*/ - "Veamos ahora que harás,&la batalla ha de comenzar,&te enviaré de una vez al más allá,&¿listo para " - "afrontar la verdad?" }, - }); + hintTextTable[RHT_GANON_JOKE08] = HintText(CustomMessage("I've learned this spell,&it's really neat,&I'll keep it later&for your treat!", + /*german*/ "", + /*french*/ "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!")); + // /*spanish*/Veamos ahora que harás,&la batalla ha de comenzar,&te enviaré de una vez al más allá,&¿listo para + // afrontar la verdad? - hintTable[RHT_GANON_LINE09] = HintText::GanonLine({ - // obscure text - Text{ "Many tricks are up my sleeve,&to save yourself&you'd better leave!", - /*french*/ "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!", - /*spanish*/ "¿No osarás a mí enfrentarte?&Rimas aparte,&¡voy a matarte!" }, - }); + hintTextTable[RHT_GANON_JOKE09] = HintText(CustomMessage("Many tricks are up my sleeve,&to save yourself&you'd better leave!", + /*german*/ "", + /*french*/ "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!")); + // /*spanish*/¿No osarás a mí enfrentarte?&Rimas aparte,&¡voy a matarte! - hintTable[RHT_GANON_LINE10] = HintText::GanonLine({ - // obscure text - Text{ "After what you did to Koholint Island, how can you call me the bad guy?", - /*french*/ "J'admire ce que tu as fait à l'Île Koholint... Toi et moi, nous devrions faire équipe!", - /*spanish*/ "Después de lo que le hiciste a la Isla Koholint, ¿cómo te atreves a llamarme malvado?" }, - }); + hintTextTable[RHT_GANON_JOKE10] = HintText(CustomMessage("After what you did to Koholint Island, how can you call me the bad guy?", + /*german*/ "", + /*french*/ "J'admire ce que tu as fait à l'Île Koholint... Toi et moi, nous devrions faire équipe!")); + // /*spanish*/Después de lo que le hiciste a la Isla Koholint, ¿cómo te atreves a llamarme malvado? - hintTable[RHT_GANON_LINE11] = HintText::GanonLine({ - // obscure text - Text{ "Today, let's begin down&'The Hero is Defeated' timeline.", - /*french*/ - "Si tu me vaincs, Hyrule sera englouti... mais si tu meurs, on aura A Link to the Past, le meilleur opus " - "de la série!", - /*spanish*/ - "Hoy daremos lugar a la línea temporal del Héroe Derrotado.&¡Prepárate para el culmen de esta saga!" }, - }); + hintTextTable[RHT_GANON_JOKE10] = HintText(CustomMessage("Today, let's begin down&'The Hero is Defeated' timeline.", + /*german*/ "", + /*french*/ "Si tu me vaincs, Hyrule sera englouti... mais si tu meurs, on aura A Link to the Past, le meilleur opus " + "de la série!")); + // /*spanish*/Hoy daremos lugar a la línea temporal del Héroe Derrotado.&¡Prepárate para el culmen de esta saga! - /*-------------------------- - | MERCHANTS' ITEMS | - ---------------------------*/ + /*-------------------------- + | Misc utilities | + ---------------------------*/ + + hintTextTable[RHT_YOUR_POCKET] = HintText(CustomMessage("your pocket", + /*german*/ "", + /*french*/ "tes poches")); + // /*spanish*/tu bolsillo - hintTable[RHT_BEAN_SALESMAN_FIRST] = HintText::MerchantsDialogs({ - Text{ - "I tried to be a #magic bean#&salesman, but it turns out my&marketing skills weren't worth&" - "beans!^Anyway, want to buy #", - /*french*/ "J'ai essayé d'être un vendeur&de #haricots magiques#, mais&j'étais mauvais au niveau du&marketing et ça " - "me courait sur&le haricot...^Enfin bref, ça te dirait de m'acheter #", - /*spanish*/ "", - /*german*/ "Möchten Sie #" - } - }); - hintTable[RHT_BEAN_SALESMAN_SECOND] = HintText::MerchantsDialogs({ - Text{ - "# for #60 Rupees#?&" + TWO_WAY_CHOICE() + "#Yes&No#", - /*french*/ "# pour #60 Rubis#?&" + TWO_WAY_CHOICE() + "#Oui&Non#", - /*spanish*/ "", - /*german*/ "# für #60 Rubine#?&" + TWO_WAY_CHOICE() + "#Ja&Nein#" - } - }); + hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage(" It's ordinary.", + /*german*/ "&Sieht aus wie immer.", + /*french*/ "&Elle vous semble %rordinaire%w.")); - hintTable[RHT_MEDIGORON_DIALOG_FIRST] = HintText::MerchantsDialogs({ - // obscure text - Text{ "How about buying #", - /*french*/ "Veux-tu acheter #", - /*spanish*/ "¿Me compras #", - /*german*/ "Möchtest du #" }, - }); + hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage(" It's masterful!", + /*german*/ "&Man kann darauf die Worte&%r\"Master Quest\"%w entziffern...", + /*french*/ "&Étrange... les mots %r\"Master&Quest\"%w sont gravés dessus.")); - hintTable[RHT_MEDIGORON_DIALOG_SECOND] = HintText::MerchantsDialogs({ - // obscure text - Text{ "# for #200 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*french*/ "# pour #200 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", - /*spanish*/ "# por #200 rupias#?&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#", - /*german*/ "# für #200 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Klar!&Nie im Leben!#" }, - }); - - hintTable[RHT_CARPET_SALESMAN_DIALOG_FIRST] = HintText::MerchantsDialogs({ - // obscure text - Text{ "Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special " - "is...^#", - /*french*/ - "Bienvenue!^Je vends des objets rares et merveilleux du&monde entier. En spécial aujourd'hui...^#", - /*spanish*/ - "¡Acércate!^Vendo productos extraños y difíciles de&encontrar... De todo el mundo a todo el&mundo. La " - "oferta de hoy es...^#¡", - /* german */ - "Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten.&Stets sonderliche und seltene Ware&aus " - "aller Welt für jedermann.&Das heutige Angebot bleibt...^#" }, - }); - - hintTable[RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS] = HintText::MerchantsDialogs({ - // obscure text - Text{ "!# Terrifying! I won't tell you what it is until I see the #money#...^How about #200 Rupees#?&&" + - TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*french*/ - "!# Un concentré de puissance! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #200 " - "rubis#?&&" + - TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", - /*spanish*/ - "!# ¡Terrorífico! No te revelaré su nombre hasta que vea el #dinero#...^#200 rupias#, ¿qué te parece?&&" + - TWO_WAY_CHOICE() + "#Comprar&No comprar#", - /*german*/ - "!# Furchterregend oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #200 Rubinen#?&&" + - TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#" }, - }); - - hintTable[RHT_CARPET_SALESMAN_DIALOG_HINTED] = HintText::MerchantsDialogs({ - // obscure text - Text{ "!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^" - "How about #200 Rupees#?&&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*french*/ - "!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #200 " - "rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", - /*spanish*/ // TODO: Flesh this out with the flavor text if we ever support spanish translations - "#!^###200 rupias#, ¿qué te parece?&&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#", - /*german*/ - "#! Ich kann versichern es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich doch " - "nicht #anlügen#, oder?^Wie wär's mit #200 Rubinen#?&&" + TWO_WAY_CHOICE() + - "#Aber sicher!&Ich bin weg!#" }, - }); - - hintTable[RHT_CARPET_SALESMAN_DIALOG_FINAL] = HintText::MerchantsDialogs({ - // obscure text - Text{ "Finally! Now I can go back to being &an %rarms dealer%w!", - /*french*/ "Squalala! Je vais enfin pouvoir &%rprendre des vacances%w!", - /*spanish*/ "", // TODO: Flesh this out with the flavor text if we ever support spanish translations - /*german*/ "Endlich! Schon bald kann ich wieder &%rKrabbelminen-Händler%w sein!" }, - }); - - hintTable[RHT_GRANNY_DIALOG] = HintText::MerchantsDialogs({ - // obscure text - Text{ "! How about #100 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*french*/ "! Que dis-tu de #100 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", - /*spanish*/ ". Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#", - /*german*/ "! Sagen wir #100 Rubine#!&" + TWO_WAY_CHOICE() + "#Gerne!&Auf keinen Fall!#" }, - }); } - -int32_t StonesRequiredBySettings() { - auto ctx = Rando::Context::GetInstance(); - int32_t stones = 0; - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value() }); - } - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 6 }); - } - if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 6 }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_STONE_COUNT).Value() }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 6 }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { - stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 6 }); - } - return stones; -} - -int32_t MedallionsRequiredBySettings() { - auto ctx = Rando::Context::GetInstance(); - int32_t medallions = 0; - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value() }); - } - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 3 }); - } - if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 3 }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value() }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 3 }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { - medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 3 }); - } - return medallions; -} - -int32_t TokensRequiredBySettings() { - auto ctx = Rando::Context::GetInstance(); - int32_t tokens = 0; - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { - tokens = std::max({ tokens, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value() }); - } - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { - tokens = std::max({ tokens, (int32_t)ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value() }); - } - return tokens; -} - -std::array AreaHintTextKeys = { - RHT_NONE, - RHT_LINKS_POCKET, - RHT_KOKIRI_FOREST, - RHT_THE_LOST_WOODS, - RHT_SACRED_FOREST_MEADOW, - RHT_HYRULE_FIELD, - RHT_LAKE_HYLIA, - RHT_GERUDO_VALLEY, - RHT_GERUDO_FORTRESS, - RHT_HAUNTED_WASTELAND, - RHT_DESERT_COLOSSUS, - RHT_THE_MARKET, - RHT_TEMPLE_OF_TIME, - RHT_HYRULE_CASTLE, - RHT_OUTSIDE_GANONS_CASTLE, - RHT_CASTLE_GROUNDS, - RHT_KAKARIKO_VILLAGE, - RHT_THE_GRAVEYARD, - RHT_DEATH_MOUNTAIN_TRAIL, - RHT_GORON_CITY, - RHT_DEATH_MOUNTAIN_CRATER, - RHT_ZORAS_RIVER, - RHT_ZORAS_DOMAIN, - RHT_ZORAS_FOUNTAIN, - RHT_LON_LON_RANCH, - RHT_DEKU_TREE, - RHT_DODONGOS_CAVERN, - RHT_JABU_JABUS_BELLY, - RHT_FOREST_TEMPLE, - RHT_FIRE_TEMPLE, - RHT_WATER_TEMPLE, - RHT_SPIRIT_TEMPLE, - RHT_SHADOW_TEMPLE, - RHT_BOTTOM_OF_THE_WELL, - RHT_ICE_CAVERN, - RHT_GERUDO_TRAINING_GROUND, - RHT_GANONS_CASTLE -}; - -std::array conditionalAlwaysHints = { - std::make_pair(RC_MARKET_10_BIG_POES, - []() { - auto ctx = Rando::Context::GetInstance(); - return ctx->GetOption(RSK_BIG_POE_COUNT).Value() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); - }), // Remember, the option's value being 3 means 4 are required - std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, - []() { - auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); - }), - std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), - std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), - std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), - std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, - []() { - auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_BIGGORON_HINT); - }), - std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, - []() { - auto ctx = Rando::Context::GetInstance(); - return TokensRequiredBySettings() < 30 && !ctx->GetOption(RSK_KAK_30_SKULLS_HINT); - }), - std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, - []() { - auto ctx = Rando::Context::GetInstance(); - return TokensRequiredBySettings() < 40 && !ctx->GetOption(RSK_KAK_40_SKULLS_HINT); - }), - std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, - []() { - auto ctx = Rando::Context::GetInstance(); - return TokensRequiredBySettings() < 50 && !ctx->GetOption(RSK_KAK_50_SKULLS_HINT); - }), - std::make_pair(RC_ZR_FROGS_OCARINA_GAME, - []() { - auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_FROGS_HINT); - }), - std::make_pair(RC_KF_LINKS_HOUSE_COW, - []() { - auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_MALON_HINT); - }), - std::make_pair(RC_KAK_100_GOLD_SKULLTULA_REWARD, - []() { - auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT); - }), -}; - -const HintText& Hint(const RandomizerHintTextKey hintKey) { - return hintTable[hintKey]; -} - -const HintText& Hint(const RandomizerArea area) { - return hintTable[AreaHintTextKeys[area]]; -} - -std::vector GetHintCategory(HintCategory category) { - - std::vector hintsInCategory = {}; - - for (const auto& hint : hintTable) { - if (hint.GetType() == category) { - hintsInCategory.push_back(hint); - } - } - return hintsInCategory; } diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.hpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.hpp deleted file mode 100644 index 69e66e6db..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "hints.hpp" - -#include - -extern std::array hintTable; - -void HintTable_Init(); -const HintText& Hint(const RandomizerHintTextKey hintKey); -const HintText& Hint(const RandomizerArea area); -std::vector GetHintCategory(HintCategory category); - -void HintTable_Init_Item(); -void HintTable_Init_Exclude_Overworld(); -void HintTable_Init_Exclude_Dungeon(); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp index 934a8f56c..b86b8f33e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp @@ -1,1964 +1,1999 @@ -#include "../hint_list.hpp" +#include "../../static_data.h" +#include "../hints.hpp" +#include "../../../custom-message/CustomMessageManager.h" -void HintTable_Init_Exclude_Dungeon() { +namespace Rando { +void StaticData::HintTable_Init_Exclude_Dungeon() { /*-------------------------- | DEKU TREE | ---------------------------*/ - hintTable[RHT_DEKU_TREE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"in the #center of the Deku Tree# lies", /*french*/"#le coeur de l'Arbre Mojo# recèle", /*spanish*/"al #centro del Gran Árbol Deku# yace"}, - }); + hintTextTable[RHT_DEKU_TREE_MAP_CHEST] = HintText(CustomMessage("They say that in the #center of the Deku Tree# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le coeur de l'Arbre Mojo# recèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al #centro del Gran Árbol Deku# yace #[[1]]#. - hintTable[RHT_DEKU_TREE_SLINGSHOT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #treasure guarded by a scrub# in the Deku Tree is", /*french*/"le #trésor protégé par une peste# dans l'Arbre Mojo est", /*spanish*/"un #deku del Gran Árbol Deku# esconde"}, - }); + hintTextTable[RHT_DEKU_TREE_SLINGSHOT_CHEST] = HintText(CustomMessage("They say that the #treasure guarded by a scrub# in the Deku Tree is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor protégé par une peste# dans l'Arbre Mojo est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku del Gran Árbol Deku# esconde #[[1]]#. - hintTable[RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #treasure guarded by a scrub# in the Deku Tree is", /*french*/"le #trésor protégé par une peste# dans l'Arbre Mojo est", /*spanish*/"un #deku del Gran Árbol Deku# esconde"}, - }); + hintTextTable[RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = HintText(CustomMessage("They say that the #treasure guarded by a scrub# in the Deku Tree is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor protégé par une peste# dans l'Arbre Mojo est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku del Gran Árbol Deku# esconde #[[1]]#. - hintTable[RHT_DEKU_TREE_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#pillars of wood# in the Deku Tree lead to", /*french*/"les #piliers de bois# dans l'Arbre Mojo indiquent", /*spanish*/"los #salientes del Gran Árbol Deku# conducen a"}, - }); + hintTextTable[RHT_DEKU_TREE_COMPASS_CHEST] = HintText(CustomMessage("They say that #pillars of wood# in the Deku Tree lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #piliers de bois# dans l'Arbre Mojo indiquent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #salientes del Gran Árbol Deku# conducen a #[[1]]#. - hintTable[RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#pillars of wood# in the Deku Tree lead to", /*french*/"les #piliers de bois# dans l'Arbre Mojo indiquent", /*spanish*/"los #salientes del Gran Árbol Deku# conducen a"}, - }); + hintTextTable[RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = HintText(CustomMessage("They say that #pillars of wood# in the Deku Tree lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #piliers de bois# dans l'Arbre Mojo indiquent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #salientes del Gran Árbol Deku# conducen a #[[1]]#. - hintTable[RHT_DEKU_TREE_BASEMENT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#webs in the Deku Tree# hide", /*french*/"les #toiles dans l'Arbre Mojo# cachent", /*spanish*/"entre #telarañas del Gran Árbol Deku# yace"}, - }); + hintTextTable[RHT_DEKU_TREE_BASEMENT_CHEST] = HintText(CustomMessage("They say that #webs in the Deku Tree# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #toiles dans l'Arbre Mojo# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, entre #telarañas del Gran Árbol Deku# yace #[[1]]#. + hintTextTable[RHT_DEKU_TREE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that in the #center of the Deku Tree# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le coeur de l'Arbre Mojo# recèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al #centro del Gran Árbol Deku# yace #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"in the #center of the Deku Tree# lies", /*french*/"#le coeur de l'Arbre Mojo# recèle", /*spanish*/"al #centro del Gran Árbol Deku# yace"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that a #treasure guarded by a large spider# in the Deku Tree is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor protégé par une grosse araignée# dans l'Arbre Mojo est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #gran araña del Gran Árbol Deku# esconde #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #treasure guarded by a large spider# in the Deku Tree is", /*french*/"le #trésor protégé par une grosse araignée# dans l'Arbre Mojo est", /*spanish*/"una #gran araña del Gran Árbol Deku# esconde"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST] = HintText(CustomMessage("They say that #pillars of wood# in the Deku Tree lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #piliers de bois# dans l'Arbre Mojo indiquent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #salientes del Gran Árbol Deku# conducen a #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#pillars of wood# in the Deku Tree lead to", /*french*/"les #piliers de bois# dans l'Arbre Mojo indiquent", /*spanish*/"los #salientes del Gran Árbol Deku# conducen a"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = HintText(CustomMessage("They say that #pillars of wood# in the Deku Tree lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #piliers de bois# dans l'Arbre Mojo indiquent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #salientes del Gran Árbol Deku# conducen a #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = HintText::Exclude({ - //obscure text - Text{"#pillars of wood# in the Deku Tree lead to", /*french*/"les #piliers de bois# dans l'Arbre Mojo indiquent", /*spanish*/"los #salientes del Gran Árbol Deku# conducen a"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_BASEMENT_CHEST] = HintText(CustomMessage("They say that #webs in the Deku Tree# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #toiles dans l'Arbre Mojo# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, entre #telarañas del Gran Árbol Deku# yace #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_BASEMENT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#webs in the Deku Tree# hide", /*french*/"les #toiles dans l'Arbre Mojo# cachent", /*spanish*/"entre #telarañas del Gran Árbol Deku# yace"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = HintText(CustomMessage("They say that #magical fire in the Deku Tree# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #feu magique dans l'Arbre Mojo# éclaire #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #fuego mágico en el Gran Árbol Deku# conduce a #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = HintText::Exclude({ - //obscure text - Text{"#magical fire in the Deku Tree# leads to", /*french*/"le #feu magique dans l'Arbre Mojo# éclaire", /*spanish*/"el #fuego mágico en el Gran Árbol Deku# conduce a"}, - }); + hintTextTable[RHT_DEKU_TREE_QUEEN_GOHMA_HEART] = HintText(CustomMessage("They say that #Queen Gohma# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #Reine Gohma# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #Reina Goma# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Parasitic Armored Arachnid# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #monstre insectoïde géant# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #arácnido parasitario acorazado# porta #[[1]]#. - hintTable[RHT_DEKU_TREE_QUEEN_GOHMA_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Parasitic Armored Arachnid# holds", /*french*/"le #monstre insectoïde géant# possède", /*spanish*/"el #arácnido parasitario acorazado# porta"}, - }, {}, - //clear text - Text{"#Queen Gohma# holds", /*french*/"la #Reine Gohma# possède", /*spanish*/"la #Reina Goma# porta"} - ); + hintTextTable[RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = HintText(CustomMessage("They say that a #spider deep within the Deku Tree# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au coeur de l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en las profundidades del Árbol Deku# otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider deep within the Deku Tree# hides", /*french*/"une #Skulltula au coeur de l'Arbre Mojo# a", /*spanish*/"una #Skulltula en las profundidades del Árbol Deku# otorga"}, - }); + hintTextTable[RHT_DEKU_TREE_GS_BASEMENT_GATE] = HintText(CustomMessage("They say that a #web protects a spider# within the Deku Tree holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une toile dans l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula protegida por su tela# del Árbol Deku otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_GS_BASEMENT_GATE] = HintText::Exclude({ - //obscure text - Text{"a #web protects a spider# within the Deku Tree holding", /*french*/"une #Skulltula derrière une toile dans l'Arbre Mojo# a", /*spanish*/"una #Skulltula protegida por su tela# del Árbol Deku otorga"}, - }); + hintTextTable[RHT_DEKU_TREE_GS_BASEMENT_VINES] = HintText(CustomMessage("They say that a #web protects a spider# within the Deku Tree holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une toile dans l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula protegida por su tela# del Árbol Deku otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_GS_BASEMENT_VINES] = HintText::Exclude({ - //obscure text - Text{"a #web protects a spider# within the Deku Tree holding", /*french*/"une #Skulltula derrière une toile dans l'Arbre Mojo# a", /*spanish*/"una #Skulltula protegida por su tela# del Árbol Deku otorga"}, - }); + hintTextTable[RHT_DEKU_TREE_GS_COMPASS_ROOM] = HintText(CustomMessage("They say that a #spider atop the Deku Tree# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au sommet de l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en lo alto del Árbol Deku# otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_GS_COMPASS_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider atop the Deku Tree# holds", /*french*/"une #Skulltula au sommet de l'Arbre Mojo# a", /*spanish*/"una #Skulltula en lo alto del Árbol Deku# otorga"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_GS_LOBBY] = HintText(CustomMessage("They say that a #spider in a crate# within the Deku Tree hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une boîte dans l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo una caja# del Árbol Deku otorga #[[1]]#. + hintTextTable[RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM] = HintText(CustomMessage("They say that a #wall of rock protects a spider# within the Deku Tree holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière des rochers dans l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula protegida por una pared rocosa# del Árbol Deku otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_GS_LOBBY] = HintText::Exclude({ - //obscure text - Text{"a #spider in a crate# within the Deku Tree hides", /*french*/"une #Skulltula dans une boîte dans l'Arbre Mojo# a", /*spanish*/"una #Skulltula bajo una caja# del Árbol Deku otorga"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = HintText(CustomMessage("They say that a #spider deep within the Deku Tree# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au coeur de l'Arbre Mojo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en las profundidades del Árbol Deku# otorga #[[1]]#. - hintTable[RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #wall of rock protects a spider# within the Deku Tree holding", /*french*/"une #Skulltula derrière des rochers dans l'Arbre Mojo# a", /*spanish*/"una #Skulltula protegida por una pared rocosa# del Árbol Deku otorga"}, - }); - - hintTable[RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider deep within the Deku Tree# hides", /*french*/"une #Skulltula au coeur de l'Arbre Mojo# a", /*spanish*/"una #Skulltula en las profundidades del Árbol Deku# otorga"}, - }); - - hintTable[RHT_DEKU_TREE_MQ_DEKU_SCRUB] = HintText::Exclude({ - //obscure text - Text{"a #scrub in the Deku Tree# sells", /*french*/"la #peste Mojo dans l'Arbre Mojo# vend", /*spanish*/"un #deku del Gran Árbol Deku# vende"}, - }); + hintTextTable[RHT_DEKU_TREE_MQ_DEKU_SCRUB] = HintText(CustomMessage("They say that a #scrub in the Deku Tree# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo dans l'Arbre Mojo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku del Gran Árbol Deku# vende #[[1]]#. /*-------------------------- | DODONGOS CAVERN | ---------------------------*/ - hintTable[RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#above King Dodongo# lies", /*french*/"#par dessus le Roi Dodongo# gît", /*spanish*/"#sobre el Rey Dodongo# yace"}, - }); +hintTextTable[RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = HintText(CustomMessage("They say that #above King Dodongo# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #par dessus le Roi Dodongo# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #sobre el Rey Dodongo# yace #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #muddy wall in Dodongo's Cavern# hides", /*french*/"le #mur fragile dans la Caverne Dodongo# recèle", /*spanish*/"tras una #agrietada pared en la Cueva de los Dodongos# yace"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MAP_CHEST] = HintText(CustomMessage("They say that a #muddy wall in Dodongo's Cavern# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile dans la Caverne Dodongo# recèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras una #agrietada pared en la Cueva de los Dodongos# yace #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #statue in Dodongo's Cavern# guards", /*french*/"la #statue dans la Caverne Dodongo# protège", /*spanish*/"una #estatua de la Cueva de los Dodongos# esconde"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_COMPASS_CHEST] = HintText(CustomMessage("They say that a #statue in Dodongo's Cavern# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #statue dans la Caverne Dodongo# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #estatua de la Cueva de los Dodongos# esconde #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = HintText::Exclude({ - //obscure text - Text{"above a #maze of stone# in Dodongo's Cavern lies", /*french*/"sur #un labyrinthe de pierre# dans la Caverne Dodongo gît", /*spanish*/"entre un #laberinto de piedra# en la Cueva de los Dodongos yace"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = HintText(CustomMessage("They say that above a #maze of stone# in Dodongo's Cavern lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur #un labyrinthe de pierre# dans la Caverne Dodongo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, entre un #laberinto de piedra# en la Cueva de los Dodongos yace #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #second lizard cavern battle# yields", /*french*/"le #deuxième duel de lézards de caverne# octroie", /*spanish*/"#luchar dos veces contra reptiles en una cueva# conduce a"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST] = HintText(CustomMessage("They say that the #second lizard cavern battle# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #deuxième duel de lézards de caverne# octroie #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #luchar dos veces contra reptiles en una cueva# conduce a #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest at the end of a bridge# yields", /*french*/"le #trésor à l'extrémité d'un pont# contient", /*spanish*/"un #cofre al final de un quebrado puente# contiene"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = HintText(CustomMessage("They say that a #chest at the end of a bridge# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor à l'extrémité d'un pont# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre al final de un quebrado puente# contiene #[[1]]#. + hintTextTable[RHT_DODONGOS_CAVERN_MQ_MAP_CHEST] = HintText(CustomMessage("They say that a #muddy wall in Dodongo's Cavern# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile dans la Caverne Dodongo# recèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #agrietada pared en la Cueva de los Dodongos# esconde #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #muddy wall in Dodongo's Cavern# hides", /*french*/"le #mur fragile dans la Caverne Dodongo# recèle", /*spanish*/"una #agrietada pared en la Cueva de los Dodongos# esconde"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = HintText(CustomMessage("They say that an #elevated alcove# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#alcove haut perchée# dans la Caverne Dodongo cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #elevada alcoba# en la Cueva de los Dodongos brinda #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #elevated alcove# in Dodongo's Cavern holds", /*french*/"l'#alcove haut perchée# dans la Caverne Dodongo cache", /*spanish*/"una #elevada alcoba# en la Cueva de los Dodongos brinda"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that #fire-breathing lizards# in Dodongo's Cavern guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #lézards cracheurs de feu# dans la Caverne Dodongo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #flamígeros reptiles# en la Cueva de los Dodongos esconden #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#fire-breathing lizards# in Dodongo's Cavern guard", /*french*/"les #lézards cracheurs de feu# dans la Caverne Dodongo protègent", /*spanish*/"unos #flamígeros reptiles# en la Cueva de los Dodongos esconden"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = HintText(CustomMessage("They say that #baby spiders# in Dodongo's Cavern guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #petites araignées dans la Caverne Dodongo# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #pequeñas larvas# en la Cueva de los Dodongos esconden #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#baby spiders# in Dodongo's Cavern guard", /*french*/"les #petites araignées dans la Caverne Dodongo# protègent", /*spanish*/"unas #pequeñas larvas# en la Cueva de los Dodongos esconden"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = HintText(CustomMessage("They say that above a #maze of stone# in Dodongo's Cavern lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur #un labyrinthe de pierre# dans la Caverne Dodongo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, sobre un #laberinto de piedra# en la Cueva de los Dodongos yace #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"above a #maze of stone# in Dodongo's Cavern lies", /*french*/"sur #un labyrinthe de pierre# dans la Caverne Dodongo gît", /*spanish*/"sobre un #laberinto de piedra# en la Cueva de los Dodongos yace"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = HintText(CustomMessage("They say that #beneath a headstone# in Dodongo's Cavern lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #sous une pierre tombale# dans la Caverne Dodongo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #bajo una lápida# en la Cueva de los Dodongos yace #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#beneath a headstone# in Dodongo's Cavern lies", /*french*/"#sous une pierre tombale# dans la Caverne Dodongo gît", /*spanish*/"#bajo una lápida# en la Cueva de los Dodongos yace"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_KING_DODONGO_HEART] = HintText(CustomMessage("They say that #King Dodongo# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Roi Dodongo# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el #Rey Dodongo# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Infernal Dinosaur# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #dinosaure infernal# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #dinosaurio infernal# porta #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_KING_DODONGO_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Infernal Dinosaur# holds", /*french*/"le #dinosaure infernal# possède", /*spanish*/"el #dinosaurio infernal# porta"}, - }, {}, - //clear text - Text{"#King Dodongo# holds", /*french*/"le #Roi Dodongo# possède", /*spanish*/"el #Rey Dodongo# porta"} - ); + hintTextTable[RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = HintText(CustomMessage("They say that a #spider entangled in vines# in Dodongo's Cavern guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur les vignes dans la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre unas cepas# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = HintText::Exclude({ - //obscure text - Text{"a #spider entangled in vines# in Dodongo's Cavern guards", /*french*/"une #Skulltula sur les vignes dans la Caverne Dodongo# a", /*spanish*/"una #Skulltula sobre unas cepas# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_GS_SCARECROW] = HintText(CustomMessage("They say that a #spider among explosive slugs# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans l'alcove du couloir dans la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada de explosivos gusanos# otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_GS_SCARECROW] = HintText::Exclude({ - //obscure text - Text{"a #spider among explosive slugs# hides", /*french*/"une #Skulltula dans l'alcove du couloir dans la Caverne Dodongo# a", /*spanish*/"una #Skulltula rodeada de explosivos gusanos# otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = HintText(CustomMessage("They say that a #spider just out of reach# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au haut des escaliers de la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula fuera del alcance# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = HintText::Exclude({ - //obscure text - Text{"a #spider just out of reach# in Dodongo's Cavern holds", /*french*/"une #Skulltula au haut des escaliers de la Caverne Dodongo# a", /*spanish*/"una #Skulltula fuera del alcance# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_GS_BACK_ROOM] = HintText(CustomMessage("They say that a #spider behind a statue# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au coeur de la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras una estatua# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_GS_BACK_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider behind a statue# in Dodongo's Cavern holds", /*french*/"une #Skulltula au coeur de la Caverne Dodongo# a", /*spanish*/"una #Skulltula tras una estatua# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = HintText(CustomMessage("They say that a #spider among bats# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula entourée de Saigneurs dans la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada de murciélagos# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = HintText::Exclude({ - //obscure text - Text{"a #spider among bats# in Dodongo's Cavern holds", /*french*/"une #Skulltula entourée de Saigneurs dans la Caverne Dodongo# a", /*spanish*/"una #Skulltula rodeada de murciélagos# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = HintText(CustomMessage("They say that a #spider high on a wall# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula haut perchée dans la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en lo alto de una pared# de la Cueva de los Dodongos otorga #[[1]]#. + hintTextTable[RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = HintText(CustomMessage("They say that a #spider on top of a pillar of rock# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur l'énorme pilier de roc de la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en lo alto de un pilar# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider high on a wall# in Dodongo's Cavern holds", /*french*/"une #Skulltula haut perchée dans la Caverne Dodongo# a", /*spanish*/"una #Skulltula en lo alto de una pared# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = HintText(CustomMessage("They say that a #spider in a crate# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une boîte de la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo una caja# de la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider on top of a pillar of rock# in Dodongo's Cavern holds", /*french*/"une #Skulltula sur l'énorme pilier de roc de la Caverne Dodongo# a", /*spanish*/"una #Skulltula en lo alto de un pilar# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = HintText(CustomMessage("They say that a #spider among graves# in Dodongo's Cavern holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula parmi les tombes de la Caverne Dodongo# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula entre lápidas# en la Cueva de los Dodongos otorga #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider in a crate# in Dodongo's Cavern holds", /*french*/"une #Skulltula dans une boîte de la Caverne Dodongo# a", /*spanish*/"una #Skulltula bajo una caja# de la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = HintText(CustomMessage("They say that a pair of #scrubs in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus en la Cueva de los Dodongos# venden #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = HintText::Exclude({ - //obscure text - Text{"a #spider among graves# in Dodongo's Cavern holds", /*french*/"une #Skulltula parmi les tombes de la Caverne Dodongo# a", /*spanish*/"una #Skulltula entre lápidas# en la Cueva de los Dodongos otorga"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = HintText(CustomMessage("They say that a #scrub guarded by Lizalfos# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo au coeur de la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku custodiado por Lizalfos# vende #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in Dodongo's Cavern# sells", /*french*/"le #duo de peste Mojo dans la Caverne Dodongo# vend", /*spanish*/"un #par de dekus en la Cueva de los Dodongos# venden"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = HintText(CustomMessage("They say that a pair of #scrubs in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus en la Cueva de los Dodongos# venden #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = HintText::Exclude({ - //obscure text - Text{"a #scrub guarded by Lizalfos# sells", /*french*/"la #peste Mojo au coeur de la Caverne Dodongo# vend", /*spanish*/"un #deku custodiado por Lizalfos# vende"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = HintText(CustomMessage("They say that a #scrub in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo dans l'entrée de la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku en la Cueva de los Dodongos# vende #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in Dodongo's Cavern# sells", /*french*/"le #duo de peste Mojo dans la Caverne Dodongo# vend", /*spanish*/"un #par de dekus en la Cueva de los Dodongos# venden"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = HintText(CustomMessage("They say that a pair of #scrubs in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans l'entrée de la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus en la Cueva de los Dodongos# venden #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = HintText::Exclude({ - //obscure text - Text{"a #scrub in Dodongo's Cavern# sells", /*french*/"la #peste Mojo dans l'entrée de la Caverne Dodongo# vend", /*spanish*/"un #deku en la Cueva de los Dodongos# vende"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = HintText(CustomMessage("They say that a pair of #scrubs in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans l'entrée de la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus en la Cueva de los Dodongos# venden #[[1]]#. + hintTextTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = HintText(CustomMessage("They say that a #scrub in Dodongo's Cavern# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo au sommet des escaliers dans la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku en la Cueva de los Dodongos# vende #[[1]]#. - hintTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in Dodongo's Cavern# sells", /*french*/"le #duo de peste Mojo dans l'entrée de la Caverne Dodongo# vend", /*spanish*/"un #par de dekus en la Cueva de los Dodongos# venden"}, - }); - - hintTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in Dodongo's Cavern# sells", /*french*/"le #duo de peste Mojo dans l'entrée de la Caverne Dodongo# vend", /*spanish*/"un #par de dekus en la Cueva de los Dodongos# venden"}, - }); - - hintTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = HintText::Exclude({ - //obscure text - Text{"a #scrub in Dodongo's Cavern# sells", /*french*/"la #peste Mojo au sommet des escaliers dans la Caverne Dodongo# vend", /*spanish*/"un #deku en la Cueva de los Dodongos# vende"}, - }); - - hintTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = HintText::Exclude({ - //obscure text - Text{"a #scrub guarded by Lizalfos# sells", /*french*/"la #peste Mojo au coeur de la Caverne Dodongo# vend", /*spanish*/"un #deku custodiado por Lizalfos# vende"}, - }); + hintTextTable[RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = HintText(CustomMessage("They say that a #scrub guarded by Lizalfos# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo au coeur de la Caverne Dodongo# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku custodiado por Lizalfos# vende #[[1]]#. /*-------------------------- | JABU JABUS BELLY | ---------------------------*/ - hintTable[RHT_JABU_JABUS_BELLY_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#tentacle trouble# in a deity's belly guards", /*french*/"la #membrane# dans le ventre du gardien protège", /*spanish*/"un #problema tentaculoso# en la tripa de cierta deidad esconde"}, - }, {}, - //clear text - Text{"a #slimy thing# guards", /*french*/"la #chose gluante# gardien protège", /*spanish*/"un #tentáculo parasitario# protege"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_MAP_CHEST] = HintText(CustomMessage("They say that a #slimy thing# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #chose gluante# gardien protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #tentáculo parasitario# protege #[[1]]#. + {}, { + CustomMessage("They say that #tentacle trouble# in a deity's belly guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #membrane# dans le ventre du gardien protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #problema tentaculoso# en la tripa de cierta deidad esconde #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#bubble trouble# in a deity's belly guards", /*french*/"un #horde de bulles# dans le ventre du gardien protègent", /*spanish*/"un #problema burbujesco# en la tripa de cierta deidad esconde"}, - }, {}, - //clear text - Text{"#bubbles# guard", /*french*/"des #bulles# entourent", /*spanish*/"unas #burbujas# protegen"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_COMPASS_CHEST] = HintText(CustomMessage("They say that #bubbles# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #bulles# entourent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, unas #burbujas# protegen #[[1]]#. + {}, { + CustomMessage("They say that #bubble trouble# in a deity's belly guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #horde de bulles# dans le ventre du gardien protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #problema burbujesco# en la tripa de cierta deidad esconde #[[1]]#. + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = HintText(CustomMessage("They say that shooting a #mouth cow# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, tirer sur une #vache# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #dispararle a una vaca# revela #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"shooting a #mouth cow# reveals", /*french*/"tirer sur une #vache# révèle", /*spanish*/"#dispararle a una vaca# revela"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST] = HintText(CustomMessage("They say that a #boulder before cows# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #rochers près des vaches# cachent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, cierta #roca rodeada de vacas# esconde #[[1]]#. + {}, { + CustomMessage("They say that #pop rocks# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #pierres aux reins# cachent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #cepillarse los dientes con explosivos# revela #[[1]]#. + CustomMessage("They say that an #explosive palate# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #gargouillis explosifs# cachent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #paladar explosivo# esconde #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#pop rocks# hide", /*french*/"des #pierres aux reins# cachent", /*spanish*/"#cepillarse los dientes con explosivos# revela"}, - Text{"an #explosive palate# holds", /*french*/"des #gargouillis explosifs# cachent", /*spanish*/"un #paladar explosivo# esconde"}, - }, {}, - //clear text - Text{"a #boulder before cows# hides", /*french*/"des #rochers près des vaches# cachent", /*spanish*/"cierta #roca rodeada de vacas# esconde"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = HintText(CustomMessage("They say that near a #spiked elevator# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, près d'un #ascenseur visqueux# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, cerca de un #ascensor puntiagudo# yace #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"near a #spiked elevator# lies", /*french*/"près d'un #ascenseur visqueux# gît", /*spanish*/"cerca de un #ascensor puntiagudo# yace"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that a #drowning cow# unveils #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #vache à l'eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca sumergida# revela #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #drowning cow# unveils", /*french*/"une #vache à l'eau# a", /*spanish*/"una #vaca sumergida# revela"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = HintText(CustomMessage("They say that #moving anatomy# creates a path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #organe descendant# mène à #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #ser movedizo entre paredes# conduce a #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#moving anatomy# creates a path to", /*french*/"un #organe descendant# mène à", /*spanish*/"un #ser movedizo entre paredes# conduce a"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = HintText(CustomMessage("They say that a #pair of digested cows# hold #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #deux boeufs digérés# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de digeridas vacas# otorgan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #pair of digested cows# hold", /*french*/"#deux boeufs digérés# détiennent", /*spanish*/"un #par de digeridas vacas# otorgan"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = HintText(CustomMessage("They say that a #pair of digested cows# hold #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #deux boeufs digérés# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de digeridas vacas# otorgan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #pair of digested cows# hold", /*french*/"#deux boeufs digérés# détiennent", /*spanish*/"un #par de digeridas vacas# otorgan"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = HintText(CustomMessage("They say that the #final cows' reward# in a deity's belly is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #cadeau des dernières vaches# estomacales est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #vacas al final# de la tripa de cierta deidad otorgan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #final cows' reward# in a deity's belly is", /*french*/"le #cadeau des dernières vaches# estomacales est", /*spanish*/"las #vacas al final# de la tripa de cierta deidad otorgan"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = HintText(CustomMessage("They say that #cows protected by falling monsters# in a deity's belly guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #vaches protégées par des monstres tombants# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #vacas custodiadas por monstruos del techo# de la tripa de cierta deidad otorgan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#cows protected by falling monsters# in a deity's belly guard", /*french*/"des #vaches protégées par des monstres tombants# cachent", /*spanish*/"unas #vacas custodiadas por monstruos del techo# de la tripa de cierta deidad otorgan"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = HintText(CustomMessage("They say that a school of #stingers swallowed by Jabu-Jabu# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies avallées par Jabu-Jabu# protègent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, unos #stingers engullidos por Jabu-Jabu# guardan #[[1]]#. + {}, { + CustomMessage("They say that a school of #stingers swallowed by a deity# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies avallées par le gardien# protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, unos #stingers engullidos por cierta deidad# guardan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = HintText::Exclude({ - //obscure text - Text{"a school of #stingers swallowed by a deity# guard", /*french*/"les #raies avallées par le gardien# protègent", /*spanish*/"unos #stingers engullidos por cierta deidad# guardan"}, - }, {}, - //clear text - Text{"a school of #stingers swallowed by Jabu-Jabu# guard", /*french*/"les #raies avallées par Jabu-Jabu# protègent", /*spanish*/"unos #stingers engullidos por Jabu-Jabu# guardan"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = HintText(CustomMessage("They say that a school of #stingers swallowed by Jabu-Jabu# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies avallées par Jabu-Jabu# protègent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, unos #stingers engullidos por Jabu-Jabu# guardan #[[1]]#. + {}, { + CustomMessage("They say that a school of #stingers swallowed by a deity# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #raies avallées par le gardien# protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, unos #stingers engullidos por cierta deidad# guardan #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = HintText::Exclude({ - //obscure text - Text{"a school of #stingers swallowed by a deity# guard", /*french*/"les #raies avallées par le gardien# protègent", /*spanish*/"unos #stingers engullidos por cierta deidad# guardan"}, - }, {}, - //clear text - Text{"a school of #stingers swallowed by Jabu-Jabu# guard", /*french*/"les #raies avallées par Jabu-Jabu# protègent", /*spanish*/"unos #stingers engullidos por Jabu-Jabu# guardan"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_BARINADE_HEART] = HintText(CustomMessage("They say that #Barinade# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Barinade# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Barinade# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Bio-Electric Anemone# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#anémone bioélectrique# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, la #anémona bioeléctrica# porta #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_BARINADE_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Bio-Electric Anemone# holds", /*french*/"l'#anémone bioélectrique# possède", /*spanish*/"la #anémona bioeléctrica# porta"}, - }, {}, - //clear text - Text{"#Barinade# holds", /*french*/"#Barinade# possède", /*spanish*/"#Barinade# porta"} - ); + hintTextTable[RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = HintText(CustomMessage("They say that a #spider resting near a princess# in Jabu-Jabu's Belly holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près de la princesse dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula junto a una princesa# en la Tripa de Jabu-Jabu otorga #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = HintText::Exclude({ - //obscure text - Text{"a #spider resting near a princess# in Jabu-Jabu's Belly holds", /*french*/"une #Skulltula près de la princesse dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula junto a una princesa# en la Tripa de Jabu-Jabu otorga"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = HintText(CustomMessage("They say that a #spider resting near a princess# in Jabu-Jabu's Belly holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près de la princesse dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula junto a una princesa# en la Tripa de Jabu-Jabu otorga #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = HintText::Exclude({ - //obscure text - Text{"a #spider resting near a princess# in Jabu-Jabu's Belly holds", /*french*/"une #Skulltula près de la princesse dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula junto a una princesa# en la Tripa de Jabu-Jabu otorga"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS] = HintText(CustomMessage("They say that #jellyfish surround a spider# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula entourée de méduses dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada de medusas# otorga #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS] = HintText::Exclude({ - //obscure text - Text{"#jellyfish surround a spider# holding", /*french*/"une #Skulltula entourée de méduses dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula rodeada de medusas# otorga"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = HintText(CustomMessage("They say that a #spider guarded by a school of stingers# in Jabu-Jabu's Belly holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par des raies dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada por unos stingers# en la Tripa de Jabu-Jabu otorga #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider guarded by a school of stingers# in Jabu-Jabu's Belly holds", /*french*/"une #Skulltula protégée par des raies dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula rodeada por unos stingers# en la Tripa de Jabu-Jabu otorga"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = HintText(CustomMessage("They say that a #spider surrounded by electricity# in Jabu-Jabu's Belly holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula entourée d'électricité dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada de electricidad# en la Tripa de Jabu-Jabu otorga #[[1]]#. + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = HintText(CustomMessage("They say that a #spider guarded by a school of stingers# in Jabu-Jabu's Belly holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par des raies dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula protegida por unos stingers# en la Tripa de Jabu-Jabu otorga #[[1]]#. - hintTable[RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider surrounded by electricity# in Jabu-Jabu's Belly holds", /*french*/"une #Skulltula entourée d'électricité dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula rodeada de electricidad# en la Tripa de Jabu-Jabu otorga"}, - }); - - hintTable[RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider guarded by a school of stingers# in Jabu-Jabu's Belly holds", /*french*/"une #Skulltula protégée par des raies dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula protegida por unos stingers# en la Tripa de Jabu-Jabu otorga"}, - }); - - hintTable[RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = HintText::Exclude({ - //obscure text - Text{"a #spider in a web within Jabu-Jabu's Belly# holds", /*french*/"une #Skulltula sur une toile dans le Ventre de Jabu-Jabu# a", /*spanish*/"una #Skulltula sobre una red# en la Tripa de Jabu-Jabu otorga"}, - }); - - hintTable[RHT_JABU_JABUS_BELLY_DEKU_SCRUB] = HintText::Exclude({ - //obscure text - Text{"a #scrub in a deity# sells", /*french*/"la #peste Mojo dans le ventre du gardien# vend", /*spanish*/"un #deku dentro de cierta deidad# vende"}, - }); + hintTextTable[RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = HintText(CustomMessage("They say that a #spider in a web within Jabu-Jabu's Belly# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une toile dans le Ventre de Jabu-Jabu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre una red# en la Tripa de Jabu-Jabu otorga #[[1]]#. + hintTextTable[RHT_JABU_JABUS_BELLY_DEKU_SCRUB] = HintText(CustomMessage("They say that a #scrub in a deity# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo dans le ventre du gardien# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku dentro de cierta deidad# vende #[[1]]#. /*-------------------------- | FOREST TEMPLE | ---------------------------*/ - hintTable[RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #tree in the Forest Temple# supports", /*french*/"sur l'#arbre dans le Temple de la Forêt# gît", /*spanish*/"sobre un #árbol del Templo del Bosque# yace"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST] = HintText(CustomMessage("They say that a #tree in the Forest Temple# supports #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur l'#arbre dans le Temple de la Forêt# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, sobre un #árbol del Templo del Bosque# yace #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#defeating enemies beneath a falling ceiling# in Forest Temple yields", /*french*/"#deux squelettes# dans le Temple de la Forêt protègent", /*spanish*/"#derrotar enemigos caídos de lo alto# del Templo del Bosque revela"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = HintText(CustomMessage("They say that #defeating enemies beneath a falling ceiling# in Forest Temple yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #deux squelettes# dans le Temple de la Forêt protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar enemigos caídos de lo alto# del Templo del Bosque revela #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_WELL_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #sunken chest deep in the woods# contains", /*french*/"le #coffre submergé dans la forêt# contient", /*spanish*/"un #sumergido cofre en lo profundo del bosque# contiene"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_WELL_CHEST] = HintText(CustomMessage("They say that a #sunken chest deep in the woods# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre submergé dans la forêt# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #sumergido cofre en lo profundo del bosque# contiene #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #fiery skull# in Forest Temple guards", /*french*/"le #crâne enflammé# dans le Temple de la Forêt protège", /*spanish*/"una #ardiente calavera# del Templo del Bosque esconde"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MAP_CHEST] = HintText(CustomMessage("They say that a #fiery skull# in Forest Temple guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #crâne enflammé# dans le Temple de la Forêt protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #ardiente calavera# del Templo del Bosque esconde #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest on a small island# in the Forest Temple holds", /*french*/"le #coffre sur l'îlot# du Temple de la Forêt contient", /*spanish*/"un #cofre sobre una isla# del Templo del Bosque contiene"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = HintText(CustomMessage("They say that a #chest on a small island# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre sur l'îlot# du Temple de la Forêt contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre sobre una isla# del Templo del Bosque contiene #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"beneath a #checkerboard falling ceiling# lies", /*french*/"sous #l'échiquier tombant# gît", /*spanish*/"tras un #techo de ajedrez# yace"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = HintText(CustomMessage("They say that beneath a #checkerboard falling ceiling# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sous #l'échiquier tombant# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras un #techo de ajedrez# yace #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #sharp eye# will spot", /*french*/"l'#oeil perçant# dans la forêt verra", /*spanish*/"un #afilado ojo# revela"}, - }, {}, - //clear text - Text{"#blocks of stone# in the Forest Temple surround", /*french*/"les #blocs dans le Temple de la Forêt# entourent", /*spanish*/"cerca de unos #bloques de piedra# del Templo del Bosque yace"} - ); + hintTextTable[RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST] = HintText(CustomMessage("They say that #blocks of stone# in the Forest Temple surround #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #blocs dans le Temple de la Forêt# entourent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, cerca de unos #bloques de piedra# del Templo del Bosque yace #[[1]]#. + {}, { + CustomMessage("They say that a #sharp eye# will spot #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil perçant# dans la forêt verra #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #afilado ojo# revela #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #turned trunk# contains", /*french*/"le #coffre pivoté# contient", /*spanish*/"en una #sala con otro punto de vista# se esconde"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a #turned trunk# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre pivoté# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en una #sala con otro punto de vista# se esconde #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_FLOORMASTER_CHEST] = HintText::Exclude({ - //obscure text - Text{"deep in the forest #shadows guard a chest# containing", /*french*/"l'#ombre de la forêt# protège un coffre contenant", /*spanish*/"en lo profundo del bosque #unas sombras# esconden"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_FLOORMASTER_CHEST] = HintText(CustomMessage("They say that deep in the forest #shadows guard a chest# containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#ombre de la forêt# protège un coffre contenant #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo profundo del bosque #unas sombras# esconden #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_BOW_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #army of the dead# guards", /*french*/"des #squelettes sylvestres# protègent", /*spanish*/"un #ejército de soldados caídos# guarda"}, - }, {}, - //clear text - Text{"#Stalfos deep in the Forest Temple# guard", /*french*/"#trois squelettes dans le Temple de la Forêt# protègent", /*spanish*/"los #Stalfos en lo profundo del Templo del Bosque# guardan"} - ); + hintTextTable[RHT_FOREST_TEMPLE_BOW_CHEST] = HintText(CustomMessage("They say that #Stalfos deep in the Forest Temple# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #trois squelettes dans le Temple de la Forêt# protègent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, los #Stalfos en lo profundo del Templo del Bosque# guardan #[[1]]#. + {}, { + CustomMessage("They say that an #army of the dead# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #squelettes sylvestres# protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #ejército de soldados caídos# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_RED_POE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Joelle# guards", /*french*/"#Joelle# protège", /*spanish*/"#Joelle# guarda"}, - }, {}, - //clear text - Text{"a #red ghost# guards", /*french*/"le #fantôme rouge# protège", /*spanish*/"un #espectro rojo# guarda"} - ); + hintTextTable[RHT_FOREST_TEMPLE_RED_POE_CHEST] = HintText(CustomMessage("They say that a #red ghost# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #fantôme rouge# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #espectro rojo# guarda #[[1]]#. + {}, { + CustomMessage("They say that #Joelle# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Joelle# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #Joelle# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_BLUE_POE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Beth# guards", /*french*/"#Beth# protège", /*spanish*/"#Beth# guarda"}, - }, {}, - //clear text - Text{"a #blue ghost# guards", /*french*/"le #fantôme bleu# protège", /*spanish*/"un #espectro azul# guarda"} - ); + hintTextTable[RHT_FOREST_TEMPLE_BLUE_POE_CHEST] = HintText(CustomMessage("They say that a #blue ghost# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #fantôme bleu# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #espectro azul# guarda #[[1]]#. + {}, { + CustomMessage("They say that #Beth# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Beth# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #Beth# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_BASEMENT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#revolving walls# in the Forest Temple conceal", /*french*/"des #murs rotatifs dans la forêt# recèlent", /*spanish*/"las #paredes giratorias# del Templo del Bosque conceden"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_BASEMENT_CHEST] = HintText(CustomMessage("They say that #revolving walls# in the Forest Temple conceal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #murs rotatifs dans la forêt# recèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes giratorias# del Templo del Bosque conceden #[[1]]#. + hintTextTable[RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = HintText(CustomMessage("They say that a #tree in the Forest Temple# supports #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur l'#arbre dans le Temple de la Forêt# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, sobre un #árbol del Templo del Bosque# yace #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #tree in the Forest Temple# supports", /*french*/"sur l'#arbre dans le Temple de la Forêt# gît", /*spanish*/"sobre un #árbol del Templo del Bosque# yace"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = HintText(CustomMessage("They say that #defeating enemies beneath a falling ceiling# in Forest Temple yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #deux squelettes# dans le Temple de la Forêt protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar enemigos caídos de lo alto# del Templo del Bosque revela #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#defeating enemies beneath a falling ceiling# in Forest Temple yields", /*french*/"#deux squelettes# dans le Temple de la Forêt protègent", /*spanish*/"#derrotar enemigos caídos de lo alto# del Templo del Bosque revela"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_BOW_CHEST] = HintText(CustomMessage("They say that #Stalfos deep in the Forest Temple# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #trois squelettes dans le Temple de la Forêt# protègent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, los #Stalfos en lo profundo del Templo del Bosque# guardan #[[1]]#. + {}, { + CustomMessage("They say that an #army of the dead# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #squelettes sylvestres# protègent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #ejército de soldados caídos# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_BOW_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #army of the dead# guards", /*french*/"des #squelettes sylvestres# protègent", /*spanish*/"un #ejército de soldados caídos# guarda"}, - }, {}, - //clear text - Text{"#Stalfos deep in the Forest Temple# guard", /*french*/"#trois squelettes dans le Temple de la Forêt# protègent", /*spanish*/"los #Stalfos en lo profundo del Templo del Bosque# guardan"} - ); + hintTextTable[RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = HintText(CustomMessage("They say that a #chest on a small island# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre sur l'îlot# du Temple de la Forêt contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre sobre una isla# del Templo del Bosque contiene #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest on a small island# in the Forest Temple holds", /*french*/"le #coffre sur l'îlot# du Temple de la Forêt contient", /*spanish*/"un #cofre sobre una isla# del Templo del Bosque contiene"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = HintText(CustomMessage("They say that #high in a courtyard# within the Forest Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #haut perché dans le jardin# du Temple de la Forêt gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre en lo alto de un patio# del Templo del Bosque contiene #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#high in a courtyard# within the Forest Temple is", /*french*/"#haut perché dans le jardin# du Temple de la Forêt gît", /*spanish*/"un #cofre en lo alto de un patio# del Templo del Bosque contiene"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_WELL_CHEST] = HintText(CustomMessage("They say that a #sunken chest deep in the woods# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre submergé dans la forêt# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #sumergido cofre en lo profundo del bosque# contiene #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_WELL_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #sunken chest deep in the woods# contains", /*french*/"le #coffre submergé dans la forêt# contient", /*spanish*/"un #sumergido cofre en lo profundo del bosque# contiene"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that a #red ghost# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #fantôme rouge# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #fantasma rojo# guarda #[[1]]#. + {}, { + CustomMessage("They say that #Joelle# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Joelle# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #Joelle# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Joelle# guards", /*french*/"#Joelle# protège", /*spanish*/"#Joelle# guarda"}, - }, {}, - //clear text - Text{"a #red ghost# guards", /*french*/"le #fantôme rouge# protège", /*spanish*/"un #fantasma rojo# guarda"} - ); + hintTextTable[RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that a #blue ghost# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #fantôme bleu# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #fantasma azul# guarda #[[1]]#. + {}, { + CustomMessage("They say that #Beth# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Beth# protège #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #Beth# guarda #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Beth# guards", /*french*/"#Beth# protège", /*spanish*/"#Beth# guarda"}, - }, {}, - //clear text - Text{"a #blue ghost# guards", /*french*/"le #fantôme bleu# protège", /*spanish*/"un #fantasma azul# guarda"} - ); + hintTextTable[RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = HintText(CustomMessage("They say that beneath a #checkerboard falling ceiling# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sous #l'échiquier tombant# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras un #techo de ajedrez# yace #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"beneath a #checkerboard falling ceiling# lies", /*french*/"sous #l'échiquier tombant# gît", /*spanish*/"tras un #techo de ajedrez# yace"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = HintText(CustomMessage("They say that #revolving walls# in the Forest Temple conceal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #murs rotatifs dans la forêt# recèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes giratorias# del Templo del Bosque conceden #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#revolving walls# in the Forest Temple conceal", /*french*/"des #murs rotatifs dans la forêt# recèlent", /*spanish*/"las #paredes giratorias# del Templo del Bosque conceden"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST] = HintText(CustomMessage("They say that deep in the forest #undead guard a chest# containing #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #revenants dans le Temple de la Forêt# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo profundo del bosque #guardias del más allá# guardan #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST] = HintText::Exclude({ - //obscure text - Text{"deep in the forest #undead guard a chest# containing", /*french*/"des #revenants dans le Temple de la Forêt# protègent", /*spanish*/"en lo profundo del bosque #guardias del más allá# guardan"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a #turned trunk# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre pivoté# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en una #sala con otro punto de vista# se esconde #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #turned trunk# contains", /*french*/"le #coffre pivoté# contient", /*spanish*/"en una #sala con otro punto de vista# se esconde"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART] = HintText(CustomMessage("They say that #Phantom Ganon# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Ganon Spectral# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Ganon Fantasma# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Evil Spirit from Beyond# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#esprit maléfique de l'au-delà# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #espíritu maligno de ultratumba# porta #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Evil Spirit from Beyond# holds", /*french*/"l'#esprit maléfique de l'au-delà# possède", /*spanish*/"el #espíritu maligno de ultratumba# porta"}, - }, {}, - //clear text - Text{"#Phantom Ganon# holds", /*french*/"#Ganon Spectral# possède", /*spanish*/"#Ganon Fantasma# porta"} - ); + hintTextTable[RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = HintText(CustomMessage("They say that a #spider on a small island# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur l'îlot du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre una pequeña isla# del Templo del Bosque otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = HintText::Exclude({ - //obscure text - Text{"a #spider on a small island# in the Forest Temple holds", /*french*/"une #Skulltula sur l'îlot du Temple de la Forêt# a", /*spanish*/"una #Skulltula sobre una pequeña isla# del Templo del Bosque otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_GS_FIRST_ROOM] = HintText(CustomMessage("They say that a #spider high on a wall of vines# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur un mur de vignes du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en lo alto de una pared de cepas# del Templo del Bosque otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_GS_FIRST_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider high on a wall of vines# in the Forest Temple holds", /*french*/"une #Skulltula sur un mur de vignes du Temple de la Forêt# a", /*spanish*/"una #Skulltula en lo alto de una pared de cepas# del Templo del Bosque otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = HintText(CustomMessage("They say that #stone columns# lead to a spider in the Forest Temple hiding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula haut perchée dans le jardin du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #columnas del Templo del Bosque# conducen a una Skulltula que otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = HintText::Exclude({ - //obscure text - Text{"#stone columns# lead to a spider in the Forest Temple hiding", /*french*/"une #Skulltula haut perchée dans le jardin du Temple de la Forêt# a", /*spanish*/"unas #columnas del Templo del Bosque# conducen a una Skulltula que otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_GS_LOBBY] = HintText(CustomMessage("They say that a #spider among ghosts# in the Forest Temple guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans la grande salle du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula rodeada de fantasmas# del Templo del Bosque otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_GS_LOBBY] = HintText::Exclude({ - //obscure text - Text{"a #spider among ghosts# in the Forest Temple guards", /*french*/"une #Skulltula dans la grande salle du Temple de la Forêt# a", /*spanish*/"una #Skulltula rodeada de fantasmas# del Templo del Bosque otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_GS_BASEMENT] = HintText(CustomMessage("They say that a #spider within revolving walls# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière les murs pivotants du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula entre paredes giratorias# del Templo del Bosque otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_GS_BASEMENT] = HintText::Exclude({ - //obscure text - Text{"a #spider within revolving walls# in the Forest Temple holds", /*french*/"une #Skulltula derrière les murs pivotants du Temple de la Forêt# a", /*spanish*/"una #Skulltula entre paredes giratorias# del Templo del Bosque otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = HintText(CustomMessage("They say that an #ivy-hidden spider# in the Forest Temple hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près de l'entrée du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula escondida entre cepas# del Templo del Bosque otorga #[[1]]#. + hintTextTable[RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = HintText(CustomMessage("They say that a #spider in a hidden nook# within the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un recoin caché du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en una esquina oculta# del Templo del Bosque otorga #[[1]]#. - hintTable[RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = HintText::Exclude({ - //obscure text - Text{"an #ivy-hidden spider# in the Forest Temple hoards", /*french*/"une #Skulltula près de l'entrée du Temple de la Forêt# a", /*spanish*/"una #Skulltula escondida entre cepas# del Templo del Bosque otorga"}, - }); - - hintTable[RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider in a hidden nook# within the Forest Temple holds", /*french*/"une #Skulltula dans un recoin caché du Temple de la Forêt# a", /*spanish*/"una #Skulltula en una esquina oculta# del Templo del Bosque otorga"}, - }); - - hintTable[RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = HintText::Exclude({ - //obscure text - Text{"a #spider on an arch# in the Forest Temple holds", /*french*/"une #Skulltula sur une arche du Temple de la Forêt# a", /*spanish*/"una #Skulltula sobre un arco# del Templo del Bosque otorga"}, - }); - - hintTable[RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = HintText::Exclude({ - //obscure text - Text{"a #spider on a ledge# in the Forest Temple holds", /*french*/"une #Skulltula dans le jardin du Temple de la Forêt# a", /*spanish*/"una #Skulltula en un borde# del Templo del Bosque otorga"}, - }); - - hintTable[RHT_FOREST_TEMPLE_MQ_GS_WELL] = HintText::Exclude({ - //obscure text - Text{"#draining a well# in Forest Temple uncovers a spider with", /*french*/"une #Skulltula au fond du Puits du Temple de la Forêt# a", /*spanish*/"#vaciar el pozo# del Templo del Bosque desvela una Skulltula que otorga"}, - }); + hintTextTable[RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = HintText(CustomMessage("They say that a #spider on an arch# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une arche du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre un arco# del Templo del Bosque otorga #[[1]]#. + hintTextTable[RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = HintText(CustomMessage("They say that a #spider on a ledge# in the Forest Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans le jardin du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en un borde# del Templo del Bosque otorga #[[1]]#. + hintTextTable[RHT_FOREST_TEMPLE_MQ_GS_WELL] = HintText(CustomMessage("They say that #draining a well# in Forest Temple uncovers a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au fond du Puits du Temple de la Forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #vaciar el pozo# del Templo del Bosque desvela una Skulltula que otorga #[[1]]#. + /*-------------------------- | FIRE TEMPLE | ---------------------------*/ - hintTable[RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#near a dragon# is", /*french*/"#près d'un dragon# gît", /*spanish*/"#cerca de un dragón# yace"}, - }); +hintTextTable[RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST] = HintText(CustomMessage("They say that #near a dragon# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #près d'un dragon# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cerca de un dragón# yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Flare Dancer behind a totem# guards", /*french*/"le #Danse-Flamme derrière un totem# protège", /*spanish*/"el #Bailafuego tras unos tótems# esconde"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST] = HintText(CustomMessage("They say that the #Flare Dancer behind a totem# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Danse-Flamme derrière un totem# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Bailafuego tras unos tótems# esconde #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #prison beyond a totem# holds", /*french*/"la #prison derrière un totem# contient", /*spanish*/"en una #prisión tras unos tótems# yace"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a #prison beyond a totem# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #prison derrière un totem# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en una #prisión tras unos tótems# yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = HintText::Exclude({ - //obscure text - Text{"#explosives over a lava pit# unveil", /*french*/"des #explosifs dans un lac de lave# révèlent", /*spanish*/"los #explosivos en un mar de llamas# revelan"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = HintText(CustomMessage("They say that #explosives over a lava pit# unveil #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #explosifs dans un lac de lave# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #explosivos en un mar de llamas# revelan #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron trapped near lava# holds", /*french*/"le #Goron emprisonné près de la lave# a", /*spanish*/"un #goron atrapado cerca de un mar de llamas# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = HintText(CustomMessage("They say that a #Goron trapped near lava# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron emprisonné près de la lave# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron atrapado cerca de un mar de llamas# guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron at the end of a maze# holds", /*french*/"le #Goron dans le labyrinthe# a", /*spanish*/"un #goron al final de un laberinto# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = HintText(CustomMessage("They say that a #Goron at the end of a maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron dans le labyrinthe# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron al final de un laberinto# guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron above a maze# holds", /*french*/"le #Goron au dessus du labyrinthe# a", /*spanish*/"un #goron sobre un laberinto# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = HintText(CustomMessage("They say that a #Goron above a maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron au dessus du labyrinthe# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron sobre un laberinto# guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron hidden near a maze# holds", /*french*/"le #Goron caché près du labyrinthe# a", /*spanish*/"un #goron escondido tras un laberinto# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = HintText(CustomMessage("They say that a #Goron hidden near a maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron caché près du labyrinthe# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron escondido tras un laberinto# guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #blocked path# in Fire Temple holds", /*french*/"un #sol fragile dans le Temple du Feu# contient", /*spanish*/"en un #camino bloqueado# del Templo del Fuego yace"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = HintText(CustomMessage("They say that a #blocked path# in Fire Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #sol fragile dans le Temple du Feu# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en un #camino bloqueado# del Templo del Fuego yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #caged chest# in the Fire Temple hoards", /*french*/"un #coffre emprisonné# dans le Temple du Feu contient", /*spanish*/"un #cofre entre rejas# del Templo del Fuego contiene"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MAP_CHEST] = HintText(CustomMessage("They say that a #caged chest# in the Fire Temple hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #coffre emprisonné# dans le Temple du Feu contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre entre rejas# del Templo del Fuego contiene #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest in a fiery maze# contains", /*french*/"un #coffre dans un labyrinthe enflammé# contient", /*spanish*/"un #cofre de un ardiente laberinto# contiene"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_COMPASS_CHEST] = HintText(CustomMessage("They say that a #chest in a fiery maze# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #coffre dans un labyrinthe enflammé# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre de un ardiente laberinto# contiene #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron atop the Fire Temple# holds", /*french*/"le #Goron au sommet du Temple du Feu# a", /*spanish*/"un #goron en lo alto del Templo del Fuego# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = HintText(CustomMessage("They say that a #Goron atop the Fire Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron au sommet du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron en lo alto del Templo del Fuego# guarda #[[1]]#. + hintTextTable[RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = HintText(CustomMessage("They say that #near a dragon# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #près d'un dragon# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cerca de un dragón# yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#near a dragon# is", /*french*/"#près d'un dragon# gît", /*spanish*/"#cerca de un dragón# yace"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = HintText(CustomMessage("They say that the #Flare Dancer in the depths of the Fire Temple# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Danse-Flamme au coeur du volcan# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el #Bailafuego en lo profundo del Templo del Fuego# esconde #[[1]]#. + {}, { + CustomMessage("They say that the #Flare Dancer in the depths of a volcano# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Danse-Flamme au coeur du volcan# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Bailafuego en lo profundo del volcán# esconde #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Flare Dancer in the depths of a volcano# guards", /*french*/"le #Danse-Flamme au coeur du volcan# a", /*spanish*/"el #Bailafuego en lo profundo del volcán# esconde"}, - }, {}, - //clear text - Text{"the #Flare Dancer in the depths of the Fire Temple# guards", /*french*/"le #Danse-Flamme au coeur du volcan# a", /*spanish*/"el #Bailafuego en lo profundo del Templo del Fuego# esconde"} - ); + hintTextTable[RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that a #blocked path# in Fire Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chemin scellé# dans le Temple du Feu contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en un #camino bloqueado# del Templo del Fuego yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #blocked path# in Fire Temple holds", /*french*/"le #chemin scellé# dans le Temple du Feu contient", /*spanish*/"en un #camino bloqueado# del Templo del Fuego yace"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = HintText(CustomMessage("They say that #crates in a maze# contain #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #boîtes dans le labyrinthe# contiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #cajas de un laberinto# contienen #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#crates in a maze# contain", /*french*/"des #boîtes dans le labyrinthe# contiennent", /*spanish*/"las #cajas de un laberinto# contienen"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = HintText(CustomMessage("They say that #crates in a maze# contain #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #boîtes dans le labyrinthe# contiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #cajas de un laberinto# contienen #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#crates in a maze# contain", /*french*/"des #boîtes dans le labyrinthe# contiennent", /*spanish*/"las #cajas de un laberinto# contienen"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = HintText(CustomMessage("They say that a #falling slug# in the Fire Temple guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #limace tombante# dans le Temple du Feu protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #babosa del techo# del Templo del Fuego guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #falling slug# in the Fire Temple guards", /*french*/"la #limace tombante# dans le Temple du Feu protège", /*spanish*/"una #babosa del techo# del Templo del Fuego guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that using a #hammer in the depths of the Fire Temple# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, frapper du #marteau au coeur du volcan# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, usar el #martillo en lo profundo del Templo del Fuego# revela #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"using a #hammer in the depths of the Fire Temple# reveals", "frapper du #marteau au coeur du volcan# révèle", /*spanish*/"usar el #martillo en lo profundo del Templo del Fuego# revela"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that #illuminating a lava pit# reveals the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #éclairer le lac de lave# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #iluminar un mar de llamas# revela #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#illuminating a lava pit# reveals the path to", /*french*/"#éclairer le lac de lave# révèle", /*spanish*/"#iluminar un mar de llamas# revela"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = HintText(CustomMessage("They say that #explosives over a lava pit# unveil #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #explosifs dans un lac de lave# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #explosivos en un mar de llamas# revelan #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = HintText::Exclude({ - //obscure text - Text{"#explosives over a lava pit# unveil", /*french*/"des #explosifs dans un lac de lave# révèlent", /*spanish*/"los #explosivos en un mar de llamas# revelan"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = HintText(CustomMessage("They say that a #Goron hidden near a maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Goron caché près du labyrinthe# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #goron cerca de un laberinto# guarda #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #Goron hidden near a maze# holds", /*french*/"le #Goron caché près du labyrinthe# a", /*spanish*/"un #goron cerca de un laberinto# guarda"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = HintText(CustomMessage("They say that hidden #beneath a block of stone# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, caché #derrière un bloc de pierre# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #bajo unos bloques de piedra# yace #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"hidden #beneath a block of stone# lies", /*french*/"caché #derrière un bloc de pierre# gît", /*spanish*/"#bajo unos bloques de piedra# yace"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_VOLVAGIA_HEART] = HintText(CustomMessage("They say that #Volvagia# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Volvagia# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Volvagia# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Subterranean Lava Dragon# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #dragon des profondeurs# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #dragón de lava subterráneo# porta #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_VOLVAGIA_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Subterranean Lava Dragon# holds", /*french*/"le #dragon des profondeurs# possède", /*spanish*/"el #dragón de lava subterráneo# porta"}, - }, {}, - //clear text - Text{"#Volvagia# holds", /*french*/"#Volvagia# possède", /*spanish*/"#Volvagia# porta"} - ); + hintTextTable[RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = HintText(CustomMessage("They say that #eight tiles of malice# guard a spider holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par huit tuiles dans le Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #ocho baldosas de maldad# custodian una Skulltula que otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = HintText::Exclude({ - //obscure text - Text{"#eight tiles of malice# guard a spider holding", /*french*/"une #Skulltula protégée par huit tuiles dans le Temple du Feu# a", /*spanish*/"#ocho baldosas de maldad# custodian una Skulltula que otorga"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = HintText(CustomMessage("They say that #five tiles of malice# guard a spider holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par cinq tuiles dans le Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cinco baldosas de maldad# custodian una Skulltula que otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = HintText::Exclude({ - //obscure text - Text{"#five tiles of malice# guard a spider holding", /*french*/"une #Skulltula protégée par cinq tuiles dans le Temple du Feu# a", /*spanish*/"#cinco baldosas de maldad# custodian una Skulltula que otorga"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_GS_BOULDER_MAZE] = HintText(CustomMessage("They say that #explosives in a maze# unveil a spider hiding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière un mur fragile du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #explosivos en un laberinto# desvelan una Skulltula que otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_GS_BOULDER_MAZE] = HintText::Exclude({ - //obscure text - Text{"#explosives in a maze# unveil a spider hiding", /*french*/"une #Skulltula derrière un mur fragile du Temple du Feu# a", /*spanish*/"los #explosivos en un laberinto# desvelan una Skulltula que otorga"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_GS_SCARECROW_TOP] = HintText(CustomMessage("They say that a #spider-friendly scarecrow# atop the Fire Temple hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula repérée par l'épouvantail du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #espantapájaros del Templo del Fuego# custodia una Skulltula que otorga #[[1]]#. + {}, { + CustomMessage("They say that a #spider-friendly scarecrow# atop a volcano hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula repérée par l'épouvantail du volcan# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #espantapájaros en lo alto de un volcán# custodia una Skulltula que otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_GS_SCARECROW_TOP] = HintText::Exclude({ - //obscure text - Text{"a #spider-friendly scarecrow# atop a volcano hides", /*french*/"une #Skulltula repérée par l'épouvantail du volcan# a", /*spanish*/"un #espantapájaros en lo alto de un volcán# custodia una Skulltula que otorga"}, - }, {}, - //clear text - Text{"a #spider-friendly scarecrow# atop the Fire Temple hides", /*french*/"une #Skulltula repérée par l'épouvantail du Temple du Feu# a", /*spanish*/"un #espantapájaros del Templo del Fuego# custodia una Skulltula que otorga"} - ); + hintTextTable[RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = HintText(CustomMessage("They say that a #spider-friendly scarecrow# atop the Fire Temple hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula repérée par l'épouvantail du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, un #espantapájaros del Templo del Fuego# custodia una Skulltula que otorga #[[1]]#. + {}, { + CustomMessage("They say that a #spider-friendly scarecrow# atop a volcano hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula repérée par l'épouvantail du volcan# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #espantapájaros en lo alto de un volcán# custodia una Skulltula que otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = HintText::Exclude({ - //obscure text - Text{"a #spider-friendly scarecrow# atop a volcano hides", /*french*/"une #Skulltula repérée par l'épouvantail du volcan# a", /*spanish*/"un #espantapájaros en lo alto de un volcán# custodia una Skulltula que otorga"}, - }, {}, - //clear text - Text{"a #spider-friendly scarecrow# atop the Fire Temple hides", /*french*/"une #Skulltula repérée par l'épouvantail du Temple du Feu# a", /*spanish*/"un #espantapájaros del Templo del Fuego# custodia una Skulltula que otorga"} - ); + hintTextTable[RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = HintText(CustomMessage("They say that a #spider above a fiery maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus du labyrinthe enflammé du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre un ardiente laberinto# otorga #[[1]]#. + hintTextTable[RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = HintText(CustomMessage("They say that a #spider within a fiery maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans le labyrinthe enflammé du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en el interior de un ardiente laberinto# otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = HintText::Exclude({ - //obscure text - Text{"a #spider above a fiery maze# holds", /*french*/"une #Skulltula au dessus du labyrinthe enflammé du Temple du Feu# a", /*spanish*/"una #Skulltula sobre un ardiente laberinto# otorga"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = HintText(CustomMessage("They say that a #Goron trapped near lava# befriended a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula emprisonnée près du lac de lave du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula amiga de un Goron atrapado junto a la lava# otorga #[[1]]#. - hintTable[RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = HintText::Exclude({ - //obscure text - Text{"a #spider within a fiery maze# holds", /*french*/"une #Skulltula dans le labyrinthe enflammé du Temple du Feu# a", /*spanish*/"una #Skulltula en el interior de un ardiente laberinto# otorga"}, - }); - - hintTable[RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = HintText::Exclude({ - //obscure text - Text{"a #Goron trapped near lava# befriended a spider with", /*french*/"une #Skulltula emprisonnée près du lac de lave du Temple du Feu# a", /*spanish*/"una #Skulltula amiga de un Goron atrapado junto a la lava# otorga"}, - }); - - hintTable[RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider beside a fiery maze# holds", /*french*/"une #Skulltula près du labyrinthe enflammé du Temple du Feu# a", /*spanish*/"una #Skulltula junto a un ardiente laberinto# otorga"}, - }); + hintTextTable[RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = HintText(CustomMessage("They say that a #spider beside a fiery maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près du labyrinthe enflammé du Temple du Feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula junto a un ardiente laberinto# otorga #[[1]]#. /*-------------------------- | WATER TEMPLE | ---------------------------*/ - hintTable[RHT_WATER_TEMPLE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#rolling spikes# in the Water Temple surround", /*french*/"des #Spikes# dans le Temple de l'Eau entourent", /*spanish*/"unas #rodantes púas# del Templo del Agua guardan"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MAP_CHEST] = HintText(CustomMessage("They say that #rolling spikes# in the Water Temple surround #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #Spikes# dans le Temple de l'Eau entourent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #rodantes púas# del Templo del Agua guardan #[[1]]#. - hintTable[RHT_WATER_TEMPLE_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#roaming stingers in the Water Temple# guard", /*french*/"des #raies dans le Temple de l'Eau# protègent", /*spanish*/"unos #errantes stingers# del Templo del Agua guardan"}, - }); + hintTextTable[RHT_WATER_TEMPLE_COMPASS_CHEST] = HintText(CustomMessage("They say that #roaming stingers in the Water Temple# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #raies dans le Temple de l'Eau# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #errantes stingers# del Templo del Agua guardan #[[1]]#. - hintTable[RHT_WATER_TEMPLE_TORCHES_CHEST] = HintText::Exclude({ - //obscure text - Text{"#fire in the Water Temple# reveals", /*french*/"des #flammes dans le Temple de l'Eau# révèlent", /*spanish*/"el #fuego en el Templo del Agua# revela"}, - }); + hintTextTable[RHT_WATER_TEMPLE_TORCHES_CHEST] = HintText(CustomMessage("They say that #fire in the Water Temple# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #flammes dans le Temple de l'Eau# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #fuego en el Templo del Agua# revela #[[1]]#. - hintTable[RHT_WATER_TEMPLE_DRAGON_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #serpent's prize# in the Water Temple is", /*french*/"la #récompense du dragon submergé# est", /*spanish*/"el #escamado premio# del Templo del Agua se trata de"}, - }); + hintTextTable[RHT_WATER_TEMPLE_DRAGON_CHEST] = HintText(CustomMessage("They say that a #serpent's prize# in the Water Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #récompense du dragon submergé# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #escamado premio# del Templo del Agua se trata de #[[1]]#. - hintTable[RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = HintText::Exclude({ - //obscure text - Text{"#blinding an eye# in the Water Temple leads to", /*french*/"#l'oeil# du Temple de l'Eau voit", /*spanish*/"#cegar un ojo# del Templo del Agua conduce a"}, - }); + hintTextTable[RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = HintText(CustomMessage("They say that #blinding an eye# in the Water Temple leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #l'oeil# du Temple de l'Eau voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cegar un ojo# del Templo del Agua conduce a #[[1]]#. - hintTable[RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = HintText::Exclude({ - //obscure text - Text{"in the #depths of the Water Temple# lies", /*french*/"le #coeur du Temple de l'Eau# cache", /*spanish*/"en las #profundidades del Templo del Agua# yace"}, - }); + hintTextTable[RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = HintText(CustomMessage("They say that in the #depths of the Water Temple# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coeur du Temple de l'Eau# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en las #profundidades del Templo del Agua# yace #[[1]]#. - hintTable[RHT_WATER_TEMPLE_CRACKED_WALL_CHEST] = HintText::Exclude({ - //obscure text - Text{"#through a crack# in the Water Temple is", /*french*/"le #mur fragile# du Temple de l'Eau cache", /*spanish*/"tras una #agrietada pared# del Templo del Agua yace"}, - }); + hintTextTable[RHT_WATER_TEMPLE_CRACKED_WALL_CHEST] = HintText(CustomMessage("They say that #through a crack# in the Water Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile# du Temple de l'Eau cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras una #agrietada pared# del Templo del Agua yace #[[1]]#. - hintTable[RHT_WATER_TEMPLE_LONGSHOT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#facing yourself# reveals", /*french*/"se #vaincre soi-même# révèle", /*spanish*/"#luchar contra ti mismo# revela"}, - Text{"a #dark reflection# of yourself guards", /*french*/"son #propre reflet# cache", /*spanish*/"el #oscuro reflejo de ti mismo# guarda"}, - }, {}, - //clear text - Text{"#Dark Link# guards", /*french*/"l'#Ombre de @# protège", /*spanish*/"#@ Oscuro# guarda"} - ); + hintTextTable[RHT_WATER_TEMPLE_LONGSHOT_CHEST] = HintText(CustomMessage("They say that #Dark Link# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#Ombre de @# protège #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #@ Oscuro# guarda #[[1]]#. + {}, { + CustomMessage("They say that #facing yourself# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, se #vaincre soi-même# révèle #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #luchar contra ti mismo# revela #[[1]]#. + CustomMessage("They say that a #dark reflection# of yourself guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, son #propre reflet# cache #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #oscuro reflejo de ti mismo# guarda #[[1]]#. + hintTextTable[RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = HintText(CustomMessage("They say that in the #depths of the Water Temple# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coeur du Temple de l'Eau# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en las #profundidades del Templo del Agua# yace #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = HintText::Exclude({ - //obscure text - Text{"in the #depths of the Water Temple# lies", /*french*/"le #coeur du Temple de l'Eau# cache", /*spanish*/"en las #profundidades del Templo del Agua# yace"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that fire in the Water Temple unlocks a #vast gate# revealing a chest with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #flammes au coeur du Temple de l'Eau# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el fuego en el Templo del Agua alza una #gran valla# con #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"fire in the Water Temple unlocks a #vast gate# revealing a chest with", /*french*/"des #flammes au coeur du Temple de l'Eau# révèlent", /*spanish*/"el fuego en el Templo del Agua alza una #gran valla# con"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = HintText(CustomMessage("They say that #through a crack# in the Water Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mur fragile# du Temple de l'Eau cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras una #agrietada pared# del Templo del Agua yace #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#through a crack# in the Water Temple is", /*french*/"le #mur fragile# du Temple de l'Eau cache", /*spanish*/"tras una #agrietada pared# del Templo del Agua yace"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that #fire in the Water Temple# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #flammes dans le Temple de l'Eau# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #fuego en el Templo del Agua# revela #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#fire in the Water Temple# reveals", /*french*/"des #flammes dans le Temple de l'Eau# révèlent", /*spanish*/"el #fuego en el Templo del Agua# revela"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that #sparring soldiers# in the Water Temple guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #soldats du Temple de l'Eau# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #acabar con unos soldados# del Templo del Agua revela #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#sparring soldiers# in the Water Temple guard", /*french*/"les #soldats du Temple de l'Eau# protègent", /*spanish*/"#acabar con unos soldados# del Templo del Agua revela"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MORPHA_HEART] = HintText(CustomMessage("They say that #Morpha# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Morpha# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Morpha# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Giant Aquatic Amoeba# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#amibe aquatique géante# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, la #ameba acuática gigante# porta #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MORPHA_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Giant Aquatic Amoeba# holds", /*french*/"l'#amibe aquatique géante# possède", /*spanish*/"la #ameba acuática gigante# porta"}, - }, {}, - //clear text - Text{"#Morpha# holds", /*french*/"#Morpha# possède", /*spanish*/"#Morpha# porta"} - ); + hintTextTable[RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = HintText(CustomMessage("They say that a #spider over a waterfall# in the Water Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'une cascade du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras una cascada# del Templo del Agua otorga #[[1]]#. - hintTable[RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider over a waterfall# in the Water Temple holds", /*french*/"une #Skulltula au dessus d'une cascade du Temple de l'Eau# a", /*spanish*/"una #Skulltula tras una cascada# del Templo del Agua otorga"}, - }); + hintTextTable[RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR] = HintText(CustomMessage("They say that a #spider in the center of the Water Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au centre du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en el centro del Templo del Agua# otorga #[[1]]#. - hintTable[RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR] = HintText::Exclude({ - //obscure text - Text{"a #spider in the center of the Water Temple# holds", /*french*/"une #Skulltula au centre du Temple de l'Eau# a", /*spanish*/"una #Skulltula en el centro del Templo del Agua# otorga"}, - }); + hintTextTable[RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a spider protected by #rolling boulders in the Water Temple# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière les rochers roulants du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, una #Skulltula protegida por rocas rodantes# del Templo del Agua otorga #[[1]]#. + {}, { + CustomMessage("They say that a spider protected by #rolling boulders under the lake# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière les rochers roulants sous le lac# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, una #Skulltula protegida por rocas rodantes# bajo el lago otorga #[[1]]#. - hintTable[RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a spider protected by #rolling boulders under the lake# hides", /*french*/"une #Skulltula derrière les rochers roulants sous le lac# a", /*spanish*/"una #Skulltula protegida por rocas rodantes# bajo el lago otorga"}, - }, {}, - //clear text - Text{"a spider protected by #rolling boulders in the Water Temple# hides", /*french*/"une #Skulltula derrière les rochers roulants du Temple de l'Eau# a", /*spanish*/"una #Skulltula protegida por rocas rodantes# del Templo del Agua otorga"} - ); + hintTextTable[RHT_WATER_TEMPLE_GS_RIVER] = HintText(CustomMessage("They say that a #spider over a river# in the Water Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus de la rivière du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre un río# del Templo del Agua otorga #[[1]]#. - hintTable[RHT_WATER_TEMPLE_GS_RIVER] = HintText::Exclude({ - //obscure text - Text{"a #spider over a river# in the Water Temple holds", /*french*/"une #Skulltula au dessus de la rivière du Temple de l'Eau# a", /*spanish*/"una #Skulltula sobre un río# del Templo del Agua otorga"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = HintText(CustomMessage("They say that #beyond a pit of lizards# is a spider holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près des lézards du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #más allá de un pozo de reptiles# una Skulltula otorga #[[1]]#. + hintTextTable[RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = HintText(CustomMessage("They say that #lizards guard a spider# in the Water Temple with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans les couloirs croisés du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #reptiles custodian una Skulltula# del Templo del Agua que otorga #[[1]]#. - hintTable[RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = HintText::Exclude({ - //obscure text - Text{"#beyond a pit of lizards# is a spider holding", /*french*/"une #Skulltula près des lézards du Temple de l'Eau# a", /*spanish*/"#más allá de un pozo de reptiles# una Skulltula otorga"}, - }); - - hintTable[RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = HintText::Exclude({ - //obscure text - Text{"#lizards guard a spider# in the Water Temple with", /*french*/"une #Skulltula dans les couloirs croisés du Temple de l'Eau# a", /*spanish*/"unos #reptiles custodian una Skulltula# del Templo del Agua que otorga"}, - }); - - hintTable[RHT_WATER_TEMPLE_MQ_GS_RIVER] = HintText::Exclude({ - //obscure text - Text{"a #spider over a river# in the Water Temple holds", /*french*/"une #Skulltula au dessus de la rivière du Temple de l'Eau# a", /*spanish*/"una #Skulltula sobre un río# del Templo del Agua otorga"}, - }); + hintTextTable[RHT_WATER_TEMPLE_MQ_GS_RIVER] = HintText(CustomMessage("They say that a #spider over a river# in the Water Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus de la rivière du Temple de l'Eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre un río# del Templo del Agua otorga #[[1]]#. /*-------------------------- | SPIRIT TEMPLE | ---------------------------*/ - hintTable[RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = HintText::Exclude({ - //obscure text - Text{"a child conquers a #skull in green fire# in the Spirit Temple to reach", /*french*/"le #crâne au halo vert dans le colosse# cache", /*spanish*/"el joven que #baje el puente# del Templo del Espíritu encontrará"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = HintText(CustomMessage("They say that a child conquers a #skull in green fire# in the Spirit Temple to reach #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #crâne au halo vert dans le colosse# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el joven que #baje el puente# del Templo del Espíritu encontrará #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = HintText::Exclude({ - //obscure text - Text{"a child can find a #caged chest# in the Spirit Temple with", /*french*/"le #coffre embarré dans le colosse# contient", /*spanish*/"un joven puede encontrar un #cofre entre rejas# del Templo del Espíritu con"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = HintText(CustomMessage("They say that a child can find a #caged chest# in the Spirit Temple with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre embarré dans le colosse# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un joven puede encontrar un #cofre entre rejas# del Templo del Espíritu con #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#across a pit of sand# in the Spirit Temple lies", /*french*/"le #trou sableux dans le colosse# a", /*spanish*/"tras un #pozo de arena# del Templo del Espíritu yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_COMPASS_CHEST] = HintText(CustomMessage("They say that #across a pit of sand# in the Spirit Temple lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trou sableux dans le colosse# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras un #pozo de arena# del Templo del Espíritu yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#dodging boulders to collect silver rupees# in the Spirit Temple yields", /*french*/"les #pièces argentées entourées de rochers dans le colosse# révèlent", /*spanish*/"#esquivar rocas y conseguir plateadas rupias# en el Templo del Espíritu conduce a"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = HintText(CustomMessage("They say that #dodging boulders to collect silver rupees# in the Spirit Temple yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pièces argentées entourées de rochers dans le colosse# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #esquivar rocas y conseguir plateadas rupias# en el Templo del Espíritu conduce a #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #shadow circling reflected light# in the Spirit Temple guards", /*french*/"l'#ombre près d'un miroir# protège", /*spanish*/"un #círculo de reflectante luz# del Templo del Espíritu guarda"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = HintText(CustomMessage("They say that a #shadow circling reflected light# in the Spirit Temple guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#ombre près d'un miroir# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #círculo de reflectante luz# del Templo del Espíritu guarda #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #shadow circling reflected light# in the Spirit Temple guards", /*french*/"l'#ombre près d'un miroir# protège", /*spanish*/"un #círculo de reflectante luz# del Templo del Espíritu guarda"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = HintText(CustomMessage("They say that a #shadow circling reflected light# in the Spirit Temple guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#ombre près d'un miroir# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #círculo de reflectante luz# del Templo del Espíritu guarda #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#before a giant statue# in the Spirit Temple lies", /*french*/"#devant la statue# dans le colosse gît", /*spanish*/"#ante una gran estatua# del Templo del Espíritu aguarda"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MAP_CHEST] = HintText(CustomMessage("They say that #before a giant statue# in the Spirit Temple lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #devant la statue# dans le colosse gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #ante una gran estatua# del Templo del Espíritu aguarda #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#lizards in the Spirit Temple# guard", /*french*/"les #lézards dans le colosse# protègent", /*spanish*/"los #reptiles del Templo del Espíritu# guardan"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = HintText(CustomMessage("They say that #lizards in the Spirit Temple# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #lézards dans le colosse# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #reptiles del Templo del Espíritu# guardan #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = HintText::Exclude({ - //obscure text - Text{"#lizards in the Spirit Temple# guard", /*french*/"les #lézards dans le colosse# protègent", /*spanish*/"los #reptiles del Templo del Espíritu# guardan"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = HintText(CustomMessage("They say that #lizards in the Spirit Temple# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #lézards dans le colosse# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #reptiles del Templo del Espíritu# guardan #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#torchlight among Beamos# in the Spirit Temple reveals", /*french*/"les #torches autour des Sentinelles# éclairent", /*spanish*/"las #antorchas junto a Beamos# del Templo del Espíritu revelan"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = HintText(CustomMessage("They say that #torchlight among Beamos# in the Spirit Temple reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #torches autour des Sentinelles# éclairent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #antorchas junto a Beamos# del Templo del Espíritu revelan #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #statue in the Spirit Temple# holds", /*french*/"la #statue dans le colosse# tient", /*spanish*/"una #estatua del Templo del Espíritu# esconde"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = HintText(CustomMessage("They say that a #statue in the Spirit Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #statue dans le colosse# tient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #estatua del Templo del Espíritu# esconde #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = HintText::Exclude({ - //obscure text - Text{"on a #ledge by a statue# in the Spirit Temple rests", /*french*/"#haut perché près de la statue# dans le colosse gît", /*spanish*/"al #borde de una estatua# del Templo del Espíritu yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = HintText(CustomMessage("They say that on a #ledge by a statue# in the Spirit Temple rests #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #haut perché près de la statue# dans le colosse gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al #borde de una estatua# del Templo del Espíritu yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"those who #show the light among statues# in the Spirit Temple find", /*french*/"le #soleil près des statues# cache", /*spanish*/"aquellos que #iluminen ante las estatuas# del Templo del Espíritu encontrarán"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = HintText(CustomMessage("They say that those who #show the light among statues# in the Spirit Temple find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil près des statues# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, aquellos que #iluminen ante las estatuas# del Templo del Espíritu encontrarán #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth in the Spirit Temple# reveals", /*french*/"le #trésor invisible près du Hache-Viande# contient", /*spanish*/"el #Ojo de la Verdad# en el Templo del Espíritu revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth in the Spirit Temple# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor invisible près du Hache-Viande# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# en el Templo del Espíritu revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth in the Spirit Temple# reveals", /*french*/"le #trésor invisible près du Hache-Viande# contient", /*spanish*/"el #Ojo de la Verdad# en el Templo del Espíritu revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth in the Spirit Temple# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor invisible près du Hache-Viande# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# en el Templo del Espíritu revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest engulfed in flame# in the Spirit Temple holds", /*french*/"le #coffre enflammé dans le colosse# contient", /*spanish*/"un #cofre rodeado de llamas# del Templo del Espíritu contiene"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a #chest engulfed in flame# in the Spirit Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre enflammé dans le colosse# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre rodeado de llamas# del Templo del Espíritu contiene #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_TOPMOST_CHEST] = HintText::Exclude({ - //obscure text - Text{"those who #show the light above the Colossus# find", /*french*/"le #soleil au sommet du colosse# révèle", /*spanish*/"aquellos que #iluminen en lo alto del Coloso# encontrarán"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_TOPMOST_CHEST] = HintText(CustomMessage("They say that those who #show the light above the Colossus# find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil au sommet du colosse# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, aquellos que #iluminen en lo alto del Coloso# encontrarán #[[1]]#. + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = HintText(CustomMessage("They say that #lying unguarded# in the Spirit Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans #l'entrée du colosse# se trouve #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en la #entrada del Templo del Espíritu# yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#lying unguarded# in the Spirit Temple is", /*french*/"dans #l'entrée du colosse# se trouve", /*spanish*/"en la #entrada del Templo del Espíritu# yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = HintText(CustomMessage("They say that a #switch in a pillar# within the Spirit Temple drops #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#interrupteur dans un pilier# du colosse cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #interruptor de un pilar# del Templo del Espíritu revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #switch in a pillar# within the Spirit Temple drops", /*french*/"l'#interrupteur dans un pilier# du colosse cache", /*spanish*/"el #interruptor de un pilar# del Templo del Espíritu revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = HintText(CustomMessage("They say that #collecting rupees through a water jet# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pièces argentées dans le jet d'eau# du colosse révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #hacerte con rupias tras un géiser# revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#collecting rupees through a water jet# reveals", /*french*/"les #pièces argentées dans le jet d'eau# du colosse révèlent", /*spanish*/"#hacerte con rupias tras un géiser# revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = HintText(CustomMessage("They say that an #eye blinded by stone# within the Spirit Temple conceals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #l'oeil derrière le rocher# dans le colosse voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cegar a un ojo# del Templo del Espíritu revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #eye blinded by stone# within the Spirit Temple conceals", /*french*/"#l'oeil derrière le rocher# dans le colosse voit", /*spanish*/"#cegar a un ojo# del Templo del Espíritu revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that surrounded by #fire and wrappings# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, près des #pierres tombales dans le colosse# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, rodeado de #fuego y vendas# yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"surrounded by #fire and wrappings# lies", /*french*/"près des #pierres tombales dans le colosse# gît", /*spanish*/"rodeado de #fuego y vendas# yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = HintText(CustomMessage("They say that a child defeats a #gauntlet of monsters# within the Spirit Temple to find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'enfant qui vainc #plusieurs monstres# dans le colosse trouvera #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el joven que derrote #unos monstruos# del Templo del Espíritu encontrará #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a child defeats a #gauntlet of monsters# within the Spirit Temple to find", /*french*/"l'enfant qui vainc #plusieurs monstres# dans le colosse trouvera", /*spanish*/"el joven que derrote #unos monstruos# del Templo del Espíritu encontrará"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = HintText(CustomMessage("They say that #explosive sunlight# within the Spirit Temple uncovers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #rayon de lumière explosif dans le colosse# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #explosiva luz solar# del Templo del Espíritu revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#explosive sunlight# within the Spirit Temple uncovers", /*french*/"le #rayon de lumière explosif dans le colosse# révèle", /*spanish*/"una #explosiva luz solar# del Templo del Espíritu revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = HintText(CustomMessage("They say that #trapped by falling enemies# within the Spirit Temple is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #ennemis tombants# dans le colosse protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #rodeado de enemigos del cielo# del Templo del Espíritu yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#trapped by falling enemies# within the Spirit Temple is", /*french*/"des #ennemis tombants# dans le colosse protègent", /*spanish*/"#rodeado de enemigos del cielo# del Templo del Espíritu yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that #blinding the colossus# unveils #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #l'oeil dans le colosse# voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cegar al coloso# revela #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#blinding the colossus# unveils", /*french*/"#l'oeil dans le colosse# voit", /*spanish*/"#cegar al coloso# revela"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = HintText(CustomMessage("They say that a #royal melody awakens the colossus# to reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie royale éveille le colosse# et révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #melodía real que despierte al coloso# revelará #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #royal melody awakens the colossus# to reveal", /*french*/"la #mélodie royale éveille le colosse# et révèle", /*spanish*/"la #melodía real que despierte al coloso# revelará"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth# finds the colossus's hidden #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #l'oeil de vérité# verra dans le colosse #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# en el Templo del Espíritu encontrará #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth# finds the colossus's hidden", /*french*/"#l'oeil de vérité# verra dans le colosse", /*spanish*/"el #Ojo de la Verdad# en el Templo del Espíritu encontrará"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = HintText(CustomMessage("They say that #the old hide what the young find# to reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil dans le trou du bloc argent# dans le colosse voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #adulto esconde lo que el joven anhela#, revelando #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#the old hide what the young find# to reveal", /*french*/"l'#oeil dans le trou du bloc argent# dans le colosse voit", /*spanish*/"el #adulto esconde lo que el joven anhela#, revelando"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = HintText(CustomMessage("They say that #sunlight in a maze of fire# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #la lumière dans le labyrinthe de feu# du colosse révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #luz solar de un ígneo laberinto# esconde #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#sunlight in a maze of fire# hides", /*french*/"#la lumière dans le labyrinthe de feu# du colosse révèle", /*spanish*/"la #luz solar de un ígneo laberinto# esconde"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = HintText(CustomMessage("They say that #across a pit of sand# in the Spirit Temple lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trou sableux# dans le colosse a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #a través del pozo de arena# del Templo del Espíritu yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"#across a pit of sand# in the Spirit Temple lies", /*french*/"le #trou sableux# dans le colosse a", /*spanish*/"#a través del pozo de arena# del Templo del Espíritu yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = HintText(CustomMessage("They say that where #temporal stone blocks the path# within the Spirit Temple lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pierres temporelles# dans le colosse cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, donde los #bloques temporales bloquean# en el Templo del Espíritu yace #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"where #temporal stone blocks the path# within the Spirit Temple lies", /*french*/"les #pierres temporelles# dans le colosse cachent", /*spanish*/"donde los #bloques temporales bloquean# en el Templo del Espíritu yace"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = HintText(CustomMessage("They say that a #chest of double purpose# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre à usage double# du colosse contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre de doble uso# contiene #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #chest of double purpose# holds", /*french*/"le #coffre à usage double# du colosse contient", /*spanish*/"un #cofre de doble uso# contiene"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that a #temporal stone blocks the light# leading to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pierre temporelle# le colosse fait ombre sur #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #bloque temporal bloquea la luz# que conduce a #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #temporal stone blocks the light# leading to", /*french*/"la #pierre temporelle# le colosse fait ombre sur", /*spanish*/"un #bloque temporal bloquea la luz# que conduce a"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = HintText(CustomMessage("They say that those who #show the light above the Colossus# find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le trésor invisible #au sommet du colosse# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, aquellos que #revelen la luz sobre el Coloso# encontrarán #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"those who #show the light above the Colossus# find", /*french*/"le trésor invisible #au sommet du colosse# contient", /*spanish*/"aquellos que #revelen la luz sobre el Coloso# encontrarán"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_TWINROVA_HEART] = HintText(CustomMessage("They say that #Twinrova# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Twinrova# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Birova# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Sorceress Sisters# hold #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les sorcières jumelles# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, las #hermanas hechiceras# portan #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_TWINROVA_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Sorceress Sisters# hold", /*french*/"#les sorcières jumelles# possède", /*spanish*/"las #hermanas hechiceras# portan"}, - }, {}, - //clear text - Text{"#Twinrova# holds", /*french*/"#Twinrova# possède", /*spanish*/"#Birova# porta"} - ); + hintTextTable[RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = HintText(CustomMessage("They say that a spider in the #hall of a knight# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'un escalier du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en el salón de un guerrero# otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = HintText::Exclude({ - //obscure text - Text{"a spider in the #hall of a knight# guards", /*french*/"une #Skulltula au dessus d'un escalier du Temple de l'Esprit# a", /*spanish*/"una #Skulltula en el salón de un guerrero# otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = HintText(CustomMessage("They say that a #spider behind a temporal stone# in the Spirit Temple yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une pierre temporelle du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras un bloque temporal# del Templo del Espíritu otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider behind a temporal stone# in the Spirit Temple yields", /*french*/"une #Skulltula derrière une pierre temporelle du Temple de l'Esprit# a", /*spanish*/"una #Skulltula tras un bloque temporal# del Templo del Espíritu otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_GS_LOBBY] = HintText(CustomMessage("They say that a #spider beside a statue# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans la grande salle du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula junto a una estatua# del Templo del Espíritu otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_GS_LOBBY] = HintText::Exclude({ - //obscure text - Text{"a #spider beside a statue# holds", /*french*/"une #Skulltula dans la grande salle du Temple de l'Esprit# a", /*spanish*/"una #Skulltula junto a una estatua# del Templo del Espíritu otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = HintText(CustomMessage("They say that a #spider at the top of a deep shaft# in the Spirit Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près d'un mur d'escalade du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en lo alto de un gran hueco# del Templo del Espíritu otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider at the top of a deep shaft# in the Spirit Temple holds", /*french*/"une #Skulltula près d'un mur d'escalade du Temple de l'Esprit# a", /*spanish*/"una #Skulltula en lo alto de un gran hueco# del Templo del Espíritu otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_GS_METAL_FENCE] = HintText(CustomMessage("They say that a child defeats a #spider among bats# in the Spirit Temple to gain #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur le grillage du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el joven que derrote la #Skulltula entre murciélagos# del Templo del Espíritu hallará #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_GS_METAL_FENCE] = HintText::Exclude({ - //obscure text - Text{"a child defeats a #spider among bats# in the Spirit Temple to gain", /*french*/"une #Skulltula sur le grillage du Temple de l'Esprit# a", /*spanish*/"el joven que derrote la #Skulltula entre murciélagos# del Templo del Espíritu hallará"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = HintText(CustomMessage("They say that #above a pit of sand# in the Spirit Temple hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus du trou sableux du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre un pozo de arena# del Templo del Espíritu otorga #[[1]]#. + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = HintText(CustomMessage("They say that a spider in the #hall of a knight# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans la salle aux neuf trônes du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en el salón de un guerrero# otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = HintText::Exclude({ - //obscure text - Text{"#above a pit of sand# in the Spirit Temple hides", /*french*/"une #Skulltula au dessus du trou sableux du Temple de l'Esprit# a", /*spanish*/"una #Skulltula sobre un pozo de arena# del Templo del Espíritu otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = HintText(CustomMessage("They say that a spider in the #hall of a knight# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans la salle aux neuf trônes du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula en el salón de un guerrero# otorga #[[1]]#. - hintTable[RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = HintText::Exclude({ - //obscure text - Text{"a spider in the #hall of a knight# guards", /*french*/"une #Skulltula dans la salle aux neuf trônes du Temple de l'Esprit# a", /*spanish*/"una #Skulltula en el salón de un guerrero# otorga"}, - }); - - hintTable[RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = HintText::Exclude({ - //obscure text - Text{"a spider in the #hall of a knight# guards", /*french*/"une #Skulltula dans la salle aux neuf trônes du Temple de l'Esprit# a", /*spanish*/"una #Skulltula en el salón de un guerrero# otorga"}, - }); - - hintTable[RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = HintText::Exclude({ - //obscure text - Text{"#upon a web of glass# in the Spirit Temple sits a spider holding", /*french*/"une #Skulltula sur une paroi de verre du Temple de l'Esprit# a", /*spanish*/"#sobre una plataforma de cristal# yace una Skulltula que otorga"}, - }); + hintTextTable[RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = HintText(CustomMessage("They say that #upon a web of glass# in the Spirit Temple sits a spider holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une paroi de verre du Temple de l'Esprit# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #sobre una plataforma de cristal# yace una Skulltula que otorga #[[1]]#. /*-------------------------- | SHADOW TEMPLE | ---------------------------*/ - hintTable[RHT_SHADOW_TEMPLE_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth# pierces a hall of faces to reveal", /*french*/"l'#oeil de vérité# voit dans les couloirs du Temple de l'Ombre", /*spanish*/"el #Ojo de la Verdad# descubrirá un pasillo de facetas con"}, - }); +hintTextTable[RHT_SHADOW_TEMPLE_MAP_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth# pierces a hall of faces to reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil de vérité# voit dans les couloirs du Temple de l'Ombre #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# descubrirá un pasillo de facetas con #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #nether dweller in the Shadow Temple# holds", /*french*/"le #spectre du Temple de l'Ombre# a", /*spanish*/"un #temido morador del Templo de las Sombras# guarda"}, - }, {}, - //clear text - Text{"#Dead Hand in the Shadow Temple# holds", /*french*/"le #Poigneur dans le Temple de l'Ombre# cache", /*spanish*/"la #Mano Muerta del Templo de las Sombras# guarda"} - ); + hintTextTable[RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = HintText(CustomMessage("They say that #Dead Hand in the Shadow Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Poigneur dans le Temple de l'Ombre# cache #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #Mano Muerta del Templo de las Sombras# guarda #[[1]]#. + {}, { + CustomMessage("They say that a #nether dweller in the Shadow Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #spectre du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #temido morador del Templo de las Sombras# guarda #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies revealed by the Eye of Truth# guard", /*french*/"les #Gibdos dans les couloirs# du Temple de l'Ombre protègent", /*spanish*/"las #momias reveladas por el Ojo de la Verdad# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_COMPASS_CHEST] = HintText(CustomMessage("They say that #mummies revealed by the Eye of Truth# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos dans les couloirs# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias reveladas por el Ojo de la Verdad# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#spinning scythes# protect", /*french*/"les #faucheurs danseurs# du Temple de l'Ombre protègent", /*spanish*/"las #giratorias guadañas# protegen"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = HintText(CustomMessage("They say that #spinning scythes# protect #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs danseurs# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #giratorias guadañas# protegen #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#invisible blades# guard", /*french*/"les #faucheurs invisibles# du Temple de l'Ombre protègent", /*spanish*/"las #hojas invisibles# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = HintText(CustomMessage("They say that #invisible blades# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs invisibles# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #hojas invisibles# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#invisible blades# guard", /*french*/"les #faucheurs invisibles# du Temple de l'Ombre protègent", /*spanish*/"las #hojas invisibles# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = HintText(CustomMessage("They say that #invisible blades# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs invisibles# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #hojas invisibles# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #dead roam among invisible spikes# guarding", /*french*/"#parmi les clous invisibles# du Temple de l'Ombre se cache", /*spanish*/"los #muertos que vagan por pinchos invisibles# protegen"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = HintText(CustomMessage("They say that the #dead roam among invisible spikes# guarding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parmi les clous invisibles# du Temple de l'Ombre se cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #muertos que vagan por pinchos invisibles# protegen #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_WIND_HINT_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #invisible chest guarded by the dead# holds", /*french*/"le #trésor invisible du cul-de-sac# du Temple de l'Ombre contient", /*spanish*/"un #cofre invisible custodiado por los del más allá# contiene"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_WIND_HINT_CHEST] = HintText(CustomMessage("They say that an #invisible chest guarded by the dead# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor invisible du cul-de-sac# du Temple de l'Ombre contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre invisible custodiado por los del más allá# contiene #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies guarding a ferry# hide", /*french*/"les #Gibdos qui bloquent le traversier# cachent", /*spanish*/"las #momias que protegen un navío# esconden"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = HintText(CustomMessage("They say that #mummies guarding a ferry# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos qui bloquent le traversier# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias que protegen un navío# esconden #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies guarding a ferry# hide", /*french*/"les #Gibdos qui bloquent le traversier# cachent", /*spanish*/"las #momias que protegen un navío# esconden"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = HintText(CustomMessage("They say that #mummies guarding a ferry# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos qui bloquent le traversier# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias que protegen un navío# esconden #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#walls consumed by a ball of fire# reveal", /*french*/"le #piège de bois# du Temple de l'Ombre cache", /*spanish*/"las #paredes consumidas por una esfera ígnea# revelan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = HintText(CustomMessage("They say that #walls consumed by a ball of fire# reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #piège de bois# du Temple de l'Ombre cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes consumidas por una esfera ígnea# revelan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#walls consumed by a ball of fire# reveal", /*french*/"le #piège de bois# du Temple de l'Ombre cache", /*spanish*/"las #paredes consumidas por una esfera ígnea# revelan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that #walls consumed by a ball of fire# reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #piège de bois# du Temple de l'Ombre cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes consumidas por una esfera ígnea# revelan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"#inside a burning skull# lies", /*french*/"#dans un crâne enflammé# gît", /*spanish*/"en el #interior de una calavera en llamas# aguarda"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_FREESTANDING_KEY] = HintText(CustomMessage("They say that #inside a burning skull# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans un crâne enflammé# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en el #interior de una calavera en llamas# aguarda #[[1]]#. + hintTextTable[RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth# pierces a hall of faces to reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil de vérité# voit dans les couloirs du Temple de l'Ombre #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# descubre un pasillo de facetas con #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth# pierces a hall of faces to reveal", /*french*/"l'#oeil de vérité# voit dans les couloirs du Temple de l'Ombre", /*spanish*/"el #Ojo de la Verdad# descubre un pasillo de facetas con"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = HintText(CustomMessage("They say that #Dead Hand in the Shadow Temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Poigneur dans le Temple de l'Ombre# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #Mano Muerta del Templo de las Sombras# guarda #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Dead Hand in the Shadow Temple# holds", /*french*/"le #Poigneur dans le Temple de l'Ombre# cache", /*spanish*/"la #Mano Muerta del Templo de las Sombras# guarda"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = HintText(CustomMessage("They say that #mummies revealed by the Eye of Truth# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos dans les couloirs# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias reveladas por el Ojo de la Verdad# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies revealed by the Eye of Truth# guard", /*french*/"les #Gibdos dans les couloirs# du Temple de l'Ombre protègent", /*spanish*/"las #momias reveladas por el Ojo de la Verdad# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_MAP_CHEST] = HintText(CustomMessage("They say that #spinning scythes# protect #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs danseurs# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #giratorias guadañas# protegen #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#spinning scythes# protect", /*french*/"les #faucheurs danseurs# du Temple de l'Ombre protègent", /*spanish*/"las #giratorias guadañas# protegen"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = HintText(CustomMessage("They say that #collecting rupees in a vast cavern# with the Shadow Temple unveils #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pièces argentées dans le Temple de l'Ombre# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, hacerte con las #rupias en una gran caverna# del Templo de las Sombras revela #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = HintText::Exclude({ - //obscure text - Text{"#collecting rupees in a vast cavern# with the Shadow Temple unveils", /*french*/"les #pièces argentées dans le Temple de l'Ombre# révèlent", /*spanish*/"hacerte con las #rupias en una gran caverna# del Templo de las Sombras revela"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = HintText(CustomMessage("They say that #falling spikes# block the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #pluie de clous# surplombe #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #pinchos de un techo# conducen a #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = HintText::Exclude({ - //obscure text - Text{"#falling spikes# block the path to", /*french*/"la #pluie de clous# surplombe", /*spanish*/"los #pinchos de un techo# conducen a"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = HintText(CustomMessage("They say that the #dead roam among invisible spikes# guarding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parmi les clous invisibles# du Temple de l'Ombre se cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #muertos que vagan por pinchos invisibles# protegen #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #dead roam among invisible spikes# guarding", /*french*/"#parmi les clous invisibles# du Temple de l'Ombre se cache", /*spanish*/"los #muertos que vagan por pinchos invisibles# protegen"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that #walls consumed by a ball of fire# reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #piège de bois# du Temple de l'Ombre cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes consumidas por una esfera ígnea# revelan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#walls consumed by a ball of fire# reveal", /*french*/"le #piège de bois# du Temple de l'Ombre cache", /*spanish*/"las #paredes consumidas por una esfera ígnea# revelan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = HintText(CustomMessage("They say that #walls consumed by a ball of fire# reveal #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #piège de bois# du Temple de l'Ombre cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #paredes consumidas por una esfera ígnea# revelan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#walls consumed by a ball of fire# reveal", /*french*/"le #piège de bois# du Temple de l'Ombre cache", /*spanish*/"las #paredes consumidas por una esfera ígnea# revelan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = HintText(CustomMessage("They say that near an #empty pedestal# within the Shadow Temple lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #près d'un pédestal vide du Temple de l'Ombre# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, cerca de un #vacío pedestal# del Templo de las Sombras yace #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = HintText::Exclude({ - //obscure text - Text{"near an #empty pedestal# within the Shadow Temple lies", /*french*/"#près d'un pédestal vide du Temple de l'Ombre# gît", /*spanish*/"cerca de un #vacío pedestal# del Templo de las Sombras yace"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = HintText(CustomMessage("They say that #invisible blades# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs invisibles# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #hojas invisibles# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#invisible blades# guard", /*french*/"les #faucheurs invisibles# du Temple de l'Ombre protègent", /*spanish*/"unas #hojas invisibles# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = HintText(CustomMessage("They say that #invisible blades# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #faucheurs invisibles# du Temple de l'Ombre protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #hojas invisibles# guardan #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#invisible blades# guard", /*french*/"les #faucheurs invisibles# du Temple de l'Ombre protègent", /*spanish*/"unas #hojas invisibles# guardan"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = HintText(CustomMessage("They say that an #invisible chest guarded by the dead# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor invisible du cul-de-sac# du Temple de l'Ombre contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #cofre invisible custodiado por los del más allá# contiene #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #invisible chest guarded by the dead# holds", /*french*/"le #trésor invisible du cul-de-sac# du Temple de l'Ombre contient", /*spanish*/"un #cofre invisible custodiado por los del más allá# contiene"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = HintText(CustomMessage("They say that #mummies guarding a ferry# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos qui bloquent le traversier# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias que protegen un navío# esconden #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies guarding a ferry# hide", /*french*/"les #Gibdos qui bloquent le traversier# cachent", /*spanish*/"las #momias que protegen un navío# esconden"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = HintText(CustomMessage("They say that #mummies guarding a ferry# hide #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #Gibdos qui bloquent le traversier# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #momias que protegen un navío# esconden #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#mummies guarding a ferry# hide", /*french*/"les #Gibdos qui bloquent le traversier# cachent", /*spanish*/"las #momias que protegen un navío# esconden"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = HintText(CustomMessage("They say that #caged near a ship# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans une cage près du traversier# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #entre rejas al lado de un navío# yace #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#caged near a ship# lies", /*french*/"#dans une cage près du traversier# gît", /*spanish*/"#entre rejas al lado de un navío# yace"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = HintText(CustomMessage("They say that #behind three burning skulls# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière trois crânes enflammés# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras #tres ardientes calaveras# yace #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"#behind three burning skulls# lies", /*french*/"#derrière trois crânes enflammés# gît", /*spanish*/"tras #tres ardientes calaveras# yace"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART] = HintText(CustomMessage("They say that #Bongo Bongo# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Bongo Bongo# possède #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #Bongo Bongo# porta #[[1]]#. + {}, { + CustomMessage("They say that the #Phantom Shadow Beast# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #monstre de l'ombre# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, la #alimaña oscura espectral# porta #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART] = HintText::Exclude({ - //obscure text - Text{"the #Phantom Shadow Beast# holds", /*french*/"le #monstre de l'ombre# possède", /*spanish*/"la #alimaña oscura espectral# porta"}, - }, {}, - //clear text - Text{"#Bongo Bongo# holds", /*french*/"#Bongo Bongo# possède", /*spanish*/"#Bongo Bongo# porta"} - ); + hintTextTable[RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = HintText(CustomMessage("They say that #beyond a burning skull# lies a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière un crâne enflammé du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #tras una ardiente calavera# yace una Skulltula que otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = HintText::Exclude({ - //obscure text - Text{"#beyond a burning skull# lies a spider with", /*french*/"une #Skulltula derrière un crâne enflammé du Temple de l'Ombre# a", /*spanish*/"#tras una ardiente calavera# yace una Skulltula que otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = HintText(CustomMessage("They say that a #spider beyond falling spikes# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au delà de la pluie de clous du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras los pinchos del techo# otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider beyond falling spikes# holds", /*french*/"une #Skulltula au delà de la pluie de clous du Temple de l'Ombre# a", /*spanish*/"una #Skulltula tras los pinchos del techo# otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = HintText(CustomMessage("They say that #beyond three burning skulls# lies a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière trois crânes enflammés du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #tras tres ardientes calaveras# yace una Skulltula que otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = HintText::Exclude({ - //obscure text - Text{"#beyond three burning skulls# lies a spider with", /*french*/"une #Skulltula derrière trois crânes enflammés du Temple de l'Ombre# a", /*spanish*/"#tras tres ardientes calaveras# yace una Skulltula que otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = HintText(CustomMessage("They say that a spider guarded by #invisible blades# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par les faucheurs invisibles du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula custodiada por hojas invisibles# otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = HintText::Exclude({ - //obscure text - Text{"a spider guarded by #invisible blades# holds", /*french*/"une #Skulltula protégée par les faucheurs invisibles du Temple de l'Ombre# a", /*spanish*/"una #Skulltula custodiada por hojas invisibles# otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_GS_NEAR_SHIP] = HintText(CustomMessage("They say that a spider near a #docked ship# hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près du traversier du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula cercana a un navío# otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_GS_NEAR_SHIP] = HintText::Exclude({ - //obscure text - Text{"a spider near a #docked ship# hoards", /*french*/"une #Skulltula près du traversier du Temple de l'Ombre# a", /*spanish*/"una #Skulltula cercana a un navío# otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = HintText(CustomMessage("They say that a #spider beyond falling spikes# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au delà de la pluie de clous du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras los pinchos del techo# otorga #[[1]]#. + hintTextTable[RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = HintText(CustomMessage("They say that a #spider amidst roaring winds# in the Shadow Temple holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près des vents du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula entre ventarrones# del Templo de las Sombras otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider beyond falling spikes# holds", /*french*/"une #Skulltula au delà de la pluie de clous du Temple de l'Ombre# a", /*spanish*/"una #Skulltula tras los pinchos del techo# otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = HintText(CustomMessage("They say that a #spider beneath gruesome debris# in the Shadow Temple hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sous des débris du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo unos horripilantes escombros# del Templo de las Sombras otorga #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider amidst roaring winds# in the Shadow Temple holds", /*french*/"une #Skulltula près des vents du Temple de l'Ombre# a", /*spanish*/"una #Skulltula entre ventarrones# del Templo de las Sombras otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = HintText(CustomMessage("They say that a #fallen statue# reveals a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près de la statue écroulée du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #estatua caída# revelará una Skulltula que otorgue #[[1]]#. - hintTable[RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = HintText::Exclude({ - //obscure text - Text{"a #spider beneath gruesome debris# in the Shadow Temple hides", /*french*/"une #Skulltula sous des débris du Temple de l'Ombre# a", /*spanish*/"una #Skulltula bajo unos horripilantes escombros# del Templo de las Sombras otorga"}, - }); - - hintTable[RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = HintText::Exclude({ - //obscure text - Text{"a #fallen statue# reveals a spider with", /*french*/"une #Skulltula près de la statue écroulée du Temple de l'Ombre# a", /*spanish*/"una #estatua caída# revelará una Skulltula que otorgue"}, - }); - - hintTable[RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = HintText::Exclude({ - //obscure text - Text{"a #suspended spider# guards", /*french*/"une #Skulltula près du repère du Temple de l'Ombre# a", /*spanish*/"una #Skulltula flotante# del Templo de las Sombras otorga"}, - }); + hintTextTable[RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = HintText(CustomMessage("They say that a #suspended spider# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près du repère du Temple de l'Ombre# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula flotante# del Templo de las Sombras otorga #[[1]]#. /*-------------------------- | BOTTOM OF THE WELL | ---------------------------*/ - hintTable[RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth in the well# reveals", /*french*/"l'#oeil de vérité dans le Puits# révèle", /*spanish*/"el #Ojo de la Verdad en el pozo# revela"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth in the well# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil de vérité dans le Puits# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad en el pozo# revela #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#gruesome debris# in the well hides", /*french*/"des #débris dans le Puits# cachent", /*spanish*/"unos #horripilantes escombros# del pozo esconden"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = HintText(CustomMessage("They say that #gruesome debris# in the well hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #débris dans le Puits# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #horripilantes escombros# del pozo esconden #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth in the well# reveals", /*french*/"l'#oeil de vérité dans le Puits# révèle", /*spanish*/"el #Ojo de la Verdad en el pozo# revela"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth in the well# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#oeil de vérité dans le Puits# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad en el pozo# revela #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hidden entrance to a cage# in the well leads to", /*french*/"dans un #chemin caché dans le Puits# gît", /*spanish*/"la #entrada oculta de una celda# del pozo conduce a"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = HintText(CustomMessage("They say that a #hidden entrance to a cage# in the well leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans un #chemin caché dans le Puits# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #entrada oculta de una celda# del pozo conduce a #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #spider guarding a cage# in the well protects", /*french*/"l'#araignée dans la cage du Puits# protège", /*spanish*/"una #araña protegiendo una celda# del pozo guarda"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = HintText(CustomMessage("They say that a #spider guarding a cage# in the well protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#araignée dans la cage du Puits# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #araña protegiendo una celda# del pozo guarda #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#gruesome debris# in the well hides", /*french*/"des #débris dans le Puits# cachent", /*spanish*/"unos #horripilantes escombros# del pozo esconden"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = HintText(CustomMessage("They say that #gruesome debris# in the well hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des #débris dans le Puits# cachent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #horripilantes escombros# del pozo esconden #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#Dead Hand's invisible secret# is", /*french*/"le #trésor invisible du Poigneur# est", /*spanish*/"el #secreto invisible de la Mano Muerta# esconde"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = HintText(CustomMessage("They say that #Dead Hand's invisible secret# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor invisible du Poigneur# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #secreto invisible de la Mano Muerta# esconde #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #royal melody in the well# uncovers", /*french*/"la #mélodie royale révèle dans le Puits#", /*spanish*/"una #melodía real en el pozo# revela"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = HintText(CustomMessage("They say that a #royal melody in the well# uncovers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie royale révèle dans le Puits# #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #melodía real en el pozo# revela #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #royal melody in the well# uncovers", /*french*/"la #mélodie royale révèle dans le Puits#", /*spanish*/"una #melodía real en el pozo# revela"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = HintText(CustomMessage("They say that a #royal melody in the well# uncovers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie royale révèle dans le Puits# #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #melodía real en el pozo# revela #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"in the #depths of the well# lies", /*french*/"#dans le coeur du Puits# gît", /*spanish*/"en las #profundidades del pozo# yace"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MAP_CHEST] = HintText(CustomMessage("They say that in the #depths of the well# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans le coeur du Puits# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en las #profundidades del pozo# yace #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#perilous pits# in the well guard the path to", /*french*/"#trois trous# dans le Puits protègent", /*spanish*/"#peligrosos fosos# del pozo conducen a"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = HintText(CustomMessage("They say that #perilous pits# in the well guard the path to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #trois trous# dans le Puits protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #peligrosos fosos# del pozo conducen a #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#locked in a cage# in the well lies", /*french*/"#dans une cage# du Puits gît", /*spanish*/"#entre rejas# en el pozo yace"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = HintText(CustomMessage("They say that #locked in a cage# in the well lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans une cage# du Puits gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #entre rejas# en el pozo yace #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"#inside a coffin# hides", /*french*/"dans #un cercueil# gît", /*spanish*/"en el #interior de un ataúd# yace"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = HintText(CustomMessage("They say that #inside a coffin# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans #un cercueil# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en el #interior de un ataúd# yace #[[1]]#. + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = HintText(CustomMessage("They say that a #royal melody in the well# uncovers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #mélodie royale révèle dans le Puits# #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #melodía real en el pozo# revela #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #royal melody in the well# uncovers", /*french*/"la #mélodie royale révèle dans le Puits#", /*spanish*/"una #melodía real en el pozo# revela"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = HintText(CustomMessage("They say that an #army of the dead# in the well guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#armée des morts# dans le Puits protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #ejército del más allá# del pozo guarda #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #army of the dead# in the well guards", /*french*/"l'#armée des morts# dans le Puits protège", /*spanish*/"un #ejército del más allá# del pozo guarda"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = HintText(CustomMessage("They say that #Dead Hand's explosive secret# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #secret explosif du Poigneur# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #explosivo secreto de la Mano Muerta# esconde #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"#Dead Hand's explosive secret# is", /*french*/"le #secret explosif du Poigneur# est", /*spanish*/"el #explosivo secreto de la Mano Muerta# esconde"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = HintText(CustomMessage("They say that an #invisible path in the well# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans un #chemin caché dans le Puits# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #camino invisible del pozo# conduce a #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"an #invisible path in the well# leads to", /*french*/"dans un #chemin caché dans le Puits# gît", /*spanish*/"un #camino invisible del pozo# conduce a"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = HintText(CustomMessage("They say that a #spider locked in a cage# in the well holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une cage au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enjaulada# del pozo otorga #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = HintText::Exclude({ - //obscure text - Text{"a #spider locked in a cage# in the well holds", /*french*/"une #Skulltula dans une cage au fonds du Puits# a", /*spanish*/"una #Skulltula enjaulada# del pozo otorga"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = HintText(CustomMessage("They say that an #invisible path in the well# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans le chemin invisible au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #camino invisible del pozo# conduce a una Skulltula que otorga #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = HintText::Exclude({ - //obscure text - Text{"an #invisible path in the well# leads to", /*french*/"une #Skulltula dans le chemin invisible au fonds du Puits# a", /*spanish*/"un #camino invisible del pozo# conduce a una Skulltula que otorga"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = HintText(CustomMessage("They say that a #spider locked in a crypt# within the well guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula embarrée dans la crypte au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula encerrada en una cripta# del pozo otorga #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider locked in a crypt# within the well guards", /*french*/"une #Skulltula embarrée dans la crypte au fonds du Puits# a", /*spanish*/"una #Skulltula encerrada en una cripta# del pozo otorga"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = HintText(CustomMessage("They say that a #gauntlet of invisible spiders# protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée par les araignées invisibles au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unas #arañas invisibles# custodian una Skulltula que otorga #[[1]]#. + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = HintText(CustomMessage("They say that a #spider crawling near the dead# in the well holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près des cercueils au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula junto a los muertos# del pozo otorga #[[1]]#. - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = HintText::Exclude({ - //obscure text - Text{"a #gauntlet of invisible spiders# protects", /*french*/"une #Skulltula protégée par les araignées invisibles au fonds du Puits# a", /*spanish*/"unas #arañas invisibles# custodian una Skulltula que otorga"}, - }); - - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider crawling near the dead# in the well holds", /*french*/"une #Skulltula près des cercueils au fonds du Puits# a", /*spanish*/"una #Skulltula junto a los muertos# del pozo otorga"}, - }); - - hintTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider locked in a crypt# within the well guards", /*french*/"une #Skulltula embarrée dans la crypte au fonds du Puits# a", /*spanish*/"una #Skulltula encerrada en una cripta# del pozo otorga"}, - }); + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = HintText(CustomMessage("They say that a #spider locked in a crypt# within the well guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula embarrée dans la crypte au fonds du Puits# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula encerrada en una cripta# del pozo otorga #[[1]]#. /*-------------------------- | ICE CAVERN | ---------------------------*/ - hintTable[RHT_ICE_CAVERN_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"#winds of ice# surround", /*french*/"#figé dans la glace rouge# gît", /*spanish*/"#heladas borrascas# rodean"}, - }); + hintTextTable[RHT_ICE_CAVERN_MAP_CHEST] = HintText(CustomMessage("They say that #winds of ice# surround #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #figé dans la glace rouge# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #heladas borrascas# rodean #[[1]]#. - hintTable[RHT_ICE_CAVERN_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #wall of ice# protects", /*french*/"#un mur de glace rouge# cache", /*spanish*/"una #gélida pared# protege"}, - }); + hintTextTable[RHT_ICE_CAVERN_COMPASS_CHEST] = HintText(CustomMessage("They say that a #wall of ice# protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #un mur de glace rouge# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #gélida pared# protege #[[1]]#. - hintTable[RHT_ICE_CAVERN_IRON_BOOTS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #monster in a frozen cavern# guards", /*french*/"le #monstre de la caverne de glace# protège", /*spanish*/"un #monstruo de una helada caverna# guarda"}, - }); + hintTextTable[RHT_ICE_CAVERN_IRON_BOOTS_CHEST] = HintText(CustomMessage("They say that a #monster in a frozen cavern# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #monstre de la caverne de glace# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #monstruo de una helada caverna# guarda #[[1]]#. - hintTable[RHT_ICE_CAVERN_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"a #wall of ice# protects", /*french*/"un #mur de glace rouge# cache", /*spanish*/"una #gélida pared# protege"}, - }); + hintTextTable[RHT_ICE_CAVERN_FREESTANDING_POH] = HintText(CustomMessage("They say that a #wall of ice# protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #mur de glace rouge# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #gélida pared# protege #[[1]]#. + hintTextTable[RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = HintText(CustomMessage("They say that a #monster in a frozen cavern# guards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #monstre de la caverne de glace# protège #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #monstruo de una helada caverna# guarda #[[1]]#. - hintTable[RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #monster in a frozen cavern# guards", /*french*/"le #monstre de la caverne de glace# protège", /*spanish*/"un #monstruo de una helada caverna# guarda"}, - }); + hintTextTable[RHT_ICE_CAVERN_MQ_COMPASS_CHEST] = HintText(CustomMessage("They say that #winds of ice# surround #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #entouré de vent glacial# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #heladas borrascas# rodean #[[1]]#. - hintTable[RHT_ICE_CAVERN_MQ_COMPASS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#winds of ice# surround", /*french*/"#entouré de vent glacial# gît", /*spanish*/"#heladas borrascas# rodean"}, - }); + hintTextTable[RHT_ICE_CAVERN_MQ_MAP_CHEST] = HintText(CustomMessage("They say that a #wall of ice# protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #un mur de glace rouge# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #gélida pared# protege #[[1]]#. - hintTable[RHT_ICE_CAVERN_MQ_MAP_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #wall of ice# protects", /*french*/"#un mur de glace rouge# cache", /*spanish*/"una #gélida pared# protege"}, - }); + hintTextTable[RHT_ICE_CAVERN_MQ_FREESTANDING_POH] = HintText(CustomMessage("They say that #winds of ice# surround #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #entouré de vent glacial# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #heladas borrascas# rodean #[[1]]#. - hintTable[RHT_ICE_CAVERN_MQ_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"#winds of ice# surround", /*french*/"#entouré de vent glacial# gît", /*spanish*/"#heladas borrascas# rodean"}, - }); + hintTextTable[RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = HintText(CustomMessage("They say that a #spider above icy pits# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'un goufre glacial# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre gélidos vacíos# otorga #[[1]]#. - hintTable[RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider above icy pits# holds", /*french*/"une #Skulltula au dessus d'un goufre glacial# a", /*spanish*/"una #Skulltula sobre gélidos vacíos# otorga"}, - }); + hintTextTable[RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = HintText(CustomMessage("They say that #spinning ice# guards a spider holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près de deux lames de glace# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #témpanos giratorios# custodian una Skulltula que otorga #[[1]]#. - hintTable[RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = HintText::Exclude({ - //obscure text - Text{"#spinning ice# guards a spider holding", /*french*/"une #Skulltula près de deux lames de glace# a", /*spanish*/"unos #témpanos giratorios# custodian una Skulltula que otorga"}, - }); + hintTextTable[RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM] = HintText(CustomMessage("They say that a #spider behind a wall of ice# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière un mur de glace# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras una gélida pared# otorga #[[1]]#. - hintTable[RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM] = HintText::Exclude({ - //obscure text - Text{"a #spider behind a wall of ice# hides", /*french*/"une #Skulltula derrière un mur de glace# a", /*spanish*/"una #Skulltula tras una gélida pared# otorga"}, - }); + hintTextTable[RHT_ICE_CAVERN_MQ_GS_SCARECROW] = HintText(CustomMessage("They say that a #spider above icy pits# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'un goufre glacial# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula sobre gélidos vacíos# otorga #[[1]]#. + hintTextTable[RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK] = HintText(CustomMessage("They say that a #web of ice# surrounds a spider with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula protégée d'une toile glacée# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #gélida red# rodea a una Skulltula que otorga #[[1]]#. - hintTable[RHT_ICE_CAVERN_MQ_GS_SCARECROW] = HintText::Exclude({ - //obscure text - Text{"a #spider above icy pits# holds", /*french*/"une #Skulltula au dessus d'un goufre glacial# a", /*spanish*/"una #Skulltula sobre gélidos vacíos# otorga"}, - }); - - hintTable[RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK] = HintText::Exclude({ - //obscure text - Text{"a #web of ice# surrounds a spider with", /*french*/"une #Skulltula protégée d'une toile glacée# a", /*spanish*/"una #gélida red# rodea a una Skulltula que otorga"}, - }); - - hintTable[RHT_ICE_CAVERN_MQ_GS_RED_ICE] = HintText::Exclude({ - //obscure text - Text{"a #spider in fiery ice# hoards", /*french*/"une #Skulltula figée dans la glace rouge# a", /*spanish*/"una #Skulltula tras un ardiente hielo# otorga"}, - }); + hintTextTable[RHT_ICE_CAVERN_MQ_GS_RED_ICE] = HintText(CustomMessage("They say that a #spider in fiery ice# hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula figée dans la glace rouge# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula tras un ardiente hielo# otorga #[[1]]#. /*-------------------------- | GERUDO TRAINING GROUNDS | ---------------------------*/ - hintTable[RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #blinded eye in the Gerudo Training Grounds# drops", /*french*/"l'#Oeil dans le Gymnase Gerudo# voit", /*spanish*/"#cegar un ojo en el Centro de Instrucción Gerudo# revela"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = HintText(CustomMessage("They say that a #blinded eye in the Gerudo Training Grounds# drops #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#Oeil dans le Gymnase Gerudo# voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cegar un ojo en el Centro de Instrucción Gerudo# revela #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #blinded eye in the Gerudo Training Grounds# drops", /*french*/"l'#Oeil dans le Gymnase Gerudo# voit", /*spanish*/"#cegar un ojo en el Centro de Instrucción Gerudo# revela"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = HintText(CustomMessage("They say that a #blinded eye in the Gerudo Training Grounds# drops #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#Oeil dans le Gymnase Gerudo# voit #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #cegar un ojo en el Centro de Instrucción Gerudo# revela #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#soldiers walking on shifting sands# in the Gerudo Training Grounds guard", /*french*/"les #squelettes# du Gymnase Gerudo protègent", /*spanish*/"#soldados en resbaladizas arenas# del Centro de Instrucción Gerudo protegen"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = HintText(CustomMessage("They say that #soldiers walking on shifting sands# in the Gerudo Training Grounds guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #squelettes# du Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #soldados en resbaladizas arenas# del Centro de Instrucción Gerudo protegen #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reptilian warriors# in the Gerudo Training Grounds protect", /*french*/"les #lézards# dans le Gymnase Gerudo protègent", /*spanish*/"#unos escamosos guerreros# del Centro de Instrucción Gerudo protegen"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = HintText(CustomMessage("They say that #reptilian warriors# in the Gerudo Training Grounds protect #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #lézards# dans le Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #unos escamosos guerreros# del Centro de Instrucción Gerudo protegen #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth# in the Gerudo Training Grounds reveals", /*french*/"#bien caché# dans le Gymnase Gerudo gît", /*spanish*/"el #Ojo de la Verdad# en el Centro de Instrucción Gerudo revela"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth# in the Gerudo Training Grounds reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #bien caché# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# en el Centro de Instrucción Gerudo revela #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = HintText::Exclude({ - //obscure text - Text{"the first prize of #the thieves' training# is", /*french*/"le #premier trésor du Gymnase Gerudo# est", /*spanish*/"el primer premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = HintText(CustomMessage("They say that the first prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #premier trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el primer premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = HintText::Exclude({ - //obscure text - Text{"the second prize of #the thieves' training# is", /*french*/"le #deuxième trésor du Gymnase Gerudo# est", /*spanish*/"el segundo premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = HintText(CustomMessage("They say that the second prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #deuxième trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el segundo premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = HintText::Exclude({ - //obscure text - Text{"the third prize of #the thieves' training# is", /*french*/"le #troisième trésor du Gymnase Gerudo# est", /*spanish*/"el tercer premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = HintText(CustomMessage("They say that the third prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #troisième trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el tercer premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Song of Time# in the Gerudo Training Grounds leads to", /*french*/"le #chant du temps# révèle dans le Gymnase Gerudo", /*spanish*/"la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = HintText(CustomMessage("They say that the #Song of Time# in the Gerudo Training Grounds leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chant du temps# révèle dans le Gymnase Gerudo #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Song of Time# in the Gerudo Training Grounds leads to", /*french*/"le #chant du temps# révèle dans le Gymnase Gerudo", /*spanish*/"la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = HintText(CustomMessage("They say that the #Song of Time# in the Gerudo Training Grounds leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chant du temps# révèle dans le Gymnase Gerudo #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = HintText::Exclude({ - //obscure text - Text{"#fiery foes# in the Gerudo Training Grounds guard", /*french*/"les #limaces de feu# du Gymnase Gerudo protègent", /*spanish*/"unos #flamígeros enemigos# del Centro de Instrucción Gerudo guardan"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = HintText(CustomMessage("They say that #fiery foes# in the Gerudo Training Grounds guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #limaces de feu# du Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #flamígeros enemigos# del Centro de Instrucción Gerudo guardan #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"#engulfed in flame# where thieves train lies", /*french*/"le #trésor enflammé# du Gymnase Gerudo est", /*spanish*/"donde entrenan las bandidas #entre llamas# yace"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = HintText(CustomMessage("They say that #engulfed in flame# where thieves train lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor enflammé# du Gymnase Gerudo est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, donde entrenan las bandidas #entre llamas# yace #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = HintText::Exclude({ - //obscure text - Text{"thieves #blind four faces# to find", /*french*/"l'#épreuve d'archerie# du Gymnase Gerudo donne", /*spanish*/"las bandidas #ciegan cuatro bustos# para hallar"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = HintText(CustomMessage("They say that thieves #blind four faces# to find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve d'archerie# du Gymnase Gerudo donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las bandidas #ciegan cuatro bustos# para hallar #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = HintText::Exclude({ - //obscure text - Text{"thieves #blind four faces# to find", /*french*/"l'#épreuve d'archerie# du Gymnase Gerudo donne", /*spanish*/"las bandidas #ciegan cuatro bustos# para hallar"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = HintText(CustomMessage("They say that thieves #blind four faces# to find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve d'archerie# du Gymnase Gerudo donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las bandidas #ciegan cuatro bustos# para hallar #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = HintText::Exclude({ - //obscure text - Text{"#before a block of silver# thieves can find", /*french*/"#près d'un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"#ante un plateado bloque# las bandidas hallan"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = HintText(CustomMessage("They say that #before a block of silver# thieves can find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #près d'un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #ante un plateado bloque# las bandidas hallan #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #feat of strength# rewards thieves with", /*french*/"#derrière un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"una #hazaña de fuerza# premia a las bandidas con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = HintText(CustomMessage("They say that a #feat of strength# rewards thieves with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #hazaña de fuerza# premia a las bandidas con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #feat of strength# rewards thieves with", /*french*/"#derrière un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"una #hazaña de fuerza# premia a las bandidas con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = HintText(CustomMessage("They say that a #feat of strength# rewards thieves with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #hazaña de fuerza# premia a las bandidas con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #feat of strength# rewards thieves with", /*french*/"#derrière un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"una #hazaña de fuerza# premia a las bandidas con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = HintText(CustomMessage("They say that a #feat of strength# rewards thieves with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #hazaña de fuerza# premia a las bandidas con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #feat of strength# rewards thieves with", /*french*/"#derrière un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"una #hazaña de fuerza# premia a las bandidas con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = HintText(CustomMessage("They say that a #feat of strength# rewards thieves with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #hazaña de fuerza# premia a las bandidas con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"the #Song of Time# in the Gerudo Training Grounds leads to", /*french*/"le #chant du temps# révèle dans le Gymnase Gerudo", /*spanish*/"la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = HintText(CustomMessage("They say that the #Song of Time# in the Gerudo Training Grounds leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chant du temps# révèle dans le Gymnase Gerudo #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #Canción del Tiempo# en el Centro de Instrucción Gerudo conduce a #[[1]]#. + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = HintText(CustomMessage("They say that #thieves prepare for training# with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans #l'entrée du Gymnase Gerudo# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #bandidas se instruyen# con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#thieves prepare for training# with", /*french*/"dans #l'entrée du Gymnase Gerudo# gît", /*spanish*/"las #bandidas se instruyen# con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = HintText(CustomMessage("They say that #thieves prepare for training# with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans #l'entrée du Gymnase Gerudo# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #bandidas se instruyen# con #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#thieves prepare for training# with", /*french*/"dans #l'entrée du Gymnase Gerudo# gît", /*spanish*/"las #bandidas se instruyen# con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = HintText(CustomMessage("They say that #soldiers walking on shifting sands# in the Gerudo Training Grounds guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #squelettes# du Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #soldados en resbaladizas arenas# del Centro de Instrucción Gerudo protegen #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#soldiers walking on shifting sands# in the Gerudo Training Grounds guard", /*french*/"les #squelettes# du Gymnase Gerudo protègent", /*spanish*/"#soldados en resbaladizas arenas# del Centro de Instrucción Gerudo protegen"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = HintText(CustomMessage("They say that #before a block of silver# thieves can find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #près d'un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #ante un plateado bloque# las bandidas hallan #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = HintText::Exclude({ - //obscure text - Text{"#before a block of silver# thieves can find", /*french*/"#près d'un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"#ante un plateado bloque# las bandidas hallan"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = HintText(CustomMessage("They say that thieves #blind four faces# to find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve d'archerie# du Gymnase Gerudo donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las bandidas #ciegan cuatro bustos# para hallar #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = HintText::Exclude({ - //obscure text - Text{"thieves #blind four faces# to find", /*french*/"l'#épreuve d'archerie# du Gymnase Gerudo donne", /*spanish*/"las bandidas #ciegan cuatro bustos# para hallar"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = HintText(CustomMessage("They say that #engulfed in flame# where thieves train lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor enflammé# du Gymnase Gerudo est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, donde entrenan las bandidas #entre llamas# yace #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#engulfed in flame# where thieves train lies", /*french*/"le #trésor enflammé# du Gymnase Gerudo est", /*spanish*/"donde entrenan las bandidas #entre llamas# yace"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = HintText(CustomMessage("They say that #fiery foes# in the Gerudo Training Grounds guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #ennemis de feu# du Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #flamígeros enemigos# del Centro de Instrucción Gerudo guardan #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#fiery foes# in the Gerudo Training Grounds guard", /*french*/"les #ennemis de feu# du Gymnase Gerudo protègent", /*spanish*/"unos #flamígeros enemigos# del Centro de Instrucción Gerudo guardan"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = HintText(CustomMessage("They say that #reptilian warriors# in the Gerudo Training Grounds protect #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #lézards# dans le Gymnase Gerudo protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #unos escamosos guerreros# del Centro de Instrucción Gerudo protegen #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reptilian warriors# in the Gerudo Training Grounds protect", /*french*/"les #lézards# dans le Gymnase Gerudo protègent", /*spanish*/"#unos escamosos guerreros# del Centro de Instrucción Gerudo protegen"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = HintText(CustomMessage("They say that a #path of fire# leads thieves to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans le #chemin enflammé# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #camino de fuego# conduce a las bandidas a #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #path of fire# leads thieves to", /*french*/"dans le #chemin enflammé# dans le Gymnase Gerudo gît", /*spanish*/"un #camino de fuego# conduce a las bandidas a"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = HintText(CustomMessage("They say that the first prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #premier trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el primer premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = HintText::Exclude({ - //obscure text - Text{"the first prize of #the thieves' training# is", /*french*/"le #premier trésor du Gymnase Gerudo# est", /*spanish*/"el primer premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = HintText(CustomMessage("They say that a #path of fire# leads thieves to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans le #chemin enflammé# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #camino de fuego# conduce a las bandidas a #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #path of fire# leads thieves to", /*french*/"dans le #chemin enflammé# dans le Gymnase Gerudo gît", /*spanish*/"un #camino de fuego# conduce a las bandidas a"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = HintText(CustomMessage("They say that the third prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #troisième trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el tercer premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = HintText::Exclude({ - //obscure text - Text{"the third prize of #the thieves' training# is", /*french*/"le #troisième trésor du Gymnase Gerudo# est", /*spanish*/"el tercer premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = HintText(CustomMessage("They say that the second prize of #the thieves' training# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #deuxième trésor du Gymnase Gerudo# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el segundo premio de la #instrucción bandida# se trata de #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = HintText::Exclude({ - //obscure text - Text{"the second prize of #the thieves' training# is", /*french*/"le #deuxième trésor du Gymnase Gerudo# est", /*spanish*/"el segundo premio de la #instrucción bandida# se trata de"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = HintText(CustomMessage("They say that the #Eye of Truth# in the Gerudo Training Grounds reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #bien caché# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Ojo de la Verdad# en el Centro de Instrucción Gerudo revela #[[1]]#. - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Eye of Truth# in the Gerudo Training Grounds reveals", /*french*/"#bien caché# dans le Gymnase Gerudo gît", /*spanish*/"el #Ojo de la Verdad# en el Centro de Instrucción Gerudo revela"}, - }); - - hintTable[RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #feat of strength# rewards thieves with", /*french*/"#derrière un bloc argent# dans le Gymnase Gerudo gît", /*spanish*/"una #hazaña de fuerza# premia a las bandidas con"}, - }); + hintTextTable[RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = HintText(CustomMessage("They say that a #feat of strength# rewards thieves with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière un bloc argent# dans le Gymnase Gerudo gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #hazaña de fuerza# premia a las bandidas con #[[1]]#. /*-------------------------- | GANONS CASTLE | ---------------------------*/ - hintTable[RHT_GANONS_TOWER_BOSS_KEY_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #Evil King# hoards", /*french*/"le #Roi du Mal# possède", /*spanish*/"el #Rey del Mal# acapara"}, - }); + hintTextTable[RHT_GANONS_TOWER_BOSS_KEY_CHEST] = HintText(CustomMessage("They say that the #Evil King# hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #Roi du Mal# possède #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #Rey del Mal# acapara #[[1]]#. + hintTextTable[RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST] = HintText(CustomMessage("They say that the #test of the wilds# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des bois# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la naturaleza# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the wilds# holds", /*french*/"l'#épreuve des bois# contient", /*spanish*/"la #prueba de la naturaleza# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = HintText(CustomMessage("They say that the #test of the seas# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des mers# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del mar# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the seas# holds", /*french*/"l'#épreuve des mers# contient", /*spanish*/"la #prueba del mar# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = HintText(CustomMessage("They say that the #test of the seas# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des mers# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del mar# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the seas# holds", /*french*/"l'#épreuve des mers# contient", /*spanish*/"la #prueba del mar# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = HintText(CustomMessage("They say that #music in the test of darkness# unveils #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #musique dans l'épreuve des ténèbres# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #música en la prueba de la oscuridad# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#music in the test of darkness# unveils", /*french*/"la #musique dans l'épreuve des ténèbres# révèle", /*spanish*/"la #música en la prueba de la oscuridad# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = HintText(CustomMessage("They say that #light in the test of darkness# unveils #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #lumière dans l'épreuve des ténèbres# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #luz en la prueba de la oscuridad# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#light in the test of darkness# unveils", /*french*/"la #lumière dans l'épreuve des ténèbres# révèle", /*spanish*/"la #luz en la prueba de la oscuridad# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = HintText(CustomMessage("They say that the #test of the sands# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des sables# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de las arenas# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the sands# holds", /*french*/"l'#épreuve des sables# contient", /*spanish*/"la #prueba de las arenas# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = HintText(CustomMessage("They say that the #test of the sands# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des sables# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de las arenas# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the sands# holds", /*french*/"l'#épreuve des sables# contient", /*spanish*/"la #prueba de las arenas# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = HintText(CustomMessage("They say that the #test of radiance# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve du ciel# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del resplandor# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of radiance# holds", /*french*/"l'#épreuve du ciel# contient", /*spanish*/"la #prueba del resplandor# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = HintText(CustomMessage("They say that #music in the test of radiance# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #musique dans l'épreuve du ciel# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #música en la prueba del resplandor# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#music in the test of radiance# reveals", /*french*/"la #musique dans l'épreuve du ciel# révèle", /*spanish*/"la #música en la prueba del resplandor# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = HintText(CustomMessage("They say that the #test of the seas# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des mers# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba del mar# brinda #[[1]]#. + hintTextTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = HintText(CustomMessage("They say that the #test of the wilds# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des bois# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la naturaleza# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the seas# holds", /*french*/"l'#épreuve des mers# contient", /*spanish*/"la #prueba del mar# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = HintText(CustomMessage("They say that the #test of the wilds# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des bois# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la naturaleza# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the wilds# holds", /*french*/"l'#épreuve des bois# contient", /*spanish*/"la #prueba de la naturaleza# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = HintText(CustomMessage("They say that #music in the test of radiance# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #musique dans l'épreuve du ciel# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #música en la prueba del resplandor# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of the wilds# holds", /*french*/"l'#épreuve des bois# contient", /*spanish*/"la #prueba de la naturaleza# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = HintText(CustomMessage("They say that the #test of darkness# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des ténèbres# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la oscuridad# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = HintText::Exclude({ - //obscure text - Text{"#music in the test of radiance# reveals", /*french*/"la #musique dans l'épreuve du ciel# révèle", /*spanish*/"la #música en la prueba del resplandor# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = HintText(CustomMessage("They say that the #test of darkness# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des ténèbres# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la oscuridad# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of darkness# holds", /*french*/"l'#épreuve des ténèbres# contient", /*spanish*/"la #prueba de la oscuridad# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #test of darkness# holds", /*french*/"l'#épreuve des ténèbres# contient", /*spanish*/"la #prueba de la oscuridad# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = HintText(CustomMessage("They say that #reflected light in the test of the sands# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #soleil dans l'épreuve des sables# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #reflejar la luz en la prueba de las arenas# revela #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = HintText(CustomMessage("They say that the #test of the wilds# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#épreuve des bois# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #prueba de la naturaleza# brinda #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = HintText::Exclude({ - //obscure text - Text{"#reflected light in the test of the sands# reveals", /*french*/"le #soleil dans l'épreuve des sables# révèle", /*spanish*/"#reflejar la luz en la prueba de las arenas# revela"}, - }); + hintTextTable[RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = HintText::Exclude({ - //obscure text - Text{"the #test of the wilds# holds", /*french*/"l'#épreuve des bois# révèle", /*spanish*/"la #prueba de la naturaleza# brinda"}, - }); + hintTextTable[RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. + hintTextTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. - hintTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); - - hintTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); - - hintTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); - - hintTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = HintText::Exclude({ - //obscure text - Text{"#scrubs in Ganon's Castle# sell", /*french*/"les #pestes Mojo dans le Château de Ganon# vendent", /*spanish*/"los #dekus del Castillo de Ganon# venden"}, - }); + hintTextTable[RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = HintText(CustomMessage("They say that #scrubs in Ganon's Castle# sell #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #pestes Mojo dans le Château de Ganon# vendent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, los #dekus del Castillo de Ganon# venden #[[1]]#. +} } diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index c705bb2b6..570101b4e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -1,1467 +1,1491 @@ -#include "../hint_list.hpp" -#include - -void HintTable_Init_Exclude_Overworld() { - hintTable[RHT_KF_KOKIRI_SWORD_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #hidden treasure of the Kokiri# is", /*french*/"le #trésor des Kokiri# est", /*spanish*/"el #tesoro oculto de los Kokiri# esconde"}, - }); - - hintTable[RHT_KF_MIDOS_TOP_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #leader of the Kokiri# hides", /*french*/"le #chef des Kokiri# possède", /*spanish*/"el #líder de los Kokiri# esconde"}, - }, {}, - //clear text - Text{"#inside Mido's house# is", /*french*/"#dans la maison de Mido# gît", /*spanish*/"en la #casa de Mido# yace"} - ); - - hintTable[RHT_KF_MIDOS_TOP_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #leader of the Kokiri# hides", /*french*/"le #chef des Kokiri# possède", /*spanish*/"el #líder de los Kokiri# esconde"}, - }, {}, - //clear text - Text{"#inside Mido's house# is", /*french*/"#dans la maison de Mido# gît", /*spanish*/"en la #casa de Mido# yace"} - ); - - hintTable[RHT_KF_MIDOS_BOTTOM_LEFT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #leader of the Kokiri# hides", /*french*/"le #chef des Kokiri# possède", /*spanish*/"el #líder de los Kokiri# esconde"}, - }, {}, - //clear text - Text{"#inside Mido's house# is", /*french*/"#dans la maison de Mido# gît", /*spanish*/"en la #casa de Mido# yace"} - ); - - hintTable[RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #leader of the Kokiri# hides", /*french*/"le #chef des Kokiri# possède", /*spanish*/"el #líder de los Kokiri# esconde"}, - }, {}, - //clear text - Text{"#inside Mido's house# is", /*french*/"#dans la maison de Mido# gît", /*spanish*/"en la #casa de Mido# yace"} - ); - - hintTable[RHT_GRAVEYARD_SHIELD_GRAVE_CHEST] = HintText::Exclude({ - //obscure text - Text{"the #treasure of a fallen soldier# is", /*french*/"le #trésor du soldat mort# est", /*spanish*/"el #tesoro de un soldado caído# esconde"}, - }); - - hintTable[RHT_DMT_CHEST] = HintText::Exclude({ - //obscure text - Text{"hidden behind a wall on a #mountain trail# is", /*french*/"derrière une façade du #chemin montagneux# est", /*spanish*/"tras una pared del #sendero de la montaña# yace"}, - }); - - hintTable[RHT_GC_MAZE_RIGHT_CHEST] = HintText::Exclude({ - //obscure text - Text{"in #Goron City# explosives unlock", /*french*/"des explosions dans le #village Goron# révèlent", /*spanish*/"en la #Ciudad Goron# unos explosivos desbloquean"}, - }); - - hintTable[RHT_GC_MAZE_CENTER_CHEST] = HintText::Exclude({ - //obscure text - Text{"in #Goron City# explosives unlock", /*french*/"des explosions dans le #village Goron# révèlent", /*spanish*/"en la #Ciudad Goron# unos explosivos desbloquean"}, - }); - - hintTable[RHT_ZD_CHEST] = HintText::Exclude({ - //obscure text - Text{"fire #beyond a waterfall# reveals", /*french*/"du feu #derrière la cascade# éclaire", /*spanish*/"las #llamas tras una una cascada# revelan"}, - }); - - hintTable[RHT_GRAVEYARD_HOOKSHOT_CHEST] = HintText::Exclude({ - //obscure text - Text{"a chest hidden by a #speedy spectre# holds", /*french*/"le #coffre du rapide revenant# contient", /*spanish*/"un cofre custodiado por un #espectro veloz# contiene"}, - }, {}, - //clear text - Text{"#dead Dampé's first prize# is", /*french*/"la #première course d'Igor# donne", /*spanish*/"el primer premio de #la carrera de Dampé# se trata de"} - ); - - hintTable[RHT_GF_CHEST] = HintText::Exclude({ - //obscure text - Text{"on a #rooftop in the desert# lies", /*french*/"sur un #toit du désert# gît", /*spanish*/"en una #azotea del desierto# yace"}, - }); - - hintTable[RHT_KAK_REDEAD_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"#zombies beneath the earth# guard", /*french*/"les #revenants sous terre# protègent", /*spanish*/"unos #zombis subterráneos# esconden"}, - }); - - hintTable[RHT_SFM_WOLFOS_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"#wolves beneath the earth# guard", /*french*/"les #loups sous terre# protègent", /*spanish*/"unos #lobos subterráneos# esconden"}, - }); - - hintTable[RHT_HF_NEAR_MARKET_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole in a field near a drawbridge# holds", /*french*/"la #grotte près d'un pont# contient", /*spanish*/"bajo el #hoyo de una llanura cercano a un puente# yace"}, - }); - - hintTable[RHT_HF_NEAR_MARKET_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole in a field near a drawbridge# holds", /*french*/"la #grotte près d'un pont# contient", /*spanish*/"bajo el #hoyo de una llanura cercano a un puente# yace"}, - }); - - hintTable[RHT_HF_SOUTHEAST_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole amongst trees in a field# holds", /*french*/"la #grotte près des arbres# contient", /*spanish*/"bajo el #hoyo de una llanura rodeado de árboles# yace"}, - }); - - hintTable[RHT_HF_SOUTHEAST_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole amongst trees in a field# holds", /*french*/"la #grotte près des arbres# contient", /*spanish*/"bajo el #hoyo de una llanura rodeado de árboles# yace"}, - }); - - hintTable[RHT_HF_OPEN_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #open hole in a field# holds", /*french*/"la #grotte dans les plaines# contient", /*spanish*/"bajo el #hoyo descubierto de una llanura# yace"}, - }); - - hintTable[RHT_HF_OPEN_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in an open hole in a field# holds", /*french*/"la #grotte dans les plaines# contient", /*spanish*/"bajo el #hoyo descubierto de una llanura# yace"}, - }); - - hintTable[RHT_KAK_OPEN_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"an #open hole in a town# holds", /*french*/"la #grotte dans le village# contient", /*spanish*/"bajo el #hoyo descubierto de un pueblo# yace"}, - }); - - hintTable[RHT_KAK_OPEN_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in an open hole in a town# holds", /*french*/"la #grotte dans le village# contient", /*spanish*/"bajo el #hoyo descubierto de un pueblo# yace"}, - }); - - hintTable[RHT_ZR_OPEN_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole along a river# holds", /*french*/"la #grotte près du fleuve# contient", /*spanish*/"bajo un #hoyo junto a un río# yace"}, - }); - - hintTable[RHT_ZR_OPEN_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole along a river# holds", /*french*/"la #grotte près du fleuve# contient", /*spanish*/"bajo un #hoyo junto a un río# yace"}, - }); - - hintTable[RHT_KF_STORMS_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole in a forest village# holds", /*french*/"la #grotte inondée de pluie dans le Village Kokiri# révèle", /*spanish*/"bajo el #hoyo de una tribu del bosque# yace"}, - }); - - hintTable[RHT_KF_STORMS_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole in a forest village# holds", /*french*/"la #grotte inondée de pluie dans le Village Kokiri# révèle", /*spanish*/"bajo el #hoyo de una tribu del bosque# yace"}, - }); - - hintTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole in a wooded maze# holds", /*french*/"la #grotte dans le labyrinthe sylvestre# contient", /*spanish*/"bajo un #hoyo de un laberinto forestal# yace"}, - }); - - hintTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole in a wooded maze# holds", /*french*/"la #grotte dans le labyrinthe sylvestre# contient", /*spanish*/"bajo un #hoyo de un laberinto forestal# yace"}, - }); - - hintTable[RHT_DMT_STORMS_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"#hole flooded with rain on a mountain# holds", /*french*/"la #grotte inondée de pluie sur la montagne# contient", /*spanish*/"bajo un #hoyo de una montaña inundado de lluvia# yace"}, - }); - - hintTable[RHT_DMT_STORMS_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"#fish in a hole flooded with rain on a mountain# holds", /*french*/"la #grotte inondée de pluie sur la montagne# contient", /*spanish*/"bajo un #hoyo de una montaña inundado de lluvia# yace"}, - }); - - hintTable[RHT_DMC_UPPER_GROTTO_CHEST] = HintText::Exclude({ - //obscure text - Text{"a #hole in a volcano# holds", /*french*/"la #grotte dans le volcan# contient", /*spanish*/"bajo el #hoyo de un volcán# yace"}, - }); - - hintTable[RHT_DMC_UPPER_GROTTO_FISH] = HintText::Exclude({ - //obscure text - Text{"a #fish in a hole in a volcano# holds", /*french*/"la #grotte dans le volcan# contient", /*spanish*/"bajo el #hoyo de un volcán# yace"}, - }); - - hintTable[RHT_TOT_MASTER_SWORD] = HintText::Exclude({ - //obscure text - Text{"a #pedestal in a temple# holds", /*french*/"un #piédestal dans un temple# contient", /*spanish*/"un #pedestal en un templo# sostiene"}, - }); - - hintTable[RHT_TOT_LIGHT_ARROWS_CUTSCENE] = HintText::Exclude({ - //obscure text - Text{"the #final gift of a princess# is", /*french*/"le #cadeau d'adieu de la princesse# est", /*spanish*/"el #obsequio final de la princesa# se trata de"}, - }); - - hintTable[RHT_LW_GIFT_FROM_SARIA] = HintText::Exclude({ - //obscure text - Text{"a #potato hoarder# holds", /*french*/"le #panini mélodieux# est en fait", /*spanish*/"cierta #jovencita verde# concede"}, - Text{"a rooty tooty #flutey cutey# gifts", /*french*/"la #patate musicale# est en fait", /*spanish*/"una #gran amiga# concede"}, - }, {}, - //clear text - Text{"#Saria's Gift# is", /*french*/"le #cadeau de Saria# est", /*spanish*/"el #regalo de Saria# se trata de"} - ); - - hintTable[RHT_ZF_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"the #fairy of winds# holds", /*french*/"la #fée du vent# a", /*spanish*/"el #hada del viento# brinda"}, - }); - - hintTable[RHT_HC_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"the #fairy of fire# holds", /*french*/"la #fée du feu# a", /*spanish*/"el #hada del fuego# brinda"}, - }); - - hintTable[RHT_COLOSSUS_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"the #fairy of love# holds", /*french*/"la #fée de l'amour# a", /*spanish*/"el #hada del amor# brinda"}, - }); - - hintTable[RHT_DMT_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"a #magical fairy# gifts", /*french*/"la #fée de la magie# a", /*spanish*/"un #hada mágica# brinda"}, - }); - - hintTable[RHT_DMC_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"a #magical fairy# gifts", /*french*/"la #fée de la magie# a", /*spanish*/"un #hada mágica# brinda"}, - }); - - hintTable[RHT_OGC_GREAT_FAIRY_REWARD] = HintText::Exclude({ - //obscure text - Text{"the #fairy of strength# holds", /*french*/"la #fée de la force# a", /*spanish*/"el #hada de la fuerza# brinda"}, - }); - - - hintTable[RHT_SONG_FROM_IMPA] = HintText::Exclude({ - //obscure text - Text{"#deep in a castle#, Impa teaches", /*french*/"#la gardienne de la princesse# donne", /*spanish*/"en el #jardín del castillo Impa enseña#"}, - }); - - hintTable[RHT_SONG_FROM_MALON] = HintText::Exclude({ - //obscure text - Text{"#a farm girl# sings", /*french*/"la #fillette de la ferme# donne", /*spanish*/"una #chica rupestre# canta"}, - }); - - hintTable[RHT_SONG_FROM_SARIA] = HintText::Exclude({ - //obscure text - Text{"#deep in the forest#, Saria teaches", /*french*/"la #fille de la forêt# donne", /*spanish*/"al #fondo del bosque# Saria enseña"}, - }); - - hintTable[RHT_SONG_FROM_WINDMILL] = HintText::Exclude({ - //obscure text - Text{"a man #in a windmill# is obsessed with", /*french*/"l'#homme du moulin# donne", /*spanish*/"el #hombre del molino# está obsesionado con"}, - }); - - - hintTable[RHT_HC_MALON_EGG] = HintText::Exclude({ - //obscure text - Text{"a #girl looking for her father# gives", /*french*/"la #fillette qui cherche son père# donne", /*spanish*/"una #chica en busca de su padre# otorga"}, - }); - - hintTable[RHT_HC_ZELDAS_LETTER] = HintText::Exclude({ - //obscure text - Text{"a #princess in a castle# gifts", /*french*/"la #princesse dans le château# donne", /*spanish*/"la #princesa de un castillo# otorga"}, - }); - - hintTable[RHT_ZD_DIVING_MINIGAME] = HintText::Exclude({ - //obscure text - Text{"an #unsustainable business model# gifts", /*french*/"le #mauvais modèle d'affaires# donne", /*spanish*/"un #mal modelo de negocio# premia con"}, - }, {}, - //clear text - Text{"those who #dive for Zora rupees# will find", /*french*/"ceux qui #plongent pour des rubis Zora# trouveront", /*spanish*/"aquellos que se #sumergan por las rupias zora# encontrarán"} - ); - - hintTable[RHT_LH_CHILD_FISHING] = HintText::Exclude({ - //obscure text - Text{"#fishing in youth# bestows", /*french*/"#pêcher dans sa jeunesse# promet", /*spanish*/"#pescar en la juventud# conduce a"}, - }); - - // TODO: needs french + spanish translation - hintTable[RHT_LH_POND_FISH] = HintText::Exclude({ - //obscure text - Text{"#hitting the pond# reveals", /*french*/ "", /*spanish*/ ""}, - {}, - //clear text - Text{"#the fishing pond's bounty# includes", /*french*/ "", /*spanish*/ ""} - }); - - // TODO: needs french translation - hintTable[RHT_LH_HYRULE_LOACH] = HintText::Exclude( - { - // obscure text - Text{ "#fishing the legend# bestows", /*french*/ "!!!", /*spanish*/ "#pescar a la leyenda# conduce a" }, - }, - {}, - // clear text - Text{ "#fishing the hyrule loach# will give you", /*french*/ "!!!", - /*spanish*/ "si #pescas a la Locha de Hyrule# encontrarás" }); - - - hintTable[RHT_LH_ADULT_FISHING] = HintText::Exclude({ - //obscure text - Text{"#fishing in maturity# bestows", /*french*/"#pêcher dans sa maturité# promet", /*spanish*/"#pescar en la madurez# conduce a"}, - }); - - hintTable[RHT_LH_LAB_DIVE] = HintText::Exclude({ - //obscure text - Text{"a #diving experiment# is rewarded with", /*french*/"l'#expérience de plongée# donne", /*spanish*/"#bucear para un experimento# se premia con"}, - }); - - // TODO: needs translation - hintTable[RHT_ZD_FISH] = HintText::Exclude({ - // obscure text - Text{"a #fish by a waterfall# hoards", /*french*/"", /*spanish*/""} - }); - - hintTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText::Exclude({ - //obscure text - Text{"#comforting yourself# provides", /*french*/"se #réconforter soi-même# donne", /*spanish*/"#confrontarte a ti mismo# otorga"}, - }, {}, - //clear text - Text{"#reassuring a young Goron# is rewarded with", /*french*/"#rassurer un jeune Goron# donne", /*spanish*/"#calmar a un joven Goron# otorga"} - ); - - hintTable[RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = HintText::Exclude({ - //obscure text - Text{"the #first explosive prize# is", /*french*/"le #premier prix explosif# est", /*spanish*/"el #primer premio explosivo# se trata de"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = HintText::Exclude({ - //obscure text - Text{"the #second explosive prize# is", /*french*/"le #deuxième prix explosif# est", /*spanish*/"el #segundo premio explosivo# se trata de"}, - }); - - hintTable[RHT_MARKET_LOST_DOG] = HintText::Exclude({ - //obscure text - Text{"#puppy lovers# will find", /*french*/"les #amoureux canins# trouveront", /*spanish*/"los #amantes caninos# encontrarán"}, - }, {}, - //clear text - Text{"#rescuing Richard the Dog# is rewarded with", /*french*/"#retrouver Kiki le chien# promet", /*spanish*/"#rescatar al perrito Ricardo# conduce a"} - ); - - hintTable[RHT_LW_OCARINA_MEMORY_GAME] = HintText::Exclude({ - //obscure text - Text{"the prize for a #game of Simon Says# is", /*french*/"la #récompense de Jean Dit# est", /*spanish*/"#repetir ciertas melodías# otorga"}, - Text{"a #child sing-a-long# holds", /*french*/"les #jeunes flûtistes# donnent", /*spanish*/"#tocar junto a otros# otorga"}, - }, {}, - //clear text - Text{"#playing an Ocarina in Lost Woods# is rewarded with", /*french*/"#jouer l'ocarina dans les Bois Perdus# donne", /*spanish*/"#tocar la ocarina en el Bosque Perdido# otorga"} - ); - - hintTable[RHT_KAK_10_GOLD_SKULLTULA_REWARD] = HintText::Exclude({ - //obscure text - Text{"#10 bug badges# rewards", /*french*/"#10 écussons# donnent", /*spanish*/"#10 medallas de insectos# otorgan"}, - Text{"#10 spider souls# yields", /*french*/"#10 âmes# donnent", /*spanish*/"#10 almas de araña# otorgan"}, - Text{"#10 auriferous arachnids# lead to", /*french*/"#10 arachnides aurifères# donnent", /*spanish*/"#10 arácnidos auríferos# otorgan"}, - }, {}, - //clear text - Text{"slaying #10 Gold Skulltulas# reveals", /*french*/"détruire #10 Skulltulas d'or# donne", /*spanish*/"#exterminar 10 skulltulas doradas# revela"} - ); - - hintTable[RHT_KAK_MAN_ON_ROOF] = HintText::Exclude({ - //obscure text - Text{"a #rooftop wanderer# holds", /*french*/"une #rencontre sur un toit# donne", /*spanish*/"#alguien sobre un tejado# otorga"}, - }); - - hintTable[RHT_ZR_MAGIC_BEAN_SALESMAN] = HintText::Exclude({ - //obscure text - Text{"a seller of #colorful crops# has", /*french*/"le #marchand de légumes# vend", /*spanish*/"el vendedor de un #colorido cultivo# ofrece"}, - }, {}, - //clear text - Text{"a #bean seller# offers", /*french*/"le #marchand de haricots magiques# vend en fait", /*spanish*/"el #vendedor de judías# ofrece"} - ); - - hintTable[RHT_ZR_FROGS_IN_THE_RAIN] = HintText::Exclude({ - //obscure text - Text{"#frogs in a storm# gift", /*french*/"#des grenouilles mouillées# donnent", /*spanish*/"las #ancas bajo la tormenta# otorgan"}, - }); - hintTable[RHT_ZR_FROGS_ZELDAS_LULLABY] = HintText::Exclude( - { - // obscure text - Text{ "#sleepy frogs# gift", /*french*/ "#les grenouilles somnolentes# donnent", - /*spanish*/ "las #ranas somnolientas# regalan" }, - Text{ "#the Froggish Tenor in the back-left# gifts", - /*french*/ "#le ténor grenouillesque au fond à gauche# donne", - /*spanish*/ "el #Sapo Tenore al fondo, a la izquierda#, regala" }, - }, - {}, - // clear text - Text{ "after hearing #Zelda's Lullaby, the frogs# gift", - /*french*/ "à l'écoute de #la berceuse de Zelda, les grenouilles# donnent", - /*spanish*/ "después de escuchar #la Nana de Zelda, las ranas# regalan" }); - - hintTable[RHT_ZR_FROGS_EPONAS_SONG] = HintText::Exclude( - { - // obscure text - Text{ "#equine frogs# gift", /*french*/ "#les grenouilles équestres# donnent", - /*spanish*/ "las #ranas equinas# regalan" }, - Text{ "#the Froggish Tenor in the back-right# gifts", - /*french*/ "#le ténor grenouillesque au fond à droite# donne", - /*spanish*/ "el #Sapo Tenore al fondo, a la derecha#, regala" }, - }, - {}, - // clear text - Text{ "after hearing #Epona's Song, the frogs# gift", - /*french*/ "à l'écoute du #chant d'Epona, les grenouilles# donnent", - /*spanish*/ "después de escuchar #la Canción de Epona, las ranas# regalan" }); - - hintTable[RHT_ZR_FROGS_SARIAS_SONG] = HintText::Exclude( - { - // obscure text - Text{ "#sylvan frogs# gift", /*french*/ "#les grenouilles sylvestres# donnent", - /*spanish*/ "las #ranas silvestres# regalan" }, - Text{ "#the Froggish Tenor in the center# gifts", - /*french*/ "#le ténor grenouillesque dans le centre# donne", - /*spanish*/ "el #Sapo Tenore en el centro# regala" }, - }, - {}, - // clear text - Text{ "after hearing #Saria's Song, the frogs# gift", - /*french*/ "à l'écoute du #chant de Saria, les grenouilles# donnent", - /*spanish*/ "después de escuchar #la Canción de Saria, las ranas# regalan" }); - - hintTable[RHT_ZR_FROGS_SUNS_SONG] = HintText::Exclude( - { - // obscure text - Text{ "#enlightened frogs# gift", /*french*/ "#les grenouilles éclairées# donnent", - /*spanish*/ "las #ranas alumbradas# regalan" }, - Text{ "#the Froggish Tenor in the front-left# gifts", - /*french*/ "#le ténor grenouillesque à l'avant gauche# donne", - /*spanish*/ "el #Sapo Tenore al frente, a la izquierda#, regala" }, - }, - {}, - // clear text - Text{ "after hearing #the Sun's Song, the frogs# gift", - /*french*/ "à l'écoute du #chant du soleil, les grenouilles# donnent", - /*spanish*/ "después de escuchar #la Canción del Sol, las ranas# regalan" }); - - hintTable[RHT_ZR_FROGS_SONG_OF_TIME] = HintText::Exclude( - { - // obscure text - Text{ "#time-traveling frogs# gift", /*french*/ "#les grenouilles voyageuses dans le temps# donnent", - /*spanish*/ "las #ranas viajeras del tiempo# regalan" }, - Text{ "#the Froggish Tenor in the front-right# gifts", - /*french*/ "#le ténor grenouillesque à l'avant droite# donne", - /*spanish*/ "el #Sapo Tenore al frente, a la derecha#, regala" }, - }, - {}, - // clear text - Text{ "after hearing #the Song of Time, the frogs# gift", - /*french*/ "à l'écoute du #chant du temps, les grenouilles# donnent", - /*spanish*/ "después de escuchar #la Canción del tiempo, las ranas# regalan" }); - - hintTable[RHT_GF_HBA_1000_POINTS] = HintText::Exclude({ - //obscure text - Text{"scoring 1000 in #horseback archery# grants", /*french*/"obtenir 1000 points dans l'#archerie équestre# donne", /*spanish*/"conseguir 1000 puntos en el #tiro con arco a caballo# premia"}, - }); - - hintTable[RHT_MARKET_SHOOTING_GALLERY_REWARD] = HintText::Exclude({ - //obscure text - Text{"#shooting in youth# grants", /*french*/"#faire du tir dans sa jeunesse# donne", /*spanish*/"#disparar en la juventud# otorga"}, - }); - - hintTable[RHT_KAK_SHOOTING_GALLERY_REWARD] = HintText::Exclude({ - //obscure text - Text{"#shooting in maturity# grants", /*french*/"#faire du tir dans sa maturité# donne", /*spanish*/"#disparar en la madurez# otorga"}, - }); - - hintTable[RHT_LW_TARGET_IN_WOODS] = HintText::Exclude({ - //obscure text - Text{"shooting a #target in the woods# grants", /*french*/"#tirer une cible dans les bois# donne", /*spanish*/"disparar a un #blanco forestal# brinda"}, - }); - - hintTable[RHT_KAK_ANJU_AS_ADULT] = HintText::Exclude({ - //obscure text - Text{"a #chicken caretaker# offers adults", /*french*/"devenir un #éleveur de Cocottes# donne", /*spanish*/"una #cuidadora de emplumados# le ofrece a los mayores"}, - }); - - hintTable[RHT_LLR_TALONS_CHICKENS] = HintText::Exclude({ - //obscure text - Text{"#finding Super Cuccos# is rewarded with", /*french*/"#trouver des Super Cocottes# donne", /*spanish*/"#hallar los supercucos# conduce a"}, - }); - - hintTable[RHT_GC_ROLLING_GORON_AS_CHILD] = HintText::Exclude({ - //obscure text - Text{"the prize offered by a #large rolling Goron# is", /*french*/"la récompense d'un #gros Goron roulant# est", /*spanish*/"un #gran Goron rodante# otorga"}, - }); - - hintTable[RHT_LH_UNDERWATER_ITEM] = HintText::Exclude({ - //obscure text - Text{"the #sunken treasure in a lake# is", /*french*/"le #trésor au fond du lac# est", /*spanish*/"el #tesoro hundido del lago# se trata de"}, - }); - - hintTable[RHT_GF_GERUDO_MEMBERSHIP_CARD] = HintText::Exclude({ - //obscure text - Text{"#rescuing captured carpenters# is rewarded with", /*french*/"#secourir les charpentiers capturés# assure", /*spanish*/"#rescatar los apresados carpinteros# se premia con"}, - }); - - hintTable[RHT_WASTELAND_BOMBCHU_SALESMAN] = HintText::Exclude({ - //obscure text - Text{"a #carpet guru# sells", /*french*/"#un marchand du désert# vend", /*spanish*/"el #genio de una alfombra# vende"}, - }); - - hintTable[RHT_GC_MEDIGORON] = HintText::Exclude({ - //obscure text - Text{"#Medigoron# sells", /*french*/"#Medigoron# vend", /*spanish*/"#Medigoron# vende"}, - }); - - hintTable[RHT_KAK_GRANNYS_SHOP] = HintText::Exclude({ - // obscure text - Text{"the #potion shop lady# sells", /*french*/"la #dame du magasin de potion# vend", /*spanish*/"la #señora de la tienda de pociones# vende" }, - }); - - hintTable[RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"#imprisoned in a house# lies", /*french*/"#encagé dans une maison# gît", /*spanish*/"#en una casa entre rejas# yace"}, - }); - - hintTable[RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"#deep underwater in a hole# is", /*french*/"#dans les profondeurs d'une grotte# gît", /*spanish*/"#en lo hondo bajo un hoyo# yace"}, - }); - - hintTable[RHT_KAK_WINDMILL_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"on a #windmill ledge# lies", /*french*/"#haut perché dans le moulin# gît", /*spanish*/"al #borde de un molino# yace"}, - }); - - hintTable[RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"#racing a ghost# leads to", /*french*/"le défi du #revenant rapide# donne", /*spanish*/"#perseguir a un fantasma# conduce a"}, - }, {}, - //clear text - Text{"#dead Dampe's second# prize is", /*french*/"la #deuxième course d'Igor# donne", /*spanish*/"el segundo premio de #la carrera de Dampé# se trata de"} - ); - - hintTable[RHT_LLR_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"in a #ranch silo# lies", /*french*/"#dans l'entrepôt de la ferme# gît", /*spanish*/"en un #granero rupestre# yace"}, - }); - - hintTable[RHT_GRAVEYARD_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"a #crate in a graveyard# hides", /*french*/"#la boîte dans le Cimetière# contient", /*spanish*/"bajo la #caja de un cementerio# yace"}, - }); - - hintTable[RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = HintText::Exclude({ - //obscure text - Text{"a #gravekeeper digs up#", /*french*/"#le jeu du fossoyeur# cache", /*spanish*/"cierto #sepultero desentierra#"}, - }); - - hintTable[RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"on top of a #pillar in a river# lies", /*french*/"#sur un pilier au dessus du fleuve# gît", /*spanish*/"en lo alto del #pilar de un río# yace"}, - }); - - hintTable[RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"on a #river ledge by a waterfall# lies", /*french*/"#sur la falaise au dessus du fleuve# gît", /*spanish*/"al borde de #la entrada a una cascada# yace"}, - }); - - hintTable[RHT_LH_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"high on a #lab rooftop# one can find", /*french*/"#la tour d'observation du lac# cache", /*spanish*/"en lo #alto de un laboratorio# yace"}, - }); - - hintTable[RHT_ZF_ICEBERG_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"#floating on ice# is", /*french*/"#gisant sur la glace# gît", /*spanish*/"#flotando sobre hielo# yace"}, - }); - - hintTable[RHT_GV_WATERFALL_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"behind a #valley waterfall# is", /*french*/"#derrière la cascade du désert# se cache", /*spanish*/"tras una #desierta cascada# yace"}, - }); - - hintTable[RHT_GV_CRATE_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"a #crate in a valley# hides", /*french*/"la #boîte dans la vallée# contient", /*spanish*/"bajo la #caja de un valle# yace"}, - }); - - hintTable[RHT_COLOSSUS_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"on top of an #arch of stone# lies", /*french*/"#gisant sur une arche de pierre# gît", /*spanish*/"en lo alto de un #arco de piedra# yace"}, - }); - - hintTable[RHT_DMT_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"above a #mountain cavern entrance# is", /*french*/"gisant #au dessus de la caverne montagneuse# gît", /*spanish*/"en lo alto de la #entrada de una cueva en la montaña# yace"}, - }); - - hintTable[RHT_DMC_WALL_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"nestled in a #volcanic wall# is", /*french*/"dans une #alcove volcanique# gît", /*spanish*/"entre unas #murallas volcánicas# yace"}, - }); - - hintTable[RHT_DMC_VOLCANO_FREESTANDING_POH] = HintText::Exclude({ - //obscure text - Text{"obscured by #volcanic ash# is", /*french*/"#recouvert de cendres volcaniques# gît", /*spanish*/"bajo la #ceniza volcánica# yace"}, - }); - - hintTable[RHT_GF_NORTH_F1_CARPENTER] = HintText::Exclude({ - //obscure text - Text{"#defeating Gerudo guards# reveals", /*french*/"les #geôliers Gerudo# détiennent", /*spanish*/"#derrotar a las guardas Gerudo# revela"}, - }); - - hintTable[RHT_GF_NORTH_F2_CARPENTER] = HintText::Exclude({ - //obscure text - Text{"#defeating Gerudo guards# reveals", /*french*/"les #geôliers Gerudo# détiennent", /*spanish*/"#derrotar a las guardas Gerudo# revela"}, - }); - - hintTable[RHT_GF_SOUTH_F1_CARPENTER] = HintText::Exclude({ - //obscure text - Text{"#defeating Gerudo guards# reveals", /*french*/"les #geôliers Gerudo# détiennent", /*spanish*/"#derrotar a las guardas Gerudo# revela"}, - }); - - hintTable[RHT_GF_SOUTH_F2_CARPENTER] = HintText::Exclude({ - //obscure text - Text{"#defeating Gerudo guards# reveals", /*french*/"les #geôliers Gerudo# détiennent", /*spanish*/"#derrotar a las guardas Gerudo# revela"}, - }); - - - hintTable[RHT_HF_GS_NEAR_KAK_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #spider-guarded spider in a hole# hoards", /*french*/"une #Skulltula dans un trou d'arachnides# a", /*spanish*/"una #Skulltula custodiada por otra# de un hoyo otorga"}, - }); - - - hintTable[RHT_LLR_GS_BACK_WALL] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a ranch# holding", /*french*/"une #Skulltula sur la façade de la ferme# a", /*spanish*/"la noche revela una #Skulltula del rancho# que otorga"}, - }); - - hintTable[RHT_LLR_GS_RAIN_SHED] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a ranch# holding", /*french*/"une #Skulltula sur le mur de l'enclos# a", /*spanish*/"la noche revela una #Skulltula del rancho# que otorga"}, - }); - - hintTable[RHT_LLR_GS_HOUSE_WINDOW] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a ranch# holding", /*french*/"une #Skulltula sur la maison de ferme# a", /*spanish*/"la noche revela una #Skulltula del rancho# que otorga"}, - }); - - hintTable[RHT_LLR_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"a spider hiding in a #ranch tree# holds", /*french*/"une #Skulltula dans l'arbre de la ferme# a", /*spanish*/"una Skulltula escondida en el #árbol de un rancho# otorga"}, - }); - - - hintTable[RHT_KF_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried in a forest# holds", /*french*/"une #Skulltula enterrée dans la forêt# a", /*spanish*/"una #Skulltula enterrada en un bosque# otorga"}, - }); - - hintTable[RHT_KF_GS_KNOW_IT_ALL_HOUSE] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a forest# holding", /*french*/"une #Skulltula derrière une cabane de la forêt# a", /*spanish*/"la noche revela en el pasado una #Skulltula del bosque# que otorga"}, - }); - - hintTable[RHT_KF_GS_HOUSE_OF_TWINS] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a forest# holding", /*french*/"une #Skulltula sur une cabane de la forêt# a", /*spanish*/"la noche revela en el futuro una #Skulltula del rancho# que otorga"}, - }); - - - hintTable[RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = HintText::Exclude({ - //obscure text - Text{"a #spider buried deep in a forest maze# holds", /*french*/"une #Skulltula enterrée dans les bois# a", /*spanish*/"una #Skulltula enterrada en un laberinto forestal# otorga"}, - }); - - hintTable[RHT_LW_GS_BEAN_PATCH_NEAR_THEATER] = HintText::Exclude({ - //obscure text - Text{"a #spider buried deep in a forest maze# holds", /*french*/"une #Skulltula enterrée dans les bois# a", /*spanish*/"una #Skulltula enterrada en un laberinto forestal# otorga"}, - }); - - hintTable[RHT_LW_GS_ABOVE_THEATER] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider deep in a forest maze# holding", /*french*/"une #Skulltula haut perchée dans les bois# a", /*spanish*/"la noche revela una #Skulltula del laberinto forestal# que otorga"}, - }); - - hintTable[RHT_SFM_GS] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a forest meadow# holding", /*french*/"une #Skulltula dans le sanctuaire des bois# a", /*spanish*/"la noche revela una #Skulltula de la pradera del bosque# que otorga"}, - }); - - - hintTable[RHT_OGC_GS] = HintText::Exclude({ - //obscure text - Text{"a #spider outside a tyrant's tower# holds", /*french*/"une #Skulltula parmi les ruines du château# a", /*spanish*/"una #Skulltula a las afueras de la torre de un tirano# otorga"}, - }); - - hintTable[RHT_HC_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"a spider hiding in a #tree outside of a castle# holds", /*french*/"une #Skulltula dans l'arbre près du château# a", /*spanish*/"una Skulltula escondida en el #árbol de las afueras de un castillo# otorga"}, - }); - - hintTable[RHT_MARKET_GS_GUARD_HOUSE] = HintText::Exclude({ - //obscure text - Text{"a #spider in a guarded crate# holds", /*french*/"une #Skulltula dans une boîte en ville# a", /*spanish*/"una #Skulltula bajo una custodiada caja# otorga"}, - }); - - - hintTable[RHT_DMC_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried in a volcano# holds", /*french*/"une #Skulltula enterrée dans un volcan# a", /*spanish*/"una #Skulltula enterrada en un volcán# otorga"}, - }); - - - hintTable[RHT_DMT_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried outside a cavern# holds", /*french*/"une #Skulltula enterrée près d'une caverne# a", /*spanish*/"una #Skulltula enterrada a la entrada de una cueva# otorga"}, - }); - - hintTable[RHT_DMT_GS_NEAR_KAK] = HintText::Exclude({ - //obscure text - Text{"a #spider hidden in a mountain nook# holds", /*french*/"une #Skulltula cachée dans le flanc d'une montagne# a", /*spanish*/"una #Skulltula oculta en el rincón de la montaña# otorga"}, - }); - - hintTable[RHT_DMT_GS_ABOVE_DODONGOS_CAVERN] = HintText::Exclude({ - //obscure text - Text{"the hammer reveals a #spider on a mountain# holding", /*french*/"une #Skulltula derrière un rocher massif près d'une caverne# a", /*spanish*/"el martillo revela #una Skulltula de la montaña# que otorga"}, - }); - - hintTable[RHT_DMT_GS_FALLING_ROCKS_PATH] = HintText::Exclude({ - //obscure text - Text{"the hammer reveals a #spider on a mountain# holding", /*french*/"une #Skulltula derrière un rocher massif près du sommet d'un volcan# a", /*spanish*/"el martillo revela #una Skulltula de la montaña# que otorga"}, - }); - - - hintTable[RHT_GC_GS_CENTER_PLATFORM] = HintText::Exclude({ - //obscure text - Text{"a #suspended spider# in Goron City holds", /*french*/"une #Skulltula perchée dans le village Goron# a", /*spanish*/"una #Skulltula suspendida# en la Ciudad Goron otorga"}, - }); - - hintTable[RHT_GC_GS_BOULDER_MAZE] = HintText::Exclude({ - //obscure text - Text{"a spider in a #Goron City crate# holds", /*french*/"une #Skulltula dans une boîte du village Goron# a", /*spanish*/"una #Skulltula bajo una caja# de la Ciudad Goron otorga"}, - }); - - - hintTable[RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a town# holding", /*french*/"une #Skulltula dans le chantier de construction# a", /*spanish*/"la noche del pasado revela una #Skulltula del pueblo# que otorga"}, - }); - - hintTable[RHT_KAK_GS_SKULLTULA_HOUSE] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a town# holding", /*french*/"une #Skulltula sur une maison maudite# a", /*spanish*/"la noche del pasado revela una #Skulltula del pueblo# que otorga"}, - }); - - hintTable[RHT_KAK_GS_GUARDS_HOUSE] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a town# holding", /*french*/"une #Skulltula sur une maison de village# a", /*spanish*/"la noche del pasado revela una #Skulltula del pueblo# que otorga"}, - }); - - hintTable[RHT_KAK_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a town# holding", /*french*/"une #Skulltula dans un arbre de village# a", /*spanish*/"la noche del pasado revela una #Skulltula del pueblo# que otorga"}, - }); - - hintTable[RHT_KAK_GS_WATCHTOWER] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a town# holding", /*french*/"une #Skulltula sur une échelle dans un village# a", /*spanish*/"la noche del pasado revela una #Skulltula del pueblo# que otorga"}, - }); - - hintTable[RHT_KAK_GS_ABOVE_IMPAS_HOUSE] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a town# holding", /*french*/"une #Skulltula au dessus d'une grande maison# a", /*spanish*/"la noche del futuro revela una #Skulltula del pueblo# que otorga"}, - }); - - - hintTable[RHT_GRAVEYARD_GS_WALL] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a graveyard# holding", /*french*/"une #Skulltula sur une façade du Cimetière# a", /*spanish*/"la noche revela una #Skulltula del cementerio# que otorga"}, - }); - - hintTable[RHT_GRAVEYARD_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried in a graveyard# holds", /*french*/"une #Skulltula enterrée dans le Cimetière# a", /*spanish*/"una #Skulltula enterrada en el cementerio# otorga"}, - }); - - - hintTable[RHT_ZR_GS_LADDER] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a river# holding", /*french*/"une #Skulltula sur une échelle près d'une cascade# a", /*spanish*/"la noche del pasado revela una #Skulltula del río# que otorga"}, - }); - - hintTable[RHT_ZR_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"a spider hiding in a #tree by a river# holds", /*french*/"une #Skulltula dans un arbre près du fleuve# a", /*spanish*/"una Skulltula escondida en el #árbol de un río# otorga"}, - }); - - hintTable[RHT_ZR_GS_ABOVE_BRIDGE] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a river# holding", /*french*/"une #Skulltula sur une façade près d'une cascade# a", /*spanish*/"la noche del futuro revela una #Skulltula del río# que otorga"}, - }); - - hintTable[RHT_ZR_GS_NEAR_RAISED_GROTTOS] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a river# holding", /*french*/"une #Skulltula sur une façade près d'une grotte du fleuve# a", /*spanish*/"la noche del futuro revela una #Skulltula del río# que otorga"}, - }); - - - hintTable[RHT_ZD_GS_FROZEN_WATERFALL] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider by a frozen waterfall# holding", /*french*/"une #Skulltula près d'une cascade gelée# a", /*spanish*/"la noche revela una #Skulltula junto a una congelada cascada# que otorga"}, - }); - - hintTable[RHT_ZF_GS_ABOVE_THE_LOG] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider near a deity# holding", /*french*/"une #Skulltula près du gardien aquatique# a", /*spanish*/"la noche revela una #Skulltula junto a cierta deidad# que otorga"}, - }); - - hintTable[RHT_ZF_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"a spider hiding in a #tree near a deity# holds", /*french*/"une #Skulltula dans un arbre dans un réservoir# a", /*spanish*/"una Skulltula escondida en el #árbol junto a cierta deidad# otorga"}, - }); - - - hintTable[RHT_LH_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried by a lake# holds", /*french*/"une #Skulltula enterrée près d'un lac# a", /*spanish*/"una #Skulltula enterrada junto a un lago# otorga"}, - }); - - hintTable[RHT_LH_GS_SMALL_ISLAND] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider by a lake# holding", /*french*/"une #Skulltula sur un îlot du lac# a", /*spanish*/"la noche revela una #Skulltula junto a un lago# que otorga"}, - }); - - hintTable[RHT_LH_GS_LAB_WALL] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider by a lake# holding", /*french*/"une #Skulltula sur le mur d'un centre de recherche# a", /*spanish*/"la noche revela una #Skulltula junto a un lago# que otorga"}, - }); - - hintTable[RHT_LH_GS_LAB_CRATE] = HintText::Exclude({ - //obscure text - Text{"a spider deed underwater in a #lab crate# holds", /*french*/"une #Skulltula dans une boîte au fond d'une cuve d'eau# a", /*spanish*/"una #Skulltula bajo la sumergida caja de un laboratorio# otorga"}, - }); - - hintTable[RHT_LH_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider by a lake high in a tree# holding", /*french*/"une #Skulltula dans un grand arbre du lac# a", /*spanish*/"la noche revela #una Skulltula del lago sobre un árbol# que otorga"}, - }); - - - hintTable[RHT_GV_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried in a valley# holds", /*french*/"une #Skulltula enterré dans une vallée# a", /*spanish*/"una #Skulltula enterrada en un valle# otorga"}, - }); - - hintTable[RHT_GV_GS_SMALL_BRIDGE] = HintText::Exclude({ - //obscure text - Text{"night in the past reveals a #spider in a valley# holding", /*french*/"une #Skulltula au dessus d'une petite cascade# a", /*spanish*/"la noche del pasado revela una #Skulltula del valle# que otorga"}, - }); - - hintTable[RHT_GV_GS_PILLAR] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a valley# holding", /*french*/"une #Skulltula sur une arche de pierre dans une vallée# a", /*spanish*/"la noche del futuro revela una #Skulltula del valle# que otorga"}, - }); - - hintTable[RHT_GV_GS_BEHIND_TENT] = HintText::Exclude({ - //obscure text - Text{"night in the future reveals a #spider in a valley# holding", /*french*/"une #Skulltula derrière une tente# a", /*spanish*/"la noche del futuro revela una #Skulltula del valle# que otorga"}, - }); - - - hintTable[RHT_GF_GS_ARCHERY_RANGE] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a fortress# holding", /*french*/"une #Skulltula sur une cible de tir# a", /*spanish*/"la noche revela una #Skulltula de una fortaleza# que otorga"}, - }); - - hintTable[RHT_GF_GS_TOP_FLOOR] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider in a fortress# holding", /*french*/"une #Skulltula au sommet d'une forteresse# a", /*spanish*/"la noche revela una #Skulltula de una fortaleza# que otorga"}, - }); - - - hintTable[RHT_COLOSSUS_GS_BEAN_PATCH] = HintText::Exclude({ - //obscure text - Text{"a #spider buried in the desert# holds", /*french*/"une #Skulltula enterrée au pied du colosse# a", /*spanish*/"una #Skulltula enterrada en el desierto# otorga"}, - }); - - hintTable[RHT_COLOSSUS_GS_HILL] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider deep in the desert# holding", /*french*/"une #Skulltula sur une colline dans le désert# a", /*spanish*/"la noche revela una #Skulltula en las profundidades del desierto# que otorga"}, - }); - - hintTable[RHT_COLOSSUS_GS_TREE] = HintText::Exclude({ - //obscure text - Text{"night reveals a #spider deep in the desert# holding", /*french*/"une #Skulltula dans un arbre du désert# a", /*spanish*/"la noche revela una #Skulltula en las profundidades del desierto# que otorga"}, - }); - - - hintTable[RHT_KF_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - hintTable[RHT_KF_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #child shopkeeper# sells", /*french*/"la #boutique Kokiri# vend", /*spanish*/"un #joven dependiente# vende"}, - }); - - - hintTable[RHT_KAK_POTION_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - hintTable[RHT_KAK_POTION_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Kakariko Potion Shop# offers", /*french*/"l'#apothicaire de Kakariko# vend", /*spanish*/"la #tienda de pociones de Kakariko# ofrece"} - ); - - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - hintTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #Bombchu merchant# sells", /*french*/"le #marchand de Missiles# vend", /*spanish*/"un #mercader de bombchus# vende"}, - }); - - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - hintTable[RHT_MARKET_POTION_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #potion seller# offers", /*french*/"l'#apothicaire# vend", /*spanish*/"un #vendedor de pociones# ofrece"}, - }, {}, - //clear text - Text{"the #Market Potion Shop# offers", /*french*/"l'#apothicaire dans la Place du Marché# vend", /*spanish*/"la #tienda de pociones del mercado# ofrece"} - ); - - - hintTable[RHT_MARKET_BAZAAR_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - hintTable[RHT_MARKET_BAZAAR_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"the #Market Bazaar# offers", /*french*/"le #bazar de la Place du Marché# vend", /*spanish*/"el #bazar del mercado# ofrece"}, - }); - - - hintTable[RHT_KAK_BAZAAR_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - hintTable[RHT_KAK_BAZAAR_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"the #Kakariko Bazaar# offers", /*french*/"le #bazar de Kakariko# vend", /*spanish*/"el #bazar de Kakariko# ofrece"}, - }); - - - hintTable[RHT_ZD_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - hintTable[RHT_ZD_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #Zora shopkeeper# sells", /*french*/"la #boutique Zora# vend", /*spanish*/"el #dependiente Zora# vende"}, - }); - - - hintTable[RHT_GC_SHOP_ITEM_1] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_2] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_3] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_4] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_5] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_6] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_7] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - hintTable[RHT_GC_SHOP_ITEM_8] = HintText::Exclude({ - //obscure text - Text{"a #Goron shopkeeper# sells", /*french*/"la #boutique Goron# vend", /*spanish*/"el #dependiente Goron# vende"}, - }); - - - hintTable[RHT_HF_DEKU_SCRUB_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a lonely #scrub in a hole# sells", /*french*/"la #peste Mojo dans une grotte de la plaine# vend", /*spanish*/"un #singular deku bajo un hoyo# de la llanura vende"}, - }); - - hintTable[RHT_LLR_DEKU_SCRUB_GROTTO_LEFT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo à la ferme# vend", /*spanish*/"un #trío de dekus# de una granja venden"}, - }); - - hintTable[RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo à la ferme# vend", /*spanish*/"un #trío de dekus# de una granja venden"}, - }); - - hintTable[RHT_LLR_DEKU_SCRUB_GROTTO_CENTER] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo à la ferme# vend", /*spanish*/"un #trío de dekus# de una granja venden"}, - }); - - - hintTable[RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in the woods# sells", /*french*/"le #duo de peste Mojo près du théâtre# vend", /*spanish*/"un par de #dekus del bosque# venden"}, - }); - - hintTable[RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = HintText::Exclude({ - //obscure text - Text{"a pair of #scrubs in the woods# sells", /*french*/"le #duo de peste Mojo près du théâtre# vend", /*spanish*/"un par de #dekus del bosque# venden"}, - }); - - hintTable[RHT_LW_DEKU_SCRUB_NEAR_BRIDGE] = HintText::Exclude({ - //obscure text - Text{"a #scrub by a bridge# sells", /*french*/"la #peste Mojo près du pont dans les bois# vend", /*spanish*/"un #deku bajo un puente# del bosque venden"}, - }); - - hintTable[RHT_LW_DEKU_SCRUB_GROTTO_REAR] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo dans les sous-bois# vend", /*spanish*/"un #par de dekus subterráneos# del bosque venden"}, - }); - - hintTable[RHT_LW_DEKU_SCRUB_GROTTO_FRONT] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo dans les sous-bois# vend", /*spanish*/"un #par de dekus subterráneos# del bosque venden"}, - }); - - - hintTable[RHT_SFM_DEKU_SCRUB_GROTTO_REAR] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo au cœur du sanctuaire sylvestre# vend", /*spanish*/"un #par de dekus subterráneos# de la pradera sagrada venden"}, - }); - - hintTable[RHT_SFM_DEKU_SCRUB_GROTTO_FRONT] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo au cœur du sanctuaire sylvestre# vend", /*spanish*/"un #par de dekus subterráneos# de la pradera sagrada venden"}, - }); - - - hintTable[RHT_GC_DEKU_SCRUB_GROTTO_LEFT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le village Goron# vend", /*spanish*/"un #trío de dekus# de la Ciudad Goron venden"}, - }); - - hintTable[RHT_GC_DEKU_SCRUB_GROTTO_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le village Goron# vend", /*spanish*/"un #trío de dekus# de la Ciudad Goron venden"}, - }); - - hintTable[RHT_GC_DEKU_SCRUB_GROTTO_CENTER] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le village Goron# vend", /*spanish*/"un #trío de dekus# de la Ciudad Goron venden"}, - }); - - - hintTable[RHT_DMC_DEKU_SCRUB_GROTTO_LEFT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le volcan# vend", /*spanish*/"un #trío de dekus# del volcán venden"}, - }); - - hintTable[RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le volcan# vend", /*spanish*/"un #trío de dekus# del volcán venden"}, - }); - - hintTable[RHT_DMC_DEKU_SCRUB_GROTTO_CENTER] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo dans le volcan# vend", /*spanish*/"un #trío de dekus# del volcán venden"}, - }); - - - hintTable[RHT_ZR_DEKU_SCRUB_GROTTO_REAR] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo près du fleuve# vend", /*spanish*/"un #par de dekus subterráneos# del río venden"}, - }); - - hintTable[RHT_ZR_DEKU_SCRUB_GROTTO_FRONT] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo près du fleuve# vend", /*spanish*/"un #par de dekus subterráneos# del río venden"}, - }); - - - hintTable[RHT_LH_DEKU_SCRUB_GROTTO_LEFT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo près du lac# vend", /*spanish*/"un #trío de dekus# del lago venden"}, - }); - - hintTable[RHT_LH_DEKU_SCRUB_GROTTO_RIGHT] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo près du lac# vend", /*spanish*/"un #trío de dekus# del lago venden"}, - }); - - hintTable[RHT_LH_DEKU_SCRUB_GROTTO_CENTER] = HintText::Exclude({ - //obscure text - Text{"a #trio of scrubs# sells", /*french*/"le #trio de peste Mojo près du lac# vend", /*spanish*/"un #trío de dekus# del lago venden"}, - }); - - - hintTable[RHT_GV_DEKU_SCRUB_GROTTO_REAR] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo près de la vallée# vend", /*spanish*/"un #par de dekus subterráneos# del valle venden"}, - }); - - hintTable[RHT_GV_DEKU_SCRUB_GROTTO_FRONT] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo près de la vallée# vend", /*spanish*/"un #par de dekus subterráneos# del valle venden"}, - }); - - - hintTable[RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo dans le désert# vend", /*spanish*/"un #par de dekus subterráneos# del desierto venden"}, - }); - - hintTable[RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = HintText::Exclude({ - //obscure text - Text{"a #scrub underground duo# sells", /*french*/"le #duo de peste Mojo dans le désert# vend", /*spanish*/"un #par de dekus subterráneos# del desierto venden"}, - }); - - - hintTable[RHT_LLR_STABLES_LEFT_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow in a stable# gifts", /*french*/"la #vache dans l'étable# donne", /*spanish*/"una #vaca del establo# brinda"}, - }); - - hintTable[RHT_LLR_STABLES_RIGHT_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow in a stable# gifts", /*french*/"la #vache dans l'étable# donne", /*spanish*/"una #vaca del establo# brinda"}, - }); - - hintTable[RHT_LLR_TOWER_RIGHT_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow in a ranch silo# gifts", /*french*/"la #vache dans le silo de la ferme# donne", /*spanish*/"una #vaca del granero# brinda"}, - }); - - hintTable[RHT_LLR_TOWER_LEFT_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow in a ranch silo# gifts", /*french*/"la #vache dans le silo de la ferme# donne", /*spanish*/"una #vaca del granero# brinda"}, - }); - - hintTable[RHT_KAK_IMPAS_HOUSE_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow imprisoned in a house# protects", /*french*/"la #vache en cage# donne", /*spanish*/"una #vaca enjaulada de una casa# brinda"}, - }); - - hintTable[RHT_DMT_COW_GROTTO_COW] = HintText::Exclude({ - //obscure text - Text{"a #cow in a luxurious hole# offers", /*french*/"la #vache dans une grotte luxueuse# donne", /*spanish*/"una #vaca de un lujoso hoyo# brinda"}, - }); - - hintTable[RHT_BEEHIVE_CHEST_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #beehive above a chest# hides", /*french*/"", /*spanish*/"una #colmena sobre un cofre# esconde"}, - }); - - hintTable[RHT_BEEHIVE_LONELY_SCRUB_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #beehive above a lonely scrub# hides", /*french*/"", /*spanish*/"una #colmena sobre un deku solitario# esconde"}, - }); - - hintTable[RHT_BEEHIVE_SCRUB_PAIR_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #beehive above a pair of scrubs# hides", /*french*/"", /*spanish*/"una #colmena sobre un par de dekus# esconde"}, - }); - - hintTable[RHT_BEEHIVE_SCRUB_TRIO_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #beehive above a trio of scrubs# hides", /*french*/"", /*spanish*/"una #colmena sobre un trío de dekus# esconde"}, - }); - - hintTable[RHT_BEEHIVE_COW_GROTTO] = HintText::Exclude({ - //obscure text - Text{"a #beehive above a cow# hides", /*french*/"", /*spanish*/"una #colmena sobre una vaca# esconde"}, - }); - - hintTable[RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA] = HintText::Exclude({ - //obscure text - Text{"a #beehive in front of the king of the zoras# hides", /*french*/"", /*spanish*/"una #colmena delante del rey de los zoras# esconde"}, - }); - - hintTable[RHT_BEEHIVE_BEHIND_KING_ZORA] = HintText::Exclude({ - //obscure text - Text{"a #beehive behind the king of the zoras# hides", /*french*/"", /*spanish*/"una #colmena detrás del rey de los zoras# esconde"}, - }); +#include "../../static_data.h" +#include "../hints.hpp" +#include "../../../custom-message/CustomMessageManager.h" + +namespace Rando { +void StaticData::HintTable_Init_Exclude_Overworld() { + + hintTextTable[RHT_KF_KOKIRI_SWORD_CHEST] = HintText(CustomMessage("They say that the #hidden treasure of the Kokiri# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor des Kokiri# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #tesoro oculto de los Kokiri# esconde #[[1]]#. + + hintTextTable[RHT_KF_MIDOS_TOP_LEFT_CHEST] = HintText(CustomMessage("They say that #inside Mido's house# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans la maison de Mido# gît #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, en la #casa de Mido# yace #[[1]]#. + {}, { + CustomMessage("They say that the #leader of the Kokiri# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chef des Kokiri# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #líder de los Kokiri# esconde #[[1]]#. + + hintTextTable[RHT_KF_MIDOS_TOP_RIGHT_CHEST] = HintText(CustomMessage("They say that #inside Mido's house# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans la maison de Mido# gît #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, en la #casa de Mido# yace #[[1]]#. + {}, { + CustomMessage("They say that the #leader of the Kokiri# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chef des Kokiri# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #líder de los Kokiri# esconde #[[1]]#. + + hintTextTable[RHT_KF_MIDOS_BOTTOM_LEFT_CHEST] = HintText(CustomMessage("They say that #inside Mido's house# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans la maison de Mido# gît #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, en la #casa de Mido# yace #[[1]]#. + {}, { + CustomMessage("They say that the #leader of the Kokiri# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chef des Kokiri# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #líder de los Kokiri# esconde #[[1]]#. + + hintTextTable[RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST] = HintText(CustomMessage("They say that #inside Mido's house# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans la maison de Mido# gît #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, en la #casa de Mido# yace #[[1]]#. + {}, { + CustomMessage("They say that the #leader of the Kokiri# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #chef des Kokiri# possède #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #líder de los Kokiri# esconde #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_SHIELD_GRAVE_CHEST] = HintText(CustomMessage("They say that the #treasure of a fallen soldier# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor du soldat mort# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #tesoro de un soldado caído# esconde #[[1]]#. + + hintTextTable[RHT_DMT_CHEST] = HintText(CustomMessage("They say that hidden behind a wall on a #mountain trail# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, derrière une façade du #chemin montagneux# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras una pared del #sendero de la montaña# yace #[[1]]#. + + hintTextTable[RHT_GC_MAZE_RIGHT_CHEST] = HintText(CustomMessage("They say that in #Goron City# explosives unlock #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des explosions dans le #village Goron# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en la #Ciudad Goron# unos explosivos desbloquean #[[1]]#. + + hintTextTable[RHT_GC_MAZE_CENTER_CHEST] = HintText(CustomMessage("They say that in #Goron City# explosives unlock #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, des explosions dans le #village Goron# révèlent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en la #Ciudad Goron# unos explosivos desbloquean #[[1]]#. + + hintTextTable[RHT_ZD_CHEST] = HintText(CustomMessage("They say that fire #beyond a waterfall# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, du feu #derrière la cascade# éclaire #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #llamas tras una una cascada# revelan #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_HOOKSHOT_CHEST] = HintText(CustomMessage("They say that #dead Dampé's first prize# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #première course d'Igor# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el primer premio de #la carrera de Dampé# se trata de #[[1]]#. + {}, { + CustomMessage("They say that a chest hidden by a #speedy spectre# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #coffre du rapide revenant# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un cofre custodiado por un #espectro veloz# contiene #[[1]]#. + + hintTextTable[RHT_GF_CHEST] = HintText(CustomMessage("They say that on a #rooftop in the desert# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, sur un #toit du désert# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en una #azotea del desierto# yace #[[1]]#. + + hintTextTable[RHT_KAK_REDEAD_GROTTO_CHEST] = HintText(CustomMessage("They say that #zombies beneath the earth# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #revenants sous terre# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #zombis subterráneos# esconden #[[1]]#. + + hintTextTable[RHT_SFM_WOLFOS_GROTTO_CHEST] = HintText(CustomMessage("They say that #wolves beneath the earth# guard #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #loups sous terre# protègent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, unos #lobos subterráneos# esconden #[[1]]#. + + hintTextTable[RHT_HF_NEAR_MARKET_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole in a field near a drawbridge# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près d'un pont# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una llanura cercano a un puente# yace #[[1]]#. + + hintTextTable[RHT_HF_NEAR_MARKET_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole in a field near a drawbridge# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près d'un pont# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una llanura cercano a un puente# yace #[[1]]#. + + hintTextTable[RHT_HF_SOUTHEAST_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole amongst trees in a field# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près des arbres# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una llanura rodeado de árboles# yace #[[1]]#. + + hintTextTable[RHT_HF_SOUTHEAST_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole amongst trees in a field# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près des arbres# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una llanura rodeado de árboles# yace #[[1]]#. + + hintTextTable[RHT_HF_OPEN_GROTTO_CHEST] = HintText(CustomMessage("They say that an #open hole in a field# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans les plaines# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo descubierto de una llanura# yace #[[1]]#. + + hintTextTable[RHT_HF_OPEN_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in an open hole in a field# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans les plaines# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo descubierto de una llanura# yace #[[1]]#. + + hintTextTable[RHT_KAK_OPEN_GROTTO_CHEST] = HintText(CustomMessage("They say that an #open hole in a town# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le village# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo descubierto de un pueblo# yace #[[1]]#. + + hintTextTable[RHT_KAK_OPEN_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in an open hole in a town# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le village# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo descubierto de un pueblo# yace #[[1]]#. + + hintTextTable[RHT_ZR_OPEN_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole along a river# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près du fleuve# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo junto a un río# yace #[[1]]#. + + hintTextTable[RHT_ZR_OPEN_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole along a river# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte près du fleuve# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo junto a un río# yace #[[1]]#. + + hintTextTable[RHT_KF_STORMS_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole in a forest village# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte inondée de pluie dans le Village Kokiri# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una tribu del bosque# yace #[[1]]#. + + hintTextTable[RHT_KF_STORMS_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole in a forest village# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte inondée de pluie dans le Village Kokiri# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de una tribu del bosque# yace #[[1]]#. + + hintTextTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole in a wooded maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le labyrinthe sylvestre# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo de un laberinto forestal# yace #[[1]]#. + + hintTextTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole in a wooded maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le labyrinthe sylvestre# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo de un laberinto forestal# yace #[[1]]#. + + hintTextTable[RHT_DMT_STORMS_GROTTO_CHEST] = HintText(CustomMessage("They say that #hole flooded with rain on a mountain# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte inondée de pluie sur la montagne# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo de una montaña inundado de lluvia# yace #[[1]]#. + + hintTextTable[RHT_DMT_STORMS_GROTTO_FISH] = HintText(CustomMessage("They say that #fish in a hole flooded with rain on a mountain# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte inondée de pluie sur la montagne# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo un #hoyo de una montaña inundado de lluvia# yace #[[1]]#. + + hintTextTable[RHT_DMC_UPPER_GROTTO_CHEST] = HintText(CustomMessage("They say that a #hole in a volcano# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le volcan# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de un volcán# yace #[[1]]#. + + hintTextTable[RHT_DMC_UPPER_GROTTO_FISH] = HintText(CustomMessage("They say that a #fish in a hole in a volcano# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #grotte dans le volcan# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo el #hoyo de un volcán# yace #[[1]]#. + + hintTextTable[RHT_TOT_MASTER_SWORD] = HintText(CustomMessage("They say that a #pedestal in a temple# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #piédestal dans un temple# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #pedestal en un templo# sostiene #[[1]]#. + + hintTextTable[RHT_TOT_LIGHT_ARROWS_CUTSCENE] = HintText(CustomMessage("They say that the #final gift of a princess# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #cadeau d'adieu de la princesse# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #obsequio final de la princesa# se trata de #[[1]]#. + + hintTextTable[RHT_LW_GIFT_FROM_SARIA] = HintText(CustomMessage("They say that #Saria's Gift# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #cadeau de Saria# est #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el #regalo de Saria# se trata de #[[1]]#. + {}, { + CustomMessage("They say that a #potato hoarder# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #panini mélodieux# est en fait #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, cierta #jovencita verde# concede #[[1]]#. + CustomMessage("They say that a rooty tooty #flutey cutey# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #patate musicale# est en fait #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, una #gran amiga# concede #[[1]]#. + + hintTextTable[RHT_ZF_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that the #fairy of winds# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée du vent# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #hada del viento# brinda #[[1]]#. + + hintTextTable[RHT_HC_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that the #fairy of fire# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée du feu# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #hada del fuego# brinda #[[1]]#. + + hintTextTable[RHT_COLOSSUS_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that the #fairy of love# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée de l'amour# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #hada del amor# brinda #[[1]]#. + + hintTextTable[RHT_DMT_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that a #magical fairy# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée de la magie# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #hada mágica# brinda #[[1]]#. + + hintTextTable[RHT_DMC_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that a #magical fairy# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée de la magie# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #hada mágica# brinda #[[1]]#. + + hintTextTable[RHT_OGC_GREAT_FAIRY_REWARD] = HintText(CustomMessage("They say that the #fairy of strength# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fée de la force# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #hada de la fuerza# brinda #[[1]]#. + + hintTextTable[RHT_SONG_FROM_IMPA] = HintText(CustomMessage("They say that #deep in a castle#, Impa teaches #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #la gardienne de la princesse# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en el #jardín del castillo Impa enseña# #[[1]]#. + + hintTextTable[RHT_SONG_FROM_MALON] = HintText(CustomMessage("They say that #a farm girl# sings #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fillette de la ferme# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #chica rupestre# canta #[[1]]#. + + hintTextTable[RHT_SONG_FROM_SARIA] = HintText(CustomMessage("They say that #deep in the forest#, Saria teaches #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fille de la forêt# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al #fondo del bosque# Saria enseña #[[1]]#. + + hintTextTable[RHT_SONG_FROM_WINDMILL] = HintText(CustomMessage("They say that a man #in a windmill# is obsessed with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#homme du moulin# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #hombre del molino# está obsesionado con #[[1]]#. + + hintTextTable[RHT_HC_MALON_EGG] = HintText(CustomMessage("They say that a #girl looking for her father# gives #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #fillette qui cherche son père# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #chica en busca de su padre# otorga #[[1]]#. + + hintTextTable[RHT_HC_ZELDAS_LETTER] = HintText(CustomMessage("They say that a #princess in a castle# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #princesse dans le château# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #princesa de un castillo# otorga #[[1]]#. + + hintTextTable[RHT_ZD_DIVING_MINIGAME] = HintText(CustomMessage("They say that those who #dive for Zora rupees# will find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, ceux qui #plongent pour des rubis Zora# trouveront #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, aquellos que se #sumergan por las rupias zora# encontrarán #[[1]]#. + {}, { + CustomMessage("They say that an #unsustainable business model# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #mauvais modèle d'affaires# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #mal modelo de negocio# premia con #[[1]]#. + + hintTextTable[RHT_LH_CHILD_FISHING] = HintText(CustomMessage("They say that #fishing in youth# bestows #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #pêcher dans sa jeunesse# promet #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #pescar en la juventud# conduce a #[[1]]#. + + hintTextTable[RHT_LH_POND_FISH] = HintText(CustomMessage("They say that #hitting the pond# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_LH_HYRULE_LOACH] = HintText(CustomMessage("They say that #fishing the hyrule loach# will give you #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, !!! #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, si #pescas a la Locha de Hyrule# encontrarás #[[1]]#. + {}, { + CustomMessage("They say that #fishing the legend# bestows #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, !!! #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #pescar a la leyenda# conduce a #[[1]]#. + + hintTextTable[RHT_LH_ADULT_FISHING] = HintText(CustomMessage("They say that #fishing in maturity# bestows #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #pêcher dans sa maturité# promet #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #pescar en la madurez# conduce a #[[1]]#. + + hintTextTable[RHT_LH_LAB_DIVE] = HintText(CustomMessage("They say that a #diving experiment# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#expérience de plongée# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #bucear para un experimento# se premia con #[[1]]#. + // RANDOTODO: needs translation + hintTextTable[RHT_ZD_FISH] = HintText(CustomMessage("They say that a #fish by a waterfall# hoards #[[1]]#.", {QM_RED, QM_GREEN})); + + + hintTextTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText(CustomMessage("They say that #reassuring a young Goron# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #rassurer un jeune Goron# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #calmar a un joven Goron# otorga #[[1]]#. + {}, { + CustomMessage("They say that #comforting yourself# provides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, se #réconforter soi-même# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #confrontarte a ti mismo# otorga #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = HintText(CustomMessage("They say that the #first explosive prize# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #premier prix explosif# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #primer premio explosivo# se trata de #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = HintText(CustomMessage("They say that the #second explosive prize# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #deuxième prix explosif# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #segundo premio explosivo# se trata de #[[1]]#. + + hintTextTable[RHT_MARKET_LOST_DOG] = HintText(CustomMessage("They say that #rescuing Richard the Dog# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #retrouver Kiki le chien# promet #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #rescatar al perrito Ricardo# conduce a #[[1]]#. + {}, { + CustomMessage("They say that #puppy lovers# will find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #amoureux canins# trouveront #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, los #amantes caninos# encontrarán #[[1]]#. + + hintTextTable[RHT_LW_OCARINA_MEMORY_GAME] = HintText(CustomMessage("They say that #playing an Ocarina in Lost Woods# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #jouer l'ocarina dans les Bois Perdus# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #tocar la ocarina en el Bosque Perdido# otorga #[[1]]#. + {}, { + CustomMessage("They say that the prize for a #game of Simon Says# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #récompense de Jean Dit# est #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #repetir ciertas melodías# otorga #[[1]]#. + CustomMessage("They say that a #child sing-a-long# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #jeunes flûtistes# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #tocar junto a otros# otorga #[[1]]#. + + hintTextTable[RHT_KAK_10_GOLD_SKULLTULA_REWARD] = HintText(CustomMessage("They say that slaying #10 Gold Skulltulas# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, détruire #10 Skulltulas d'or# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #exterminar 10 skulltulas doradas# revela #[[1]]#. + {}, { + CustomMessage("They say that #10 bug badges# rewards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #10 écussons# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #10 medallas de insectos# otorgan #[[1]]#. + CustomMessage("They say that #10 spider souls# yields #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #10 âmes# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, #10 almas de araña# otorgan #[[1]]#. + CustomMessage("They say that #10 auriferous arachnids# lead to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #10 arachnides aurifères# donnent #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #10 arácnidos auríferos# otorgan #[[1]]#. + + hintTextTable[RHT_KAK_MAN_ON_ROOF] = HintText(CustomMessage("They say that a #rooftop wanderer# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #rencontre sur un toit# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #alguien sobre un tejado# otorga #[[1]]#. + + hintTextTable[RHT_ZR_MAGIC_BEAN_SALESMAN] = HintText(CustomMessage("They say that a #bean seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de haricots magiques# vend en fait #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el #vendedor de judías# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a seller of #colorful crops# has #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de légumes# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el vendedor de un #colorido cultivo# ofrece #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_IN_THE_RAIN] = HintText(CustomMessage("They say that #frogs in a storm# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #des grenouilles mouillées# donnent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, las #ancas bajo la tormenta# otorgan #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_ZELDAS_LULLABY] = HintText(CustomMessage("They say that after hearing #Zelda's Lullaby, the frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, à l'écoute de #la berceuse de Zelda, les grenouilles# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, después de escuchar #la Nana de Zelda, las ranas# regalan #[[1]]#. + {}, { + CustomMessage("They say that #sleepy frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les grenouilles somnolentes# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, las #ranas somnolientas# regalan #[[1]]#. + CustomMessage("They say that #the Froggish Tenor in the back-left# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le ténor grenouillesque au fond à gauche# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Sapo Tenore al fondo, a la izquierda#, regala #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_EPONAS_SONG] = HintText(CustomMessage("They say that after hearing #Epona's Song, the frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, à l'écoute du #chant d'Epona, les grenouilles# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, después de escuchar #la Canción de Epona, las ranas# regalan #[[1]]#. + {}, { + CustomMessage("They say that #equine frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les grenouilles équestres# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, las #ranas equinas# regalan #[[1]]#. + CustomMessage("They say that #the Froggish Tenor in the back-right# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le ténor grenouillesque au fond à droite# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Sapo Tenore al fondo, a la derecha#, regala #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_SARIAS_SONG] = HintText(CustomMessage("They say that after hearing #Saria's Song, the frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, à l'écoute du #chant de Saria, les grenouilles# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, después de escuchar #la Canción de Saria, las ranas# regalan #[[1]]#. + {}, { + CustomMessage("They say that #sylvan frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les grenouilles sylvestres# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, las #ranas silvestres# regalan #[[1]]#. + CustomMessage("They say that #the Froggish Tenor in the center# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le ténor grenouillesque dans le centre# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Sapo Tenore en el centro# regala #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_SUNS_SONG] = HintText(CustomMessage("They say that after hearing #the Sun's Song, the frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, à l'écoute du #chant du soleil, les grenouilles# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, después de escuchar #la Canción del Sol, las ranas# regalan #[[1]]#. + {}, { + CustomMessage("They say that #enlightened frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les grenouilles éclairées# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, las #ranas alumbradas# regalan #[[1]]#. + CustomMessage("They say that #the Froggish Tenor in the front-left# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le ténor grenouillesque à l'avant gauche# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Sapo Tenore al frente, a la izquierda#, regala #[[1]]#. + + hintTextTable[RHT_ZR_FROGS_SONG_OF_TIME] = HintText(CustomMessage("They say that after hearing #the Song of Time, the frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, à l'écoute du #chant du temps, les grenouilles# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, después de escuchar #la Canción del tiempo, las ranas# regalan #[[1]]#. + {}, { + CustomMessage("They say that #time-traveling frogs# gift #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #les grenouilles voyageuses dans le temps# donnent #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, las #ranas viajeras del tiempo# regalan #[[1]]#. + CustomMessage("They say that #the Froggish Tenor in the front-right# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le ténor grenouillesque à l'avant droite# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, el #Sapo Tenore al frente, a la derecha#, regala #[[1]]#. + + hintTextTable[RHT_GF_HBA_1000_POINTS] = HintText(CustomMessage("They say that scoring 1000 in #horseback archery# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, obtenir 1000 points dans l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, conseguir 1000 puntos en el #tiro con arco a caballo# premia #[[1]]#. + + hintTextTable[RHT_MARKET_SHOOTING_GALLERY_REWARD] = HintText(CustomMessage("They say that #shooting in youth# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #faire du tir dans sa jeunesse# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #disparar en la juventud# otorga #[[1]]#. + + hintTextTable[RHT_KAK_SHOOTING_GALLERY_REWARD] = HintText(CustomMessage("They say that #shooting in maturity# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #faire du tir dans sa maturité# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #disparar en la madurez# otorga #[[1]]#. + + hintTextTable[RHT_LW_TARGET_IN_WOODS] = HintText(CustomMessage("They say that shooting a #target in the woods# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #tirer une cible dans les bois# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, disparar a un #blanco forestal# brinda #[[1]]#. + + hintTextTable[RHT_KAK_ANJU_AS_ADULT] = HintText(CustomMessage("They say that a #chicken caretaker# offers adults #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, devenir un #éleveur de Cocottes# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #cuidadora de emplumados# le ofrece a los mayores #[[1]]#. + + hintTextTable[RHT_LLR_TALONS_CHICKENS] = HintText(CustomMessage("They say that #finding Super Cuccos# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #trouver des Super Cocottes# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #hallar los supercucos# conduce a #[[1]]#. + + hintTextTable[RHT_GC_ROLLING_GORON_AS_CHILD] = HintText(CustomMessage("They say that the prize offered by a #large rolling Goron# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la récompense d'un #gros Goron roulant# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #gran Goron rodante# otorga #[[1]]#. + + hintTextTable[RHT_LH_UNDERWATER_ITEM] = HintText(CustomMessage("They say that the #sunken treasure in a lake# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trésor au fond du lac# est #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #tesoro hundido del lago# se trata de #[[1]]#. + + hintTextTable[RHT_GF_GERUDO_MEMBERSHIP_CARD] = HintText(CustomMessage("They say that #rescuing captured carpenters# is rewarded with #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #secourir les charpentiers capturés# assure #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #rescatar los apresados carpinteros# se premia con #[[1]]#. + + hintTextTable[RHT_WASTELAND_BOMBCHU_SALESMAN] = HintText(CustomMessage("They say that a #carpet guru# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #un marchand du désert# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #genio de una alfombra# vende #[[1]]#. + + hintTextTable[RHT_GC_MEDIGORON] = HintText(CustomMessage("They say that #Medigoron# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #Medigoron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #Medigoron# vende #[[1]]#. + + hintTextTable[RHT_KAK_GRANNYS_SHOP] = HintText(CustomMessage("They say that the #potion shop lady# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #dame du magasin de potion# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la #señora de la tienda de pociones# vende #[[1]]#. + + hintTextTable[RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH] = HintText(CustomMessage("They say that #imprisoned in a house# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #encagé dans une maison# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #en una casa entre rejas# yace #[[1]]#. + + hintTextTable[RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH] = HintText(CustomMessage("They say that #deep underwater in a hole# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans les profondeurs d'une grotte# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #en lo hondo bajo un hoyo# yace #[[1]]#. + + hintTextTable[RHT_KAK_WINDMILL_FREESTANDING_POH] = HintText(CustomMessage("They say that on a #windmill ledge# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #haut perché dans le moulin# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al #borde de un molino# yace #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = HintText(CustomMessage("They say that #dead Dampe's second# prize is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #deuxième course d'Igor# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, el segundo premio de #la carrera de Dampé# se trata de #[[1]]#. + {}, { + CustomMessage("They say that #racing a ghost# leads to #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le défi du #revenant rapide# donne #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, #perseguir a un fantasma# conduce a #[[1]]#. + + hintTextTable[RHT_LLR_FREESTANDING_POH] = HintText(CustomMessage("They say that in a #ranch silo# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #dans l'entrepôt de la ferme# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en un #granero rupestre# yace #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_FREESTANDING_POH] = HintText(CustomMessage("They say that a #crate in a graveyard# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #la boîte dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo la #caja de un cementerio# yace #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = HintText(CustomMessage("They say that a #gravekeeper digs up# #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #le jeu du fossoyeur# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, cierto #sepultero desentierra# #[[1]]#. + + hintTextTable[RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = HintText(CustomMessage("They say that on top of a #pillar in a river# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #sur un pilier au dessus du fleuve# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo alto del #pilar de un río# yace #[[1]]#. + + hintTextTable[RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH] = HintText(CustomMessage("They say that on a #river ledge by a waterfall# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #sur la falaise au dessus du fleuve# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, al borde de #la entrada a una cascada# yace #[[1]]#. + + hintTextTable[RHT_LH_FREESTANDING_POH] = HintText(CustomMessage("They say that high on a #lab rooftop# one can find #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #la tour d'observation du lac# cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo #alto de un laboratorio# yace #[[1]]#. + + hintTextTable[RHT_ZF_ICEBERG_FREESTANDING_POH] = HintText(CustomMessage("They say that #floating on ice# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #gisant sur la glace# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #flotando sobre hielo# yace #[[1]]#. + + hintTextTable[RHT_GV_WATERFALL_FREESTANDING_POH] = HintText(CustomMessage("They say that behind a #valley waterfall# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #derrière la cascade du désert# se cache #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, tras una #desierta cascada# yace #[[1]]#. + + hintTextTable[RHT_GV_CRATE_FREESTANDING_POH] = HintText(CustomMessage("They say that a #crate in a valley# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boîte dans la vallée# contient #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo la #caja de un valle# yace #[[1]]#. + + hintTextTable[RHT_COLOSSUS_FREESTANDING_POH] = HintText(CustomMessage("They say that on top of an #arch of stone# lies #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #gisant sur une arche de pierre# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo alto de un #arco de piedra# yace #[[1]]#. + + hintTextTable[RHT_DMT_FREESTANDING_POH] = HintText(CustomMessage("They say that above a #mountain cavern entrance# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, gisant #au dessus de la caverne montagneuse# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, en lo alto de la #entrada de una cueva en la montaña# yace #[[1]]#. + + hintTextTable[RHT_DMC_WALL_FREESTANDING_POH] = HintText(CustomMessage("They say that nestled in a #volcanic wall# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, dans une #alcove volcanique# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, entre unas #murallas volcánicas# yace #[[1]]#. + + hintTextTable[RHT_DMC_VOLCANO_FREESTANDING_POH] = HintText(CustomMessage("They say that obscured by #volcanic ash# is #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #recouvert de cendres volcaniques# gît #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, bajo la #ceniza volcánica# yace #[[1]]#. + + hintTextTable[RHT_GF_NORTH_F1_CARPENTER] = HintText(CustomMessage("They say that #defeating Gerudo guards# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #geôliers Gerudo# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar a las guardas Gerudo# revela #[[1]]#. + + hintTextTable[RHT_GF_NORTH_F2_CARPENTER] = HintText(CustomMessage("They say that #defeating Gerudo guards# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #geôliers Gerudo# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar a las guardas Gerudo# revela #[[1]]#. + + hintTextTable[RHT_GF_SOUTH_F1_CARPENTER] = HintText(CustomMessage("They say that #defeating Gerudo guards# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #geôliers Gerudo# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar a las guardas Gerudo# revela #[[1]]#. + + hintTextTable[RHT_GF_SOUTH_F2_CARPENTER] = HintText(CustomMessage("They say that #defeating Gerudo guards# reveals #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, les #geôliers Gerudo# détiennent #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, #derrotar a las guardas Gerudo# revela #[[1]]#. + + hintTextTable[RHT_HF_GS_NEAR_KAK_GROTTO] = HintText(CustomMessage("They say that a #spider-guarded spider in a hole# hoards #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un trou d'arachnides# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula custodiada por otra# de un hoyo otorga #[[1]]#. + + hintTextTable[RHT_LLR_GS_BACK_WALL] = HintText(CustomMessage("They say that night reveals a #spider in a ranch# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur la façade de la ferme# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula del rancho# que otorga #[[1]]#. + + hintTextTable[RHT_LLR_GS_RAIN_SHED] = HintText(CustomMessage("They say that night reveals a #spider in a ranch# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur le mur de l'enclos# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula del rancho# que otorga #[[1]]#. + + hintTextTable[RHT_LLR_GS_HOUSE_WINDOW] = HintText(CustomMessage("They say that night reveals a #spider in a ranch# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur la maison de ferme# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula del rancho# que otorga #[[1]]#. + + hintTextTable[RHT_LLR_GS_TREE] = HintText(CustomMessage("They say that a spider hiding in a #ranch tree# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans l'arbre de la ferme# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una Skulltula escondida en el #árbol de un rancho# otorga #[[1]]#. + + hintTextTable[RHT_KF_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried in a forest# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée dans la forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en un bosque# otorga #[[1]]#. + + hintTextTable[RHT_KF_GS_KNOW_IT_ALL_HOUSE] = HintText(CustomMessage("They say that night in the past reveals a #spider in a forest# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une cabane de la forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela en el pasado una #Skulltula del bosque# que otorga #[[1]]#. + + hintTextTable[RHT_KF_GS_HOUSE_OF_TWINS] = HintText(CustomMessage("They say that night in the future reveals a #spider in a forest# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une cabane de la forêt# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela en el futuro una #Skulltula del rancho# que otorga #[[1]]#. + + hintTextTable[RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = HintText(CustomMessage("They say that a #spider buried deep in a forest maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée dans les bois# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en un laberinto forestal# otorga #[[1]]#. + + hintTextTable[RHT_LW_GS_BEAN_PATCH_NEAR_THEATER] = HintText(CustomMessage("They say that a #spider buried deep in a forest maze# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée dans les bois# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en un laberinto forestal# otorga #[[1]]#. + + hintTextTable[RHT_LW_GS_ABOVE_THEATER] = HintText(CustomMessage("They say that night reveals a #spider deep in a forest maze# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula haut perchée dans les bois# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula del laberinto forestal# que otorga #[[1]]#. + + hintTextTable[RHT_SFM_GS] = HintText(CustomMessage("They say that night reveals a #spider in a forest meadow# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans le sanctuaire des bois# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula de la pradera del bosque# que otorga #[[1]]#. + + hintTextTable[RHT_OGC_GS] = HintText(CustomMessage("They say that a #spider outside a tyrant's tower# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula parmi les ruines du château# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula a las afueras de la torre de un tirano# otorga #[[1]]#. + + hintTextTable[RHT_HC_GS_TREE] = HintText(CustomMessage("They say that a spider hiding in a #tree outside of a castle# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans l'arbre près du château# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una Skulltula escondida en el #árbol de las afueras de un castillo# otorga #[[1]]#. + + hintTextTable[RHT_MARKET_GS_GUARD_HOUSE] = HintText(CustomMessage("They say that a #spider in a guarded crate# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une boîte en ville# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo una custodiada caja# otorga #[[1]]#. + + hintTextTable[RHT_DMC_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried in a volcano# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée dans un volcan# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en un volcán# otorga #[[1]]#. + + hintTextTable[RHT_DMT_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried outside a cavern# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée près d'une caverne# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada a la entrada de una cueva# otorga #[[1]]#. + + hintTextTable[RHT_DMT_GS_NEAR_KAK] = HintText(CustomMessage("They say that a #spider hidden in a mountain nook# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula cachée dans le flanc d'une montagne# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula oculta en el rincón de la montaña# otorga #[[1]]#. + + hintTextTable[RHT_DMT_GS_ABOVE_DODONGOS_CAVERN] = HintText(CustomMessage("They say that the hammer reveals a #spider on a mountain# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière un rocher massif près d'une caverne# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el martillo revela #una Skulltula de la montaña# que otorga #[[1]]#. + + hintTextTable[RHT_DMT_GS_FALLING_ROCKS_PATH] = HintText(CustomMessage("They say that the hammer reveals a #spider on a mountain# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière un rocher massif près du sommet d'un volcan# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el martillo revela #una Skulltula de la montaña# que otorga #[[1]]#. + + hintTextTable[RHT_GC_GS_CENTER_PLATFORM] = HintText(CustomMessage("They say that a #suspended spider# in Goron City holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula perchée dans le village Goron# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula suspendida# en la Ciudad Goron otorga #[[1]]#. + + hintTextTable[RHT_GC_GS_BOULDER_MAZE] = HintText(CustomMessage("They say that a spider in a #Goron City crate# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une boîte du village Goron# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo una caja# de la Ciudad Goron otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = HintText(CustomMessage("They say that night in the past reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans le chantier de construction# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_SKULLTULA_HOUSE] = HintText(CustomMessage("They say that night in the past reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une maison maudite# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_GUARDS_HOUSE] = HintText(CustomMessage("They say that night in the past reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une maison de village# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_TREE] = HintText(CustomMessage("They say that night in the past reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un arbre de village# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_WATCHTOWER] = HintText(CustomMessage("They say that night in the past reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une échelle dans un village# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_KAK_GS_ABOVE_IMPAS_HOUSE] = HintText(CustomMessage("They say that night in the future reveals a #spider in a town# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'une grande maison# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del futuro revela una #Skulltula del pueblo# que otorga #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_GS_WALL] = HintText(CustomMessage("They say that night reveals a #spider in a graveyard# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une façade du Cimetière# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula del cementerio# que otorga #[[1]]#. + + hintTextTable[RHT_GRAVEYARD_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried in a graveyard# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée dans le Cimetière# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en el cementerio# otorga #[[1]]#. + + hintTextTable[RHT_ZR_GS_LADDER] = HintText(CustomMessage("They say that night in the past reveals a #spider in a river# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une échelle près d'une cascade# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del río# que otorga #[[1]]#. + + hintTextTable[RHT_ZR_GS_TREE] = HintText(CustomMessage("They say that a spider hiding in a #tree by a river# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un arbre près du fleuve# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una Skulltula escondida en el #árbol de un río# otorga #[[1]]#. + + hintTextTable[RHT_ZR_GS_ABOVE_BRIDGE] = HintText(CustomMessage("They say that night in the future reveals a #spider in a river# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une façade près d'une cascade# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del futuro revela una #Skulltula del río# que otorga #[[1]]#. + + hintTextTable[RHT_ZR_GS_NEAR_RAISED_GROTTOS] = HintText(CustomMessage("They say that night in the future reveals a #spider in a river# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une façade près d'une grotte du fleuve# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del futuro revela una #Skulltula del río# que otorga #[[1]]#. + + hintTextTable[RHT_ZD_GS_FROZEN_WATERFALL] = HintText(CustomMessage("They say that night reveals a #spider by a frozen waterfall# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près d'une cascade gelée# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula junto a una congelada cascada# que otorga #[[1]]#. + + hintTextTable[RHT_ZF_GS_ABOVE_THE_LOG] = HintText(CustomMessage("They say that night reveals a #spider near a deity# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula près du gardien aquatique# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula junto a cierta deidad# que otorga #[[1]]#. + + hintTextTable[RHT_ZF_GS_TREE] = HintText(CustomMessage("They say that a spider hiding in a #tree near a deity# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un arbre dans un réservoir# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una Skulltula escondida en el #árbol junto a cierta deidad# otorga #[[1]]#. + + hintTextTable[RHT_LH_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried by a lake# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée près d'un lac# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada junto a un lago# otorga #[[1]]#. + + hintTextTable[RHT_LH_GS_SMALL_ISLAND] = HintText(CustomMessage("They say that night reveals a #spider by a lake# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur un îlot du lac# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula junto a un lago# que otorga #[[1]]#. + + hintTextTable[RHT_LH_GS_LAB_WALL] = HintText(CustomMessage("They say that night reveals a #spider by a lake# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur le mur d'un centre de recherche# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula junto a un lago# que otorga #[[1]]#. + + hintTextTable[RHT_LH_GS_LAB_CRATE] = HintText(CustomMessage("They say that a spider deed underwater in a #lab crate# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans une boîte au fond d'une cuve d'eau# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula bajo la sumergida caja de un laboratorio# otorga #[[1]]#. + + hintTextTable[RHT_LH_GS_TREE] = HintText(CustomMessage("They say that night reveals a #spider by a lake high in a tree# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un grand arbre du lac# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela #una Skulltula del lago sobre un árbol# que otorga #[[1]]#. + + hintTextTable[RHT_GV_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried in a valley# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterré dans une vallée# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en un valle# otorga #[[1]]#. + + hintTextTable[RHT_GV_GS_SMALL_BRIDGE] = HintText(CustomMessage("They say that night in the past reveals a #spider in a valley# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au dessus d'une petite cascade# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del pasado revela una #Skulltula del valle# que otorga #[[1]]#. + + hintTextTable[RHT_GV_GS_PILLAR] = HintText(CustomMessage("They say that night in the future reveals a #spider in a valley# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une arche de pierre dans une vallée# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del futuro revela una #Skulltula del valle# que otorga #[[1]]#. + + hintTextTable[RHT_GV_GS_BEHIND_TENT] = HintText(CustomMessage("They say that night in the future reveals a #spider in a valley# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula derrière une tente# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche del futuro revela una #Skulltula del valle# que otorga #[[1]]#. + + hintTextTable[RHT_GF_GS_ARCHERY_RANGE] = HintText(CustomMessage("They say that night reveals a #spider in a fortress# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une cible de tir# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula de una fortaleza# que otorga #[[1]]#. + + hintTextTable[RHT_GF_GS_TOP_FLOOR] = HintText(CustomMessage("They say that night reveals a #spider in a fortress# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula au sommet d'une forteresse# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula de una fortaleza# que otorga #[[1]]#. + + hintTextTable[RHT_COLOSSUS_GS_BEAN_PATCH] = HintText(CustomMessage("They say that a #spider buried in the desert# holds #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula enterrée au pied du colosse# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #Skulltula enterrada en el desierto# otorga #[[1]]#. + + hintTextTable[RHT_COLOSSUS_GS_HILL] = HintText(CustomMessage("They say that night reveals a #spider deep in the desert# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula sur une colline dans le désert# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula en las profundidades del desierto# que otorga #[[1]]#. + + hintTextTable[RHT_COLOSSUS_GS_TREE] = HintText(CustomMessage("They say that night reveals a #spider deep in the desert# holding #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #Skulltula dans un arbre du désert# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, la noche revela una #Skulltula en las profundidades del desierto# que otorga #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_1] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_2] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_3] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_4] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_5] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_6] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_7] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KF_SHOP_ITEM_8] = HintText(CustomMessage("They say that a #child shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Kokiri# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #joven dependiente# vende #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_1] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_2] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_3] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_4] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_5] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_6] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_7] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_POTION_SHOP_ITEM_8] = HintText(CustomMessage("They say that the #Kakariko Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones de Kakariko# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_1] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_2] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_3] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_4] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_5] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_6] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_7] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_BOMBCHU_SHOP_ITEM_8] = HintText(CustomMessage("They say that a #Bombchu merchant# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #marchand de Missiles# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #mercader de bombchus# vende #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_1] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_2] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_3] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_4] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_5] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_6] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_7] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_POTION_SHOP_ITEM_8] = HintText(CustomMessage("They say that the #Market Potion Shop# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire dans la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/ Según dicen, la #tienda de pociones del mercado# ofrece #[[1]]#. + {}, { + CustomMessage("They say that a #potion seller# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, l'#apothicaire# vend #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/ Según dicen, un #vendedor de pociones# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_1] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_2] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_3] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_4] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_5] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_6] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_7] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_MARKET_BAZAAR_ITEM_8] = HintText(CustomMessage("They say that the #Market Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de la Place du Marché# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar del mercado# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_1] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_2] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_3] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_4] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_5] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_6] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_7] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_KAK_BAZAAR_ITEM_8] = HintText(CustomMessage("They say that the #Kakariko Bazaar# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #bazar de Kakariko# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #bazar de Kakariko# ofrece #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_1] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_2] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_3] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_4] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_5] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_6] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_7] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_ZD_SHOP_ITEM_8] = HintText(CustomMessage("They say that a #Zora shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Zora# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Zora# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_1] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_2] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_3] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_4] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_5] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_6] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_7] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_GC_SHOP_ITEM_8] = HintText(CustomMessage("They say that a #Goron shopkeeper# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #boutique Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, el #dependiente Goron# vende #[[1]]#. + + hintTextTable[RHT_HF_DEKU_SCRUB_GROTTO] = HintText(CustomMessage("They say that a lonely #scrub in a hole# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo dans une grotte de la plaine# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #singular deku bajo un hoyo# de la llanura vende #[[1]]#. + + hintTextTable[RHT_LLR_DEKU_SCRUB_GROTTO_LEFT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo à la ferme# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de una granja venden #[[1]]#. + + hintTextTable[RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo à la ferme# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de una granja venden #[[1]]#. + + hintTextTable[RHT_LLR_DEKU_SCRUB_GROTTO_CENTER] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo à la ferme# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de una granja venden #[[1]]#. + + hintTextTable[RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = HintText(CustomMessage("They say that a pair of #scrubs in the woods# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près du théâtre# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un par de #dekus del bosque# venden #[[1]]#. + + hintTextTable[RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = HintText(CustomMessage("They say that a pair of #scrubs in the woods# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près du théâtre# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un par de #dekus del bosque# venden #[[1]]#. + + hintTextTable[RHT_LW_DEKU_SCRUB_NEAR_BRIDGE] = HintText(CustomMessage("They say that a #scrub by a bridge# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #peste Mojo près du pont dans les bois# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #deku bajo un puente# del bosque venden #[[1]]#. + + hintTextTable[RHT_LW_DEKU_SCRUB_GROTTO_REAR] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans les sous-bois# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del bosque venden #[[1]]#. + + hintTextTable[RHT_LW_DEKU_SCRUB_GROTTO_FRONT] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans les sous-bois# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del bosque venden #[[1]]#. + + hintTextTable[RHT_SFM_DEKU_SCRUB_GROTTO_REAR] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo au cœur du sanctuaire sylvestre# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# de la pradera sagrada venden #[[1]]#. + + hintTextTable[RHT_SFM_DEKU_SCRUB_GROTTO_FRONT] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo au cœur du sanctuaire sylvestre# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# de la pradera sagrada venden #[[1]]#. + + hintTextTable[RHT_GC_DEKU_SCRUB_GROTTO_LEFT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le village Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de la Ciudad Goron venden #[[1]]#. + + hintTextTable[RHT_GC_DEKU_SCRUB_GROTTO_RIGHT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le village Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de la Ciudad Goron venden #[[1]]#. + + hintTextTable[RHT_GC_DEKU_SCRUB_GROTTO_CENTER] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le village Goron# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# de la Ciudad Goron venden #[[1]]#. + + hintTextTable[RHT_DMC_DEKU_SCRUB_GROTTO_LEFT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le volcan# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del volcán venden #[[1]]#. + + hintTextTable[RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le volcan# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del volcán venden #[[1]]#. + + hintTextTable[RHT_DMC_DEKU_SCRUB_GROTTO_CENTER] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo dans le volcan# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del volcán venden #[[1]]#. + + hintTextTable[RHT_ZR_DEKU_SCRUB_GROTTO_REAR] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près du fleuve# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del río venden #[[1]]#. + + hintTextTable[RHT_ZR_DEKU_SCRUB_GROTTO_FRONT] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près du fleuve# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del río venden #[[1]]#. + + hintTextTable[RHT_LH_DEKU_SCRUB_GROTTO_LEFT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo près du lac# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del lago venden #[[1]]#. + + hintTextTable[RHT_LH_DEKU_SCRUB_GROTTO_RIGHT] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo près du lac# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del lago venden #[[1]]#. + + hintTextTable[RHT_LH_DEKU_SCRUB_GROTTO_CENTER] = HintText(CustomMessage("They say that a #trio of scrubs# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #trio de peste Mojo près du lac# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #trío de dekus# del lago venden #[[1]]#. + + hintTextTable[RHT_GV_DEKU_SCRUB_GROTTO_REAR] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près de la vallée# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del valle venden #[[1]]#. + + hintTextTable[RHT_GV_DEKU_SCRUB_GROTTO_FRONT] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo près de la vallée# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del valle venden #[[1]]#. + + hintTextTable[RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans le désert# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del desierto venden #[[1]]#. + + hintTextTable[RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = HintText(CustomMessage("They say that a #scrub underground duo# sells #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #duo de peste Mojo dans le désert# vend #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #par de dekus subterráneos# del desierto venden #[[1]]#. + + hintTextTable[RHT_LLR_STABLES_LEFT_COW] = HintText(CustomMessage("They say that a #cow in a stable# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans l'étable# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca del establo# brinda #[[1]]#. + + hintTextTable[RHT_LLR_STABLES_RIGHT_COW] = HintText(CustomMessage("They say that a #cow in a stable# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans l'étable# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca del establo# brinda #[[1]]#. + + hintTextTable[RHT_LLR_TOWER_RIGHT_COW] = HintText(CustomMessage("They say that a #cow in a ranch silo# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans le silo de la ferme# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca del granero# brinda #[[1]]#. + + hintTextTable[RHT_LLR_TOWER_LEFT_COW] = HintText(CustomMessage("They say that a #cow in a ranch silo# gifts #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans le silo de la ferme# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca del granero# brinda #[[1]]#. + + hintTextTable[RHT_KAK_IMPAS_HOUSE_COW] = HintText(CustomMessage("They say that a #cow imprisoned in a house# protects #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache en cage# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca enjaulada de una casa# brinda #[[1]]#. + + hintTextTable[RHT_DMT_COW_GROTTO_COW] = HintText(CustomMessage("They say that a #cow in a luxurious hole# offers #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #vache dans une grotte luxueuse# donne #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #vaca de un lujoso hoyo# brinda #[[1]]#. + + hintTextTable[RHT_BEEHIVE_CHEST_GROTTO] = HintText(CustomMessage("They say that a #beehive above a chest# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena sobre un cofre# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_LONELY_SCRUB_GROTTO] = HintText(CustomMessage("They say that a #beehive above a lonely scrub# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena sobre un deku solitario# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_SCRUB_PAIR_GROTTO] = HintText(CustomMessage("They say that a #beehive above a pair of scrubs# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena sobre un par de dekus# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_SCRUB_TRIO_GROTTO] = HintText(CustomMessage("They say that a #beehive above a trio of scrubs# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena sobre un trío de dekus# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_COW_GROTTO] = HintText(CustomMessage("They say that a #beehive above a cow# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena sobre una vaca# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA] = HintText(CustomMessage("They say that a #beehive in front of the king of the zoras# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena delante del rey de los zoras# esconde #[[1]]#. + + hintTextTable[RHT_BEEHIVE_BEHIND_KING_ZORA] = HintText(CustomMessage("They say that a #beehive behind the king of the zoras# hides #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, una #colmena detrás del rey de los zoras# esconde #[[1]]#. +} } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index be20b95a3..e99b6fd71 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -1,2142 +1,2084 @@ -#include "../hint_list.hpp" - -void HintTable_Init_Item() { - hintTable[RHT_KOKIRI_SWORD] = HintText::Item({ - //obscure text - Text{"a butter knife", /*french*/"un couteau à beurre", /*spanish*/"un ágil puñal"}, - Text{"a starter slasher", /*french*/"une arme de débutant", /*spanish*/"una hoja de principiantes"}, - Text{"a switchblade", /*french*/"un canif", /*spanish*/"una navaja"}, - }, { - //ambiguous text - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"the Kokiri Sword", /*french*/"l'Épée Kokiri", /*spanish*/"la Espada Kokiri"} - ); - - hintTable[RHT_MASTER_SWORD] = HintText::Item({ - //obscure text - Text{"evil's bane", /*french*/"le fléau du mal", /*spanish*/"la destructora del mal"}, - Text{"a seven year limbo", /*french*/"une stase de sept ans", /*spanish*/"unos siete años de espera"}, - }, { - //ambiguous text - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"the Master Sword", /*french*/"l'Épée de Légende", /*spanish*/"la Espada Maestra"} - ); - - hintTable[RHT_GIANTS_KNIFE] = HintText::Item({ - //obscure text - Text{"a fragile blade", /*french*/"une lame fragile", /*spanish*/"una frágil hoja"}, - Text{"a breakable cleaver", /*french*/"un espadon de verre", /*spanish*/"un rompible acero"}, - }, { - //ambiguous text - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"the Giant's Knife", /*french*/"la Lame des Géants", /*spanish*/"la daga gigante"} - ); - - hintTable[RHT_BIGGORON_SWORD] = HintText::Item({ - //obscure text - Text{"the biggest blade", /*french*/"une lame gigantesque", /*spanish*/"el mayor mandoble"}, - Text{"a colossal cleaver", /*french*/"un espadon colossal", /*spanish*/"un estoque colosal"}, - }, { - //ambiguous text - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"the Biggoron Sword", /*french*/"l'Épée de Biggoron", /*spanish*/"la Espada de Biggoron"} - ); - - hintTable[RHT_DEKU_SHIELD] = HintText::Item({ - //obscure text - Text{"a wooden ward", /*french*/"un écu d'écorce", /*spanish*/"una protección del bosque"}, - Text{"a burnable barrier", /*french*/"une protection inflammable", /*spanish*/"una barrera quemable"}, - }, { - //ambiguous text - Text{"a shield", /*french*/"un bouclier", /*spanish*/"un escudo"}, - }, - //clear text - Text{"a Deku Shield", /*french*/"un Bouclier Mojo", /*spanish*/"un escudo deku"} - ); - - hintTable[RHT_HYLIAN_SHIELD] = HintText::Item({ - //obscure text - Text{"a steel safeguard", /*french*/"une carapace d'acier", /*spanish*/"una protección de acero"}, - Text{"Like Like's metal meal", /*french*/"un amuse-gueule de Pudding", /*spanish*/"un alimento de Like Like"}, - }, { - //ambiguous text - Text{"a shield", /*french*/"un bouclier", /*spanish*/"un escudo"}, - }, - //clear text - Text{"a Hylian Shield", /*french*/"un Bouclier Hylien", /*spanish*/"un escudo hyliano"} - ); - - hintTable[RHT_MIRROR_SHIELD] = HintText::Item({ - //obscure text - Text{"a reflective rampart", /*french*/"un capteur de lumière", /*spanish*/"una muralla reflectora"}, - Text{"Medusa's weakness", /*french*/"la faiblesse de Méduse", /*spanish*/"la debilidad de Medusa"}, - Text{"a silvered surface", /*french*/"une surface argentée", /*spanish*/"una superficie plateada"}, - }, { - //ambiguous text - Text{"a shield", /*french*/"un bouclier", /*spanish*/"un escudo"}, - }, - //clear text - Text{"the Mirror Shield", /*french*/"le Bouclier Miroir", /*spanish*/"el escudo espejo"} - ); - - hintTable[RHT_GORON_TUNIC] = HintText::Item({ - //obscure text - Text{"ruby robes", /*french*/"un pigment rouge", /*spanish*/"una vestimenta rubí"}, - Text{"fireproof fabric", /*french*/"un trésor anti-flamme", /*spanish*/"una ignífuga prenda"}, - Text{"cooking clothes", /*french*/"une tenue de cuisine", /*spanish*/"unos abrasantes ropajes"}, - }, { - //ambiguous text - Text{"a tunic", /*french*/"une tunique", /*spanish*/"un sayo"}, - }, - //clear text - Text{"a Goron Tunic", /*french*/"une Tunique Goron", /*spanish*/"un sayo goron"} - ); - - hintTable[RHT_ZORA_TUNIC] = HintText::Item({ - //obscure text - Text{"a sapphire suit", /*french*/"un pigment bleuté", /*spanish*/"una vestidura zafiro"}, - Text{"scuba gear", /*french*/"un habit de plongée", /*spanish*/"un traje impermeable"}, - Text{"a swimsuit", /*french*/"un costume de baignade", /*spanish*/"unos ropajes sumergibles"}, - }, { - //ambiguous text - Text{"a tunic", /*french*/"une tunique", /*spanish*/"un sayo"}, - Text{"something expensive", /*french*/"une chose dispendieuse", /*spanish*/"algo caro"}, - }, - //clear text - Text{"a Zora Tunic", /*french*/"une Tunique Zora", /*spanish*/"un sayo zora"} - ); - - hintTable[RHT_IRON_BOOTS] = HintText::Item({ - //obscure text - Text{"sink shoes", /*french*/"un boulet de fer", /*spanish*/"un calzado de las profundidades"}, - Text{"clank cleats", /*french*/"une paire de talons bruyants", /*spanish*/"unas suelas férreas"}, - }, { - //ambiguous text - Text{"some boots", /*french*/"une paire de bottes", /*spanish*/"un par de botas"}, - Text{"a feature of the Water Temple", /*french*/"une particularité du Temple de l'Eau", /*spanish*/"algo particular del Templo del Agua"}, - Text{"something heavy", /*french*/"une chose pesante", /*spanish*/"algo de lo más pesado"}, - }, - //clear text - Text{"the Iron Boots", /*french*/"une paire de Bottes de plomb", /*spanish*/"las botas de hierro"} - ); - - hintTable[RHT_HOVER_BOOTS] = HintText::Item({ - //obscure text - Text{"butter boots", /*french*/"une paire de patins de beurre", /*spanish*/"unas suelas resvaladizas"}, - Text{"sacred slippers", /*french*/"une paire de pantoufles sacrées", /*spanish*/"unos escurridizos botines"}, - Text{"spacewalkers", /*french*/"une paire de bottes spatiales", /*spanish*/"un calzado antigravitatorio"}, - }, { - //ambiguous text - Text{"some boots", /*french*/"une paire de bottes", /*spanish*/"un par de botas"}, - }, - //clear text - Text{"the Hover Boots", /*french*/"une paire de Bottes des airs", /*spanish*/"las botas voladoras"} - ); - - - hintTable[RHT_ZELDAS_LETTER] = HintText::Item({ - //obscure text - Text{"an autograph", /*french*/"un autographe", /*spanish*/"un autógrafo"}, - Text{"royal stationery", /*french*/"du papier royal", /*spanish*/"un escrito real"}, - Text{"royal snail mail", /*french*/"une enveloppe royale", /*spanish*/"correo de la realeza"}, - }, {}, - //clear text - Text{"Zelda's Letter", /*french*/"la Lettre de Zelda", /*spanish*/"la carta de Zelda"} - ); - - hintTable[RHT_WEIRD_EGG] = HintText::Item({ - //obscure text - Text{"a chicken dilemma", /*french*/"un drôle d'ovale", /*spanish*/"el dilema de la gallina"}, - }, { - //ambiguous text - Text{"an egg", /*french*/"un oeuf", /*spanish*/"un huevo"}, - }, - //clear text - Text{"the Weird Egg", /*french*/"l'Oeuf Curieux", /*spanish*/"el huevo extraño"} - ); - - hintTable[RHT_BOOMERANG] = HintText::Item({ - //obscure text - Text{"a banana", /*french*/"une banane", /*spanish*/"un plátano"}, - Text{"a stun stick", /*french*/"un bâton étourdissant", /*spanish*/"un palo aturdidor"}, - Text{"a yellow angle", /*french*/"un angle jaune", /*spanish*/"un ángulo amarillo"}, - }, { - //ambiguous text - Text{"something that can grab things", /*french*/"une chose qui peut attraper", /*spanish*/"algo que pueda agarrar cosas"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"the Boomerang", /*french*/"le Boomerang", /*spanish*/"el bumerán"} - ); - - hintTable[RHT_LENS_OF_TRUTH] = HintText::Item({ - //obscure text - Text{"a lie detector", /*french*/"un détecteur de mensonges", /*spanish*/"el detector de ilusiones"}, - Text{"a ghost tracker", /*french*/"un trouve-fantôme", /*spanish*/"el rastreador paranormal"}, - Text{"true sight", /*french*/"le troisième œil", /*spanish*/"el ojo que todo ve"}, - Text{"a detective's tool", /*french*/"un trésor Sheikah", /*spanish*/"la revelación verdadera"}, - }, { - //ambiguous text - Text{"a secret-finding tool", /*french*/"un cherche-secrets", /*spanish*/"un instrumento para hallar objetos"}, - }, - //clear text - Text{"the Lens of Truth", /*french*/"le Monocle de Vérité", /*spanish*/"la Lupa de la Verdad"} - ); - - hintTable[RHT_MEGATON_HAMMER] = HintText::Item({ - //obscure text - Text{"the dragon smasher", /*french*/"le tueur de dragons", /*spanish*/"un destructor de dragones"}, - Text{"the metal mallet", /*french*/"un outil de construction", /*spanish*/"un mazo de metal"}, - Text{"the heavy hitter", /*french*/"un poids lourd", /*spanish*/"un machacador"}, - }, { - //ambiguous text - Text{"something that can remove boulders", /*french*/"une chose qui enlève les rochers", /*spanish*/"algo que pueda quitar rocas"}, - }, - //clear text - Text{"the Megaton Hammer", /*french*/"la Masse des Titans", /*spanish*/"el martillo Megatón"} - ); - - hintTable[RHT_STONE_OF_AGONY] = HintText::Item({ - //obscure text - Text{"the shake stone", /*french*/"le fragment vibrant", /*spanish*/"el fragmento tintineante"}, - Text{"a gray alarm", /*french*/"une alerte bleue", /*spanish*/"una azul alarma"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - Text{"a secret-finding tool", /*french*/"un cherche-secrets", /*spanish*/"un instrumento para hallar objetos"}, - }, - //clear text - Text{"the Stone of Agony", /*french*/"la Pierre de Souffrance", /*spanish*/"la Piedra de la Agonía"} - ); - - hintTable[RHT_DINS_FIRE] = HintText::Item({ - //obscure text - Text{"an inferno", /*french*/"un brasier", /*spanish*/"un incendio"}, - Text{"a heat wave", /*french*/"une vague de chaleur", /*spanish*/"una onda de calor"}, - Text{"a red ball", /*french*/"une explosion de flammes", /*spanish*/"una roja esfera"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - }, - //clear text - Text{"Din's Fire", /*french*/"le Feu de Din", /*spanish*/"el Fuego de Din"} - ); - - hintTable[RHT_FARORES_WIND] = HintText::Item({ - //obscure text - Text{"teleportation", /*french*/"la téléportation", /*spanish*/"un teletransportador"}, - Text{"a relocation rune", /*french*/"une rune de relocation", /*spanish*/"una runa de transporte"}, - Text{"a green ball", /*french*/"une boule verte", /*spanish*/"una verde esfera"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - }, - //clear text - Text{"Farore's Wind", /*french*/"le Vent de Farore", /*spanish*/"el Viento de Farore"} - ); - - hintTable[RHT_NAYRUS_LOVE] = HintText::Item({ - //obscure text - Text{"a safe space", /*french*/"une bulle de cristal", /*spanish*/"una seguridad temporal"}, - Text{"an impregnable aura", /*french*/"un aura impénétrable", /*spanish*/"un aura impenetrable"}, - Text{"a blue barrier", /*french*/"une toison bleu", /*spanish*/"una barrera azul"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - }, - //clear text - Text{"Nayru's Love", /*french*/"l'Amour de Nayru", /*spanish*/"el Amor de Nayru"} - ); - - hintTable[RHT_FIRE_ARROWS] = HintText::Item({ - //obscure text - Text{"the furnace firearm" , /*french*/"une fusée solaire", /*spanish*/"el ardiente aguijón"}, - Text{"the burning bolts", /*french*/"un obus enflammé", /*spanish*/"las puntas ígneas"}, - Text{"a magma missile", /*french*/"un missile volcanique", /*spanish*/"el misil abrasador"}, - }, { - //ambiguous text - Text{"a magic arrow", /*french*/"une flèche magique", /*spanish*/"una flecha mágica"}, - }, - //clear text - Text{"the Fire Arrows", /*french*/"les Flèches de Feu", /*spanish*/"la flecha de fuego"} - ); - - hintTable[RHT_ICE_ARROWS] = HintText::Item({ - //obscure text - Text{"the refrigerator rocket", /*french*/"un missile pétrifiant", /*spanish*/"el misil congelador"}, - Text{"the frostbite bolts", /*french*/"un froid mordant", /*spanish*/"las puntas gélidas"}, - Text{"an iceberg maker", /*french*/"une aiguille glaciale", /*spanish*/"el control de escarcha"}, - }, { - //ambiguous text - Text{"a magic arrow", /*french*/"une flèche magique", /*spanish*/"una flecha mágica"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"the Ice Arrows", /*french*/"les Flèches de Glace", /*spanish*/"la flecha de hielo"} - ); - - hintTable[RHT_LIGHT_ARROWS] = HintText::Item({ - //obscure text - Text{"the shining shot", /*french*/"l'arme brillante", /*spanish*/"el haz de luz"}, - Text{"the luminous launcher", /*french*/"un jet de lumière", /*spanish*/"el disparo luminoso"}, - Text{"Ganondorf's bane", /*french*/"le fléau de Ganondorf", /*spanish*/"la perdición de Ganondorf"}, - Text{"the lighting bolts", /*french*/"l'éclair sacré", /*spanish*/"las puntas resplandecientes"}, - }, { - //ambiguous text - Text{"a magic arrow", /*french*/"une flèche magique", /*spanish*/"una flecha mágica"}, - }, - //clear text - Text{"the Light Arrows", /*french*/"les Flèches de Lumière", /*spanish*/"la flecha de luz"} - ); - - hintTable[RHT_GERUDO_MEMBERSHIP_CARD] = HintText::Item({ - //obscure text - Text{"a girl club membership", /*french*/"une carte de membre", /*spanish*/"una fémina membresía"}, - Text{"a desert tribe's pass", /*french*/"un laissez-passer", /*spanish*/"el vale del desierto"}, - }, { - Text{"a token of recognition", /*french*/"une preuve de reconnaissance", /*spanish*/"una prueba de reconocimiento"}, - }, - //clear text - Text{"the Gerudo Membership Card", /*french*/"la Carte Gerudo", /*spanish*/"el pase de socio gerudo"} - ); - - hintTable[RHT_MAGIC_BEAN] = HintText::Item({ - //obscure text - Text{"a wizardly legume", /*french*/"un légume ensorcelé", /*spanish*/"una legumbre hechizada"}, - }, { - //ambiguous text - Text{"something sometimes buried", /*french*/"une chose parfois enterrée", /*spanish*/"algo a veces enterrado"}, - }, - //clear text - Text{"a Magic Bean", /*french*/"un Haricot Magique", /*spanish*/"una judía mágica"} - ); - - hintTable[RHT_MAGIC_BEAN_PACK] = HintText::Item({ - //obscure text - Text{"wizardly legumes", /*french*/"un paquet de légumes ensorcelés", /*spanish*/"unas legumbres hechizadas"}, - }, { - //ambiguous text - Text{"something sometimes buried", /*french*/"une chose parfois enterrée", /*spanish*/"algo a veces enterrado"}, - }, - //clear text - Text{"Magic Beans", /*french*/"un Paquet de Haricots Magiques", /*spanish*/"unas judías mágicas"} - ); - - hintTable[RHT_DOUBLE_DEFENSE] = HintText::Item({ - //obscure text - Text{"a white outline", /*french*/"un rebord blanc", /*spanish*/"un contorno blanco"}, - Text{"damage decrease", /*french*/"une protection supplémentaire", /*spanish*/"una reducción de daño"}, - Text{"strengthened love", /*french*/"un amour coriace", /*spanish*/"un amor fortalecido"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - Text{"something heart-shaped", /*french*/"une chose en forme de coeur", /*spanish*/"algo con forma de corazón"}, - }, - //clear text - Text{"Double Defense", /*french*/"la Double Défence", /*spanish*/"la doble defensa"} - ); - - hintTable[RHT_GOLD_SKULLTULA_TOKEN] = HintText::Item({ - //obscure text - Text{"proof of destruction", /*french*/"un certificat d'élimination", /*spanish*/"una prueba de la destrucción"}, - Text{"an arachnid chip", /*french*/"un symbole cranien", /*spanish*/"una figura arácnida"}, - Text{"spider remains", /*french*/"une dépouille dorée", /*spanish*/"unos restos dorados"}, - Text{"one percent of a curse", /*french*/"un centième de malédiction", /*spanish*/"una centésima de una maldición"}, - }, { - //ambiguous text - Text{"a token of recognition", /*french*/"une preuve de reconnaissance", /*spanish*/"una prueba de reconocimiento"}, - Text{"something sometimes buried", /*french*/"une chose parfois enterrée", /*spanish*/"algo a veces enterrado"}, - }, - //clear text - Text{"a Gold Skulltula Token", /*french*/"un Symbole de Skulltula d'or", /*spanish*/"un símbolo de skulltula dorada"} - ); - - hintTable[RHT_POCKET_EGG] = HintText::Item({ - //obscure text - Text{"a Cucco container", /*french*/"un réservoir à Cocotte", /*spanish*/"cuco contenido"}, - Text{"a Cucco, eventually", /*french*/"un poussin éventuel", /*spanish*/"un futuro cuco"}, - Text{"a fowl youth", /*french*/"une omelette crue", /*spanish*/"una dulce juventud"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - Text{"an egg", /*french*/"un oeuf", /*spanish*/"un huevo"}, - }, - //clear text - Text{"the Pocket Egg", /*french*/"l'Oeuf de Poche", /*spanish*/"el huevo de bolsillo"} - ); - - hintTable[RHT_POCKET_CUCCO] = HintText::Item({ - //obscure text - Text{"a little clucker", /*french*/"un petit glousseur", /*spanish*/"un pollito chiquito"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Pocket Cucco", /*french*/"la Cocotte de Poche", /*spanish*/"el cuco de bolsillo"} - ); - - hintTable[RHT_COJIRO] = HintText::Item({ - //obscure text - Text{"a cerulean capon", /*french*/"un paon azur", /*spanish*/"un cerúleo capón"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"Cojiro", /*french*/"le p'tit poulet", /*spanish*/"a Cojiro"} - ); - - hintTable[RHT_ODD_MUSHROOM] = HintText::Item({ - //obscure text - Text{"a powder ingredient", /*french*/"un ingrédient à poudre", /*spanish*/"un oloroso ingrediente"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"an Odd Mushroom", /*french*/"un Champignon Suspect", /*spanish*/"un champiñón extraño"} - ); - - hintTable[RHT_ODD_POTION] = HintText::Item({ - //obscure text - Text{"Granny's goodies", /*french*/"la confiserie de mamie", /*spanish*/"la especialidad de la abuela"}, - }, { - //ambiguous text - Text{"something that contains medicine", /*french*/"une chose médicamenteuse", /*spanish*/"algo que contenga medicina"}, - Text{"something with a strange smell", /*french*/"une chose qui sent bizarre", /*spanish*/"algo con un olor extraño"}, - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"an Odd Potion", /*french*/"une Mixture Suspecte", /*spanish*/"una medicina rara"} - ); - - hintTable[RHT_POACHERS_SAW] = HintText::Item({ - //obscure text - Text{"a tree killer", /*french*/"un coupeur d'arbres", /*spanish*/"un destructor de árboles"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Poacher's Saw", /*french*/"la Scie du Chasseur", /*spanish*/"la sierra del furtivo"} - ); - - hintTable[RHT_BROKEN_SWORD] = HintText::Item({ - //obscure text - Text{"a shattered slicer", /*french*/"une arme cassée", /*spanish*/"una rebanadora rota"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"the Broken Goron's Sword", /*french*/"l'Épée Brisée de Goron", /*spanish*/"la espada goron rota"} - ); - - hintTable[RHT_PRESCRIPTION] = HintText::Item({ - //obscure text - Text{"a pill pamphlet", /*french*/"un document urgent", /*spanish*/"un instructivo medicinal"}, - Text{"a doctor's note", /*french*/"un papier médical", /*spanish*/"unas notas del doctor"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Prescription", /*french*/"une Ordonnance", /*spanish*/"la receta"} - ); - - hintTable[RHT_EYEBALL_FROG] = HintText::Item({ - //obscure text - Text{"a perceiving polliwog", /*french*/"un amphibien", /*spanish*/"un variopinto batracio"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Eyeball Frog", /*french*/"le Crapaud-qui-louche", /*spanish*/"la rana de ojos saltones"} - ); - - hintTable[RHT_EYEDROPS] = HintText::Item({ - //obscure text - Text{"a vision vial", /*french*/"une solution oculaire", /*spanish*/"un remedio para la vista"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Eyedrops", /*french*/"une phiole de Super-Gouttes", /*spanish*/"las supergotas oculares"} - ); - - hintTable[RHT_CLAIM_CHECK] = HintText::Item({ - //obscure text - Text{"a three day wait", /*french*/"un rendez-vous dans trois jours", /*spanish*/"unos tres días de espera"}, - }, { - //ambiguous text - Text{"a trade quest item", /*french*/"un objet de quête d'échanges", /*spanish*/"un objeto de una misión secundaria"}, - }, - //clear text - Text{"the Claim Check", /*french*/"un Certificat", /*spanish*/"el recibo"} - ); - - hintTable[RHT_PROGRESSIVE_HOOKSHOT] = HintText::Item({ - //obscure text - Text{"Dampé's keepsake", /*french*/"l'héritage d'Igor", /*spanish*/"un recuerdo de Dampé"}, - Text{"the Grapple Beam", /*french*/"le rayon grippeur", /*spanish*/"una garra metálica"}, - Text{"the RHT_BOING! chain", /*french*/"la chaîne de RHT_BOING!", /*spanish*/"una cadena retráctil"}, - }, { - //ambiguous text - Text{"something that can grab things", /*french*/"une chose qui peut attraper", /*spanish*/"algo que pueda agarrar cosas"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"a Hookshot", /*french*/"un Grappin", /*spanish*/"un gancho"} - ); - - hintTable[RHT_PROGRESSIVE_STRENGTH] = HintText::Item({ - //obscure text - Text{"power gloves", /*french*/"une paire de gants de travail", /*spanish*/"unos poderosos guanteletes"}, - Text{"metal mittens", /*french*/"une paire de mitaines", /*spanish*/"unas manoplas metálicas"}, - Text{"the heavy lifty", /*french*/"la puissance de dix hommes", /*spanish*/"un levantamiento pesado"}, - }, { - //ambiguous text - Text{"something that can remove boulders", /*french*/"une chose qui enlève les rochers", /*spanish*/"algo que pueda quitar rocas"}, - }, - //clear text - Text{"a Strength Upgrade", /*french*/"une Amélioration de Force", /*spanish*/"un aumento de fuerza"} - ); - - hintTable[RHT_PROGRESSIVE_BOMB_BAG] = HintText::Item({ - //obscure text - Text{"an explosive container", /*french*/"un porte-grenade", /*spanish*/"un recipiente explosivo"}, - Text{"a blast bag", /*french*/"un estomac de Dodongo", /*spanish*/"un zurrón de estallidos"}, - }, { - //ambiguous text - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - Text{"something that can remove boulders", /*french*/"une chose qui enlève les rochers", /*spanish*/"algo que pueda quitar rocas"}, - }, - //clear text - Text{"a Bomb Bag", /*french*/"un Sac de Bombes", /*spanish*/"un saco de bombas"} - ); - - hintTable[RHT_PROGRESSIVE_BOW] = HintText::Item({ - //obscure text - Text{"an archery enabler", /*french*/"un facilitateur de tir", /*spanish*/"un tiro al blanco"}, - Text{"a danger dart launcher", /*french*/"un tire-fléchette", /*spanish*/"un peligroso lanzadardos"}, - }, { - //ambiguous text - Text{"a projectile shooter", /*french*/"un tire-projectile", /*spanish*/"un arma de proyectil"}, - }, - //clear text - Text{"a Bow", /*french*/"l'Arc des Fées", /*spanish*/"un arco de las hadas"} - ); - - hintTable[RHT_PROGRESSIVE_SLINGSHOT] = HintText::Item({ - //obscure text - Text{"a seed shooter", /*french*/"un lance-noix", /*spanish*/"un lanzasemillas"}, - Text{"a rubberband", /*french*/"un élastique", /*spanish*/"un tirachinas"}, - Text{"a child's catapult", /*french*/"un jouet d'enfant", /*spanish*/"una catapulta infantil"}, - }, { - //ambiguous text - Text{"a projectile shooter", /*french*/"un tire-projectile", /*spanish*/"un arma de proyectil"}, - }, - //clear text - Text{"a Slingshot", /*french*/"un Lance-Pierre", /*spanish*/"una resortera de las hadas"} - ); - - hintTable[RHT_PROGRESSIVE_WALLET] = HintText::Item({ - //obscure text - Text{"a mo' money holder", /*french*/"un sac à sous", /*spanish*/"una cartera de dinero"}, - Text{"a gem purse", /*french*/"une sacoche", /*spanish*/"un zurrón de gemas"}, - Text{"a portable bank", /*french*/"une petite banque", /*spanish*/"un banco portable"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - }, - //clear text - Text{"a Wallet", /*french*/"une Bourse", /*spanish*/"una bolsa de rupias"} - ); - - hintTable[RHT_PROGRESSIVE_SCALE] = HintText::Item({ - //obscure text - Text{"a deeper dive", /*french*/"une bulle de plongée", /*spanish*/"un profundo buceo"}, - Text{"a piece of Zora", /*french*/"un morceau de Zora", /*spanish*/"un fragmento de Zora"}, - }, { - //ambiguous text - Text{"a diving tool", /*french*/"un outil de plongée", /*spanish*/"un instrumento de buceo"}, - }, - //clear text - Text{"a Zora Scale", /*french*/"une Écaille Zora", /*spanish*/"una escama Zora"} - ); - - hintTable[RHT_PROGRESSIVE_NUT_UPGRADE] = HintText::Item({ - //obscure text - Text{"more nuts", /*french*/"ecnore plus de noix", /*spanish*/"más semillas de nogal"}, - Text{"flashbang storage", /*french*/"un sac à noix", /*spanish*/"más frutos aturdidores"}, - }, { - //ambiguous text - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"Deku Nut Capacity", /*french*/"une Augmentation de Noix Mojo", /*spanish*/"un aumento de nueces deku"} - ); - - hintTable[RHT_PROGRESSIVE_STICK_UPGRADE] = HintText::Item({ - //obscure text - Text{"a lumber rack", /*french*/"un paquet de bois", /*spanish*/"más bastones"}, - Text{"more flammable twigs", /*french*/"beaucoup de branches", /*spanish*/"más varas"}, - }, { - //ambiguous text - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - }, - //clear text - Text{"Deku Stick Capacity", /*french*/"une augmentation de bâtons Mojo", /*spanish*/"un aumento de palos deku"} - ); - - hintTable[RHT_PROGRESSIVE_MAGIC_METER] = HintText::Item({ - //obscure text - Text{"mystic training", /*french*/"un potentiel magique", /*spanish*/"una maestría mística"}, - Text{"pixie dust", /*french*/"de la poudre de fée", /*spanish*/"un polvo de hada"}, - Text{"a green rectangle", /*french*/"un rectangle vert", /*spanish*/"una verduzca barra"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - }, - //clear text - Text{"a Magic Meter", /*french*/"une Jauge de Magie", /*spanish*/"un aumento de poder mágico"} - ); - - hintTable[RHT_PROGRESSIVE_OCARINA] = HintText::Item({ - //obscure text - Text{"a flute", /*french*/"un bec musical", /*spanish*/"un utensilio musical"}, - Text{"a music maker", /*french*/"un porteur de chansons", /*spanish*/"un instrumento"}, - }, { - //ambiguous text - Text{"something given by Saria", /*french*/"un cadeau de Saria", /*spanish*/"un obsequio de Saria"}, - Text{"something kept by the royal family", /*french*/"une chose qui paralyse", /*spanish*/"algo guardado por la familia real"}, - }, - //clear text - Text{"an Ocarina", /*french*/"un ocarina", /*spanish*/"una ocarina"} - ); - - hintTable[RHT_PROGRESSIVE_BOMBCHUS] = HintText::Item({ - //obscure text - Text{"mice bombs", /*french*/"un adorable explosif", /*spanish*/"unas bombas roedoras"}, - Text{"proximity mice", /*french*/"une mine anti-rongeur", /*spanish*/"unos explosivos ratoncitos"}, - Text{"wall crawlers", /*french*/"un rapide grimpeur", /*spanish*/"unos trepaparedes"}, - Text{"trail blazers", /*french*/"un zigzag éclatant", /*spanish*/"unas ratas propulsadas"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombchus", /*french*/"un paquet de Missiles", /*spanish*/"unos bombchus"} - ); - - hintTable[RHT_PROGRESSIVE_GORONSWORD] = HintText::Item({ - //obscure text - Text{"a long blade", /*french*/"une longue lame", /*spanish*/"una gran hoja"}, - Text{"a Goron weapon", /*french*/"une arme Goron", /*spanish*/"un arma goron"}, - }, { - //ambiguous text - Text{"a sword", /*french*/"une épée", /*spanish*/"una espada"}, - }, - //clear text - Text{"a Goron Sword", /*french*/"une épée Goron", /*spanish*/"una espada goron"} - ); - - hintTable[RHT_EMPTY_BOTTLE] = HintText::Item({ - //obscure text - Text{"a glass container", /*french*/"un cylindre de cristal", /*spanish*/"un recipiente de cristal"}, - Text{"an empty jar", /*french*/"une jarre incassable", /*spanish*/"un frasco vacío"}, - Text{"encased air", /*french*/"un bocal d'air", /*spanish*/"aire a presión"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Bottle", /*french*/"un flacon vide", /*spanish*/"una botella"} - ); - - hintTable[RHT_BOTTLE_WITH_MILK] = HintText::Item({ - //obscure text - Text{"cow juice", /*french*/"une source de calcium", /*spanish*/"una fuente de calcio"}, - Text{"a white liquid", /*french*/"un liquide blanc", /*spanish*/"una bebida nutritiva"}, - Text{"a baby's breakfast", /*french*/"du jus pour bébé", /*spanish*/"un trago para bebés"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Milk Bottle", /*french*/"un flacon de lait", /*spanish*/"una botella de leche"} - ); - - hintTable[RHT_BOTTLE_WITH_RED_POTION] = HintText::Item({ - //obscure text - Text{"a vitality vial", /*french*/"un mélange de vitalité", /*spanish*/"una pócima vitalicia"}, - Text{"a red liquid", /*french*/"un liquide rouge", /*spanish*/"un remedio rojizo"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Red Potion Bottle", /*french*/"un flacon de potion rouge", /*spanish*/"una botella de poción roja"} - ); - - hintTable[RHT_BOTTLE_WITH_GREEN_POTION] = HintText::Item({ - //obscure text - Text{"a magic mixture", /*french*/"une réserve magique", /*spanish*/"un potingue mágico"}, - Text{"a green liquid", /*french*/"un liquide vert", /*spanish*/"un remedio verduzco"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Green Potion Bottle", /*french*/"un flacon de potion verte", /*spanish*/"una botella de poción verde"} - ); - - hintTable[RHT_BOTTLE_WITH_BLUE_POTION] = HintText::Item({ - //obscure text - Text{"an ailment antidote", /*french*/"l'élixir ultime", /*spanish*/"un antídoto para el dolor"}, - Text{"a blue liquid", /*french*/"un liquide bleu", /*spanish*/"un remedio índigo"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Blue Potion Bottle", /*french*/"un flacon de potion bleue", /*spanish*/"una botella de poción azul"} - ); - - hintTable[RHT_BOTTLE_WITH_FAIRY] = HintText::Item({ - //obscure text - Text{"an imprisoned fairy", /*french*/"une fée emprisonnée", /*spanish*/"un hada atrapada"}, - Text{"an extra life", /*french*/"une vie de rechange", /*spanish*/"una oportunidad más"}, - Text{"Navi's cousin", /*french*/"le cousin de Navi", /*spanish*/"una prima de Navi"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Fairy Bottle", /*french*/"une fée en flacon", /*spanish*/"un hada en una botella"} - ); - - hintTable[RHT_BOTTLE_WITH_FISH] = HintText::Item({ - //obscure text - Text{"an aquarium", /*french*/"un aquarium", /*spanish*/"un escamado ser"}, - Text{"a deity's snack", /*french*/"le repas d'un dieu marin", /*spanish*/"un tentempié de cierta deidad"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Fish Bottle", /*french*/"un poisson en flacon", /*spanish*/"un pez en una botella"} - ); - - hintTable[RHT_BOTTLE_WITH_BLUE_FIRE] = HintText::Item({ - //obscure text - Text{"a conflagration canteen", /*french*/"une mystérieuse flamme", /*spanish*/"un incendio retenido"}, - Text{"an icemelt jar", /*french*/"un brasier glacial", /*spanish*/"unas brasas enfrascadas"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Blue Fire Bottle", /*french*/"une flamme bleue en flacon", /*spanish*/"una botella de fuego azul"} - ); - - hintTable[RHT_BOTTLE_WITH_BUGS] = HintText::Item({ - //obscure text - Text{"an insectarium", /*french*/"un insectarium", /*spanish*/"unos invertebrados seres"}, - Text{"Skulltula finders", /*french*/"une poignée de trouve-Skulltula", /*spanish*/"unos rastreadores de skulltulas"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Bug Bottle", /*french*/"un insecte en flacon", /*spanish*/"unos insectos en una botella"} - ); - - hintTable[RHT_BOTTLE_WITH_POE] = HintText::Item({ - //obscure text - Text{"a spooky ghost", /*french*/"un effroyable fantôme", /*spanish*/"un espantoso espectro"}, - Text{"a face in the jar", /*french*/"un visage dans un bocal", /*spanish*/"una expresión enfrascada"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Poe Bottle", /*french*/"un Esprit en flacon", /*spanish*/"un Poe en una botella"} - ); - - hintTable[RHT_BOTTLE_WITH_BIG_POE] = HintText::Item({ - //obscure text - Text{"the spookiest ghost", /*french*/"un épouvantable spectre", /*spanish*/"el espectro más espeluznante"}, - Text{"a sidequest spirit", /*french*/"un précieux esprit", /*spanish*/"un buen valorado espíritu"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"a Big Poe Bottle", /*french*/"une Ame en flacon", /*spanish*/"un Gran Poe en una botella"} - ); - - hintTable[RHT_RUTOS_LETTER] = HintText::Item({ - //obscure text - Text{"a call for help", /*french*/"un appel au secours", /*spanish*/"una llamada de auxilio"}, - Text{"the note that Mweeps", /*french*/"un message qui fait mwip", /*spanish*/"un escrito mweep"}, - Text{"an RHT_SOS call", /*french*/"un signal RHT_SOS", /*spanish*/"una nota de socorro"}, - Text{"a fishy stationery", /*french*/"un papier mouillé", /*spanish*/"un mensaje de ayuda"}, - }, { - //ambiguous text - Text{"a bottle", /*french*/"un flacon", /*spanish*/"una botella"}, - }, - //clear text - Text{"Ruto's Letter", /*french*/"la lettre de Ruto", /*spanish*/"la carta de Ruto"} - ); - - hintTable[RHT_ZELDAS_LULLABY] = HintText::Item({ - //obscure text - Text{"a song of royal slumber", /*french*/"une chanson royale", /*spanish*/"la canción real"}, - Text{"a triforce tune", /*french*/"la musique sacrée", /*spanish*/"la melodía de la trifuerza"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - Text{"something kept by the royal family", /*french*/"une chose qui paralyse", /*spanish*/"algo guardado por la familia real"}, - }, - //clear text - Text{"Zelda's Lullaby", /*french*/"la berceuse de Zelda", /*spanish*/"la Nana de Zelda"} - ); - - hintTable[RHT_EPONAS_SONG] = HintText::Item({ - //obscure text - Text{"an equestrian etude", /*french*/"une hymne équestre", /*spanish*/"una copla ecuestre"}, - Text{"Malon's melody", /*french*/"la mélodie des vaches", /*spanish*/"la sonata de Malon"}, - Text{"a ranch song", /*french*/"le chant des champs", /*spanish*/"un canto rupestre"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - }, - //clear text - Text{"Epona's Song", /*french*/"le chant d'Epona", /*spanish*/"la Canción de Epona"} - ); - - hintTable[RHT_SARIAS_SONG] = HintText::Item({ - //obscure text - Text{"a song of dancing Gorons", /*french*/"une chanson danceuse", /*spanish*/"un pegadizo tono goron"}, - Text{"Saria's phone number", /*french*/"le téléphone d'une amie", /*spanish*/"una consulta de asistencia"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - Text{"something given by Saria", /*french*/"un cadeau de Saria", /*spanish*/"un obsequio de Saria"}, - }, - //clear text - Text{"Saria's Song", /*french*/"le chant de Saria", /*spanish*/"la Canción de Saria"} - ); - - hintTable[RHT_SUNS_SONG] = HintText::Item({ - //obscure text - Text{"Sunny Day", /*french*/"Zénith", /*spanish*/"un día soleado"}, - Text{"the ReDead's bane", /*french*/"le fléau des Éffrois", /*spanish*/"la destructora de Redeads"}, - Text{"the Gibdo's bane", /*french*/"le fléau des Gibdo", /*spanish*/"la destructora de Gibdos"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"the Sun's Song", /*french*/"le chant du soleil", /*spanish*/"la Canción del Sol"} - ); - - hintTable[RHT_SONG_OF_TIME] = HintText::Item({ - //obscure text - Text{"a song 7 years long", /*french*/"le flot du temps", /*spanish*/"la setenada canción"}, - Text{"the tune of ages", /*french*/"le Chant des Âges", /*spanish*/"la melodía eónica"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - }, - //clear text - Text{"the Song of Time", /*french*/"le chant du temps", /*spanish*/"la Canción del tiempo"} - ); - - hintTable[RHT_SONG_OF_STORMS] = HintText::Item({ - //obscure text - Text{"Rain Dance", /*french*/"Danse Pluie", /*spanish*/"la danza de la lluvia"}, - Text{"a thunderstorm tune", /*french*/"une hymne foudroyante", /*spanish*/"una sonata tormentosa"}, - Text{"windmill acceleration", /*french*/"l'accélérateur de moulins", /*spanish*/"el arranque de molinos"}, - }, { - //ambiguous text - Text{"a regular song", /*french*/"une chanson normale", /*spanish*/"una cancion normal"}, - }, - //clear text - Text{"the Song of Storms", /*french*/"le chant des tempêtes", /*spanish*/"la Canción de la Tormenta"} - ); - - hintTable[RHT_MINUET_OF_FOREST] = HintText::Item({ - //obscure text - Text{"the song of tall trees", /*french*/"le bruit des arbres", /*spanish*/"la canción de las copas"}, - Text{"an arboreal anthem", /*french*/"l'hymne sylvestre", /*spanish*/"el himno forestal"}, - Text{"a green spark trail", /*french*/"une comète verte", /*spanish*/"el sendero esmeralda"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Minuet of Forest", /*french*/"le menuet de la forêt", /*spanish*/"el Minueto del bosque"} - ); - - hintTable[RHT_BOLERO_OF_FIRE] = HintText::Item({ - //obscure text - Text{"a song of lethal lava", /*french*/"une musique enflammée", /*spanish*/"la canción de la lava"}, - Text{"a red spark trail", /*french*/"une comète rouge", /*spanish*/"el sendero rubí"}, - Text{"a volcanic verse", /*french*/"le souffle du volcan", /*spanish*/"el verso volcánico"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Bolero of Fire", /*french*/"le boléro du feu", /*spanish*/"el Bolero del fuego"} - ); - - hintTable[RHT_SERENADE_OF_WATER] = HintText::Item({ - //obscure text - Text{"a song of a damp ditch", /*french*/"le calme de l'eau", /*spanish*/"la canción del estanque"}, - Text{"a blue spark trail", /*french*/"une comète bleue", /*spanish*/"el sendero zafiro"}, - Text{"the lake's lyric", /*french*/"la voix du lac", /*spanish*/"la letra del lago"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Serenade of Water", /*french*/"la sérénade de l'eau", /*spanish*/"la Serenata del agua"} - ); - - hintTable[RHT_REQUIEM_OF_SPIRIT] = HintText::Item({ - //obscure text - Text{"a song of sandy statues", /*french*/"la mélodie d'une grande statue", /*spanish*/"la canción de la gran estatua"}, - Text{"an orange spark trail", /*french*/"une comète orange", /*spanish*/"el sendero ámbar"}, - Text{"the desert ditty", /*french*/"le vent du désert", /*spanish*/"la estrofa del desierto"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Requiem of Spirit", /*french*/"le requiem des esprits", /*spanish*/"el Réquiem del espíritu"} - ); - - hintTable[RHT_NOCTURNE_OF_SHADOW] = HintText::Item({ - //obscure text - Text{"a song of spooky spirits", /*french*/"une hymne de chair de poule", /*spanish*/"la canción de los espectros"}, - Text{"a graveyard boogie", /*french*/"un boogie de fantômes", /*spanish*/"una honra fúnebre"}, - Text{"a haunted hymn", /*french*/"une chanson lugubre", /*spanish*/"una estrofa encantada"}, - Text{"a purple spark trail", /*french*/"une comète mauve", /*spanish*/"el sendero malva"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Nocturne of Shadow", /*french*/"le nocturne de l'ombre", /*spanish*/"el Nocturno de la sombra"} - ); - - hintTable[RHT_PRELUDE_OF_LIGHT] = HintText::Item({ - //obscure text - Text{"a luminous prologue melody", /*french*/"une matine illuminée", /*spanish*/"la melodía refulgente"}, - Text{"a yellow spark trail", /*french*/"une comète jaune", /*spanish*/"el sendero resplandeciente"}, - Text{"the temple traveler", /*french*/"un chant de sanctuaire", /*spanish*/"la ruta del templo"}, - }, { - //ambiguous text - Text{"a warp song", /*french*/"une chanson de téléportation", /*spanish*/"una canción de teletransportación"}, - }, - //clear text - Text{"the Prelude of Light", /*french*/"le prélude de la lumière", /*spanish*/"el Preludio de la luz"} - ); - hintTable[RHT_DEKU_TREE_MAP] = HintText::Item({ - //obscure text - Text{"a mossy atlas", /*french*/"un atlas boisé", /*spanish*/"un atlas musgoso"}, - Text{"some mossy blueprints", /*french*/"un plan boisé", /*spanish*/"unos planos musgosos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Deku Tree Map", /*french*/"la carte de l'Arbre Mojo", /*spanish*/"el mapa del Gran Árbol Deku"} - ); - hintTable[RHT_DODONGOS_CAVERN_MAP] = HintText::Item({ - //obscure text - Text{"a rocky atlas", /*french*/"un atlas rocheux", /*spanish*/"un atlas rocoso"}, - Text{"some rocky blueprints", /*french*/"un plan rocheux", /*spanish*/"unos planos rocosos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Dodongo's Cavern Map", /*french*/"la carte de la Caverne Dodongo", /*spanish*/"el mapa de la Cueva de los Dodongos"} - ); - hintTable[RHT_JABU_JABUS_BELLY_MAP] = HintText::Item({ - //obscure text - Text{"a fishy atlas", /*french*/"un atlas digéré", /*spanish*/"un atlas digesto"}, - Text{"some fishy blueprints", /*french*/"un plan digéré", /*spanish*/"unos planos digestos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Jabu-Jabu's Belly Map", /*french*/"la carte de Jabu-Jabu", /*spanish*/"el mapa de la Tripa de Jabu-Jabu"} - ); - hintTable[RHT_FOREST_TEMPLE_MAP] = HintText::Item({ - //obscure text - Text{"a sylvan atlas", /*french*/"un atlas sylvestre", /*spanish*/"un atlas enselvado"}, - Text{"some sylvan blueprints", /*french*/"un plan sylvestre", /*spanish*/"unos planos enselvados"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Forest Temple Map", /*french*/"la carte du Temple de la Forêt", /*spanish*/"el mapa del Templo del Bosque"} - ); - hintTable[RHT_FIRE_TEMPLE_MAP] = HintText::Item({ - //obscure text - Text{"a molten atlas", /*french*/"un atlas fondu", /*spanish*/"un atlas fundido"}, - Text{"some molten blueprints", /*french*/"un plan fondu", /*spanish*/"unos planos fundidos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Fire Temple Map", /*french*/"la carte du Temple du Feu", /*spanish*/"el mapa del Templo del Fuego"} - ); - hintTable[RHT_WATER_TEMPLE_MAP] = HintText::Item({ - //obscure text - Text{"a wet atlas", /*french*/"un atlas humide", /*spanish*/"un atlas mojado"}, - Text{"some wet blueprints", /*french*/"un plan humide", /*spanish*/"unos planos mojados"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Water Temple Map", /*french*/"la carte du Temple de l'Eau", /*spanish*/"el mapa del Templo del Agua"} - ); - hintTable[RHT_SPIRIT_TEMPLE_MAP] = HintText::Item({ - //obscure text - Text{"a sandy atlas", /*french*/"un atlas sableux", /*spanish*/"un atlas arenoso"}, - Text{"some sandy blueprints", /*french*/"un plan sableux", /*spanish*/"unos planos arenosos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Spirit Temple Map", /*french*/"la carte du Temple de l'Esprit", /*spanish*/"el mapa del Templo del Espíritu"} - ); - hintTable[RHT_SHADOW_TEMPLE_MAP] = HintText::Item({ - //obscure text - Text{"a creepy atlas", /*french*/"un atlas sinistre", /*spanish*/"un atlas siniestra"}, - Text{"some creepy blueprints", /*french*/"un plan sinistre", /*spanish*/"unos planos siniestras"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Shadow Temple Map", /*french*/"la carte du Temple de l'Ombre", /*spanish*/"el mapa del Templo de las Sombras"} - ); - hintTable[RHT_BOTTOM_OF_THE_WELL_MAP] = HintText::Item({ - //obscure text - Text{"a moldy atlas", /*french*/"un atlas moisi", /*spanish*/"un atlas mohoso"}, - Text{"some moldy blueprints", /*french*/"un plan moisi", /*spanish*/"unos planos mohosos"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Bottom of the Well Map", /*french*/"la carte du fond du Puits", /*spanish*/"el mapa del Fondo del pozo"} - ); - hintTable[RHT_ICE_CAVERN_MAP] = HintText::Item({ - //obscure text - Text{"a polar atlas", /*french*/"un atlas polaire", /*spanish*/"un atlas polar"}, - Text{"some polar blueprints", /*french*/"un plan polaire", /*spanish*/"unos planos polars"}, - }, { - //ambiguous text - Text{"a dungeon map", /*french*/"une carte", /*spanish*/"un mapa"}, - }, - //clear text - Text{"the Ice Cavern Map", /*french*/"la carte de la Caverne Polaire", /*spanish*/"el mapa de la Caverna de hielo"} - ); - hintTable[RHT_DEKU_TREE_COMPASS] = HintText::Item({ - //obscure text - Text{"a mossy treasure tracker", /*french*/"un cherche-trésor boisé", /*spanish*/"un zahorí musgoso"}, - Text{"a mossy magnetic needle", /*french*/"une aimant boisée", /*spanish*/"un imán musgoso"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Deku Tree Compass", /*french*/"la boussole de l'Arbre Mojo", /*spanish*/"la brújula del Gran Árbol Deku"} - ); - hintTable[RHT_DODONGOS_CAVERN_COMPASS] = HintText::Item({ - //obscure text - Text{"a rocky treasure tracker", /*french*/"un cherche-trésor rocheux", /*spanish*/"un zahorí rocoso"}, - Text{"a rocky magnetic needle", /*french*/"une aimant rocheux", /*spanish*/"un imán rocoso"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Dodongo's Cavern Compass", /*french*/"la boussole de la Caverne Dodongo", /*spanish*/"la brújula de la Cueva de los Dodongos"} - ); - hintTable[RHT_JABU_JABUS_BELLY_COMPASS] = HintText::Item({ - //obscure text - Text{"a fishy treasure tracker", /*french*/"un cherche-trésor digéré", /*spanish*/"un zahorí digesto"}, - Text{"a fishy magnetic needle", /*french*/"une aimant digéré", /*spanish*/"un imán digesto"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Jabu-Jabu's Belly Compass", /*french*/"la boussole de Jabu-Jabu", /*spanish*/"la brújula de la Tripa de Jabu-Jabu"} - ); - hintTable[RHT_FOREST_TEMPLE_COMPASS] = HintText::Item({ - //obscure text - Text{"a sylvan treasure tracker", /*french*/"un cherche-trésor sylvestre", /*spanish*/"un zahorí enselvado"}, - Text{"a sylvan magnetic needle", /*french*/"une aimant sylvestre", /*spanish*/"un imán enselvado"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Forest Temple Compass", /*french*/"la boussole du Temple de la Forêt", /*spanish*/"la brújula del Templo del Bosque"} - ); - hintTable[RHT_FIRE_TEMPLE_COMPASS] = HintText::Item({ - //obscure text - Text{"a molten treasure tracker", /*french*/"un cherche-trésor fondu", /*spanish*/"un zahorí fundido"}, - Text{"a molten magnetic needle", /*french*/"une aimant fondu", /*spanish*/"un imán fundido"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Fire Temple Compass", /*french*/"la boussole du Temple du Feu", /*spanish*/"la brújula del Templo del Fuego"} - ); - hintTable[RHT_WATER_TEMPLE_COMPASS] = HintText::Item({ - //obscure text - Text{"a wet treasure tracker", /*french*/"un cherche-trésor humide", /*spanish*/"un zahorí mojado"}, - Text{"a wet magnetic needle", /*french*/"une aimant humide", /*spanish*/"un imán mojado"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Water Temple Compass", /*french*/"la boussole du Temple de l'Eau", /*spanish*/"la brújula del Templo del Agua"} - ); - hintTable[RHT_SPIRIT_TEMPLE_COMPASS] = HintText::Item({ - //obscure text - Text{"a sandy treasure tracker", /*french*/"un cherche-trésor sableux", /*spanish*/"un zahorí arenoso"}, - Text{"a sandy magnetic needle", /*french*/"une aimant sableux", /*spanish*/"un imán arenoso"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Spirit Temple Compass", /*french*/"la boussole du Temple de l'Esprit", /*spanish*/"la brújula del Templo del Espíritu"} - ); - hintTable[RHT_SHADOW_TEMPLE_COMPASS] = HintText::Item({ - //obscure text - Text{"a creepy treasure tracker", /*french*/"un cherche-trésor sinistre", /*spanish*/"un zahorí siniestra"}, - Text{"a creepy magnetic needle", /*french*/"une aimant sinistre", /*spanish*/"un imán siniestra"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Shadow Temple Compass", /*french*/"la boussole du Temple de l'Ombre", /*spanish*/"la brújula del Templo de las Sombras"} - ); - hintTable[RHT_BOTTOM_OF_THE_WELL_COMPASS] = HintText::Item({ - //obscure text - Text{"a dank treasure tracker", /*french*/"un cherche-trésor moisi", /*spanish*/"un zahorí mohoso"}, - Text{"a dank magnetic needle", /*french*/"une aimant moisi", /*spanish*/"un imán mohoso"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Bottom of the Well Compass", /*french*/"la boussole du fond du Puits", /*spanish*/"la brújula del Fondo del pozo"} - ); - hintTable[RHT_ICE_CAVERN_COMPASS] = HintText::Item({ - //obscure text - Text{"a polar treasure tracker", /*french*/"un cherche-trésor polaire", /*spanish*/"un zahorí polar"}, - Text{"a polar magnetic needle", /*french*/"une aimant polaire", /*spanish*/"un imán polar"}, - }, { - //ambiguous text - Text{"a compass", /*french*/"une boussole", /*spanish*/"una brújula"}, - }, - //clear text - Text{"the Ice Cavern Compass", /*french*/"la Boussole de la Caverne Polaire", /*spanish*/"la brújula de la Caverna de hielo"} - ); - hintTable[RHT_FOREST_TEMPLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a sylvan master of unlocking", /*french*/"un anti-grosse porte sylvestre", /*spanish*/"la clave enselvada de un jefe"}, - Text{"a sylvan dungeon's master pass", /*french*/"une clé maléfique sylvestree", /*spanish*/"el pase maestro enselvado"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Forest Temple Boss Key", /*french*/"la Clé d'Or du Temple de la Forêt", /*spanish*/"la gran llave del Templo del Bosque"} - ); - hintTable[RHT_FIRE_TEMPLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a molten master of unlocking", /*french*/"un anti-grosse porte fondu", /*spanish*/"la clave fundido de un jefe"}, - Text{"a molten dungeon's master pass", /*french*/"une clé maléfique fondu", /*spanish*/"el pase maestro fundido"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Fire Temple Boss Key", /*french*/"la Clé d'Or du Temple du Feu", /*spanish*/"la gran llave del Templo del Fuego"} - ); - hintTable[RHT_WATER_TEMPLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a wet master of unlocking", /*french*/"un anti-grosse porte humide", /*spanish*/"la clave mojado de un jefe"}, - Text{"a wet dungeon's master pass", /*french*/"une clé maléfique humide", /*spanish*/"el pase maestro mojado"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Water Temple Boss Key", /*french*/"la Clé d'Or du Temple de l'Eau", /*spanish*/"la gran llave del Templo del Agua"} - ); - hintTable[RHT_SPIRIT_TEMPLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a sandy master of unlocking", /*french*/"un anti-grosse porte sableux", /*spanish*/"la clave arenoso de un jefe"}, - Text{"a sandy dungeon's master pass", /*french*/"une clé maléfique sableux", /*spanish*/"el pase maestro arenoso"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Spirit Temple Boss Key", /*french*/"la Clé d'Or du Temple de l'Esprit", /*spanish*/"la gran llave del Templo del Espíritu"} - ); - hintTable[RHT_SHADOW_TEMPLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a creepy master of unlocking", /*french*/"un anti-grosse porte sinistre", /*spanish*/"la clave siniestra de un jefe"}, - Text{"a creepy dungeon's master pass", /*french*/"une clé maléfique sinistre", /*spanish*/"el pase maestro siniestra"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Shadow Temple Boss Key", /*french*/"la Clé d'Or du Temple de l'Ombre", /*spanish*/"la gran llave del Templo de las Sombras"} - ); - hintTable[RHT_GANONS_CASTLE_BOSS_KEY] = HintText::Item({ - //obscure text - Text{"a final master of unlocking", /*french*/"un anti-grosse porte final", /*spanish*/"la clave final de un jefe"}, - Text{"a final dungeon's master pass", /*french*/"une clé maléfique final", /*spanish*/"el pase maestro final"}, - }, { - //ambiguous text - Text{"a boss key", /*french*/"une Clé d'Or", /*spanish*/"una gran llave"}, - }, - //clear text - Text{"the Ganon's Castle Boss Key", /*french*/"la Clé d'Or du Château de Ganon", /*spanish*/"la gran llave del Castillo de Ganon"} - ); - hintTable[RHT_FOREST_TEMPLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a sylvan tool for unlocking", /*french*/"un anti-porte sylvestre", /*spanish*/"una clave de una entrada enselvada"}, - Text{"a sylvan dungeon pass", /*french*/"le rêve sylvestre d'un prisonnier", /*spanish*/"un pase de una mazmorra enselvada"}, - Text{"a sylvan lock remover", /*french*/"un efface-serrure sylvestre", /*spanish*/"un destructor de cerraduras enselvada"}, - Text{"a sylvan lockpick", /*french*/"un crochet à porte sylvestre", /*spanish*/"una apertura portentosa enselvada"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Forest Temple Small Key", /*french*/"une petite clé du Temple de la Forêt", /*spanish*/"una llave pequeña del Templo del Bosque"} - ); - hintTable[RHT_FIRE_TEMPLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a molten tool for unlocking", /*french*/"un anti-porte fondu", /*spanish*/"una clave de una entrada fundida"}, - Text{"a molten dungeon pass", /*french*/"le rêve fondu d'un prisonnier", /*spanish*/"un pase de una mazmorra fundida"}, - Text{"a molten lock remover", /*french*/"un efface-serrure fondu", /*spanish*/"un destructor de cerraduras fundida"}, - Text{"a molten lockpick", /*french*/"un crochet à porte fondu", /*spanish*/"una apertura portentosa fundida"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Fire Temple Small Key", /*french*/"une petite clé du Temple du Feu", /*spanish*/"una llave pequeña del Templo del Fuego"} - ); - hintTable[RHT_WATER_TEMPLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a wet tool for unlocking", /*french*/"un anti-porte humide", /*spanish*/"una clave de una entrada mojada"}, - Text{"a wet dungeon pass", /*french*/"le rêve humide d'un prisonnier", /*spanish*/"un pase de una mazmorra mojada"}, - Text{"a wet lock remover", /*french*/"un efface-serrure humide", /*spanish*/"un destructor de cerraduras mojada"}, - Text{"a wet lockpick", /*french*/"un crochet à porte humide", /*spanish*/"una apertura portentosa mojada"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Water Temple Small Key", /*french*/"une petite clé du Temple de l'Eau", /*spanish*/"una llave pequeña del Templo del Agua"} - ); - hintTable[RHT_SPIRIT_TEMPLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a sandy tool for unlocking", /*french*/"un anti-porte sableux", /*spanish*/"una clave de una entrada arenosa"}, - Text{"a sandy dungeon pass", /*french*/"le rêve sableux d'un prisonnier", /*spanish*/"un pase de una mazmorra arenosa"}, - Text{"a sandy lock remover", /*french*/"un efface-serrure sableux", /*spanish*/"un destructor de cerraduras arenosa"}, - Text{"a sandy lockpick", /*french*/"un crochet à porte sableux", /*spanish*/"una apertura portentosa arenosa"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Spirit Temple Small Key", /*french*/"une petite clé du Temple de l'Esprit", /*spanish*/"una llave pequeña del Templo del Espíritu"} - ); - hintTable[RHT_SHADOW_TEMPLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a creepy tool for unlocking", /*french*/"un anti-porte sinistre", /*spanish*/"una clave de una entrada siniestra:a"}, - Text{"a creepy dungeon pass", /*french*/"le rêve sinistre d'un prisonnier", /*spanish*/"un pase de una mazmorra siniestra:a"}, - Text{"a creepy lock remover", /*french*/"un efface-serrure sinistre", /*spanish*/"un destructor de cerraduras siniestra:a"}, - Text{"a creepy lockpick", /*french*/"un crochet à porte sinistre", /*spanish*/"una apertura portentosa siniestra:a"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Shadow Temple Small Key", /*french*/"une petite clé du Temple de l'Ombre", /*spanish*/"una llave pequeña del Templo de las Sombras"} - ); - hintTable[RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a labyrinthian tool for unlocking", /*french*/"un anti-porte labyrinthique", /*spanish*/"una clave de una entrada laberíntica"}, - Text{"a labyrinthian dungeon pass", /*french*/"le rêve labyrinthique d'un prisonnier", /*spanish*/"un pase de una mazmorra laberíntica"}, - Text{"a labyrinthian lock remover", /*french*/"un efface-serrure labyrinthique", /*spanish*/"un destructor de cerraduras laberíntica"}, - Text{"a labyrinthian lockpick", /*french*/"un crochet à porte labyrinthique", /*spanish*/"una apertura portentosa laberíntica"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Gerudo Training Ground Small Key", /*french*/"une petite clé du Gymnase Gerudo", /*spanish*/"una llave pequeña del Centro de Instrucción Gerudo"} - ); - hintTable[RHT_GERUDO_FORTRESS_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"an imprisoned tool for unlocking", /*french*/"un anti-porte emprisonné", /*spanish*/"una clave de una entrada encarcelada"}, - Text{"an imprisoned dungeon pass", /*french*/"le rêve emprisonné d'un prisonnier", /*spanish*/"un pase de una mazmorra encarcelada"}, - Text{"an imprisoned lock remover", /*french*/"un efface-serrure emprisonné", /*spanish*/"un destructor de cerraduras encarcelada"}, - Text{"an imprisoned lockpick", /*french*/"un crochet à porte emprisonné", /*spanish*/"una apertura portentosa encarcelada"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Gerudo Fortress Small Key", /*french*/"une petite clé de la Repaire des Voleurs", /*spanish*/"una llave pequeña de la Fortaleza Gerudo"} - ); - hintTable[RHT_BOTTOM_OF_THE_WELL_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a moldy tool for unlocking", /*french*/"un anti-porte moisi", /*spanish*/"una clave de una entrada mohosa"}, - Text{"a moldy dungeon pass", /*french*/"le rêve moisi d'un prisonnier", /*spanish*/"un pase de una mazmorra mohosa"}, - Text{"a moldy lock remover", /*french*/"un efface-serrure moisi", /*spanish*/"un destructor de cerraduras mohosa"}, - Text{"a moldy lockpick", /*french*/"un crochet à porte moisi", /*spanish*/"una apertura portentosa mohosa"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Bottom of the Well Small Key", /*french*/"une petite clé du fond du Puits", /*spanish*/"una llave pequeña del Fondo del pozo"} - ); - hintTable[RHT_GANONS_CASTLE_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a final tool for unlocking", /*french*/"un anti-porte final", /*spanish*/"una clave de una entrada final"}, - Text{"a final dungeon pass", /*french*/"le rêve final d'un prisonnier", /*spanish*/"un pase de una mazmorra final"}, - Text{"a final lock remover", /*french*/"un efface-serrure final", /*spanish*/"un destructor de cerraduras final"}, - Text{"a final lockpick", /*french*/"un crochet à porte final", /*spanish*/"una apertura portentosa final"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Ganon's Castle Small Key", /*french*/"une petite clé du Château de Ganon", /*spanish*/"una llave pequeña del Castillo de Ganon"} - ); - hintTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a sylvan toolbox for unlocking", /*french*/"des anti-portes sylvestres", /*spanish*/"un conjunto silvestre de cerrajero"}, - Text{"a sylvan dungeon season pass", /*french*/"les rêves sylvestres d'un prisonnier", /*spanish*/"un pase vip de mazmorras silvestre"}, - Text{"a sylvan jingling ring", /*french*/"des efface-serrures sylvestres", /*spanish*/"una cadena multiusos silvestre"}, - Text{"a sylvan skeleton key", /*french*/"des crochets à porte sylvestres", /*spanish*/"un anillo silvestre contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Forest Temple Key Ring", /*french*/"un trousseau de clés du Temple de la Forêt", /*spanish*/"un llavero del Templo del Bosque"} - ); - hintTable[RHT_FIRE_TEMPLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a molten toolbox for unlocking", /*french*/"des anti-portes fondus", /*spanish*/"un conjunto fundido de cerrajero"}, - Text{"a molten dungeon season pass", /*french*/"les rêves fondus d'un prisonnier", /*spanish*/"un pase vip de mazmorras fundido"}, - Text{"a molten jingling ring", /*french*/"des efface-serrures fondus", /*spanish*/"una cadena multiusos fundida"}, - Text{"a molten skeleton key", /*french*/"des crochets à porte fondus", /*spanish*/"un anillo fundido contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Fire Temple Key Ring", /*french*/"un trousseau de clés du Temple du Feu", /*spanish*/"un llavero del Templo del Fuego"} - ); - hintTable[RHT_WATER_TEMPLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a wet toolbox for unlocking", /*french*/"des anti-portes humides", /*spanish*/"un conjunto abisal de cerrajero"}, - Text{"a wet dungeon season pass", /*french*/"les rêves humides d'un prisonnier", /*spanish*/"un pase vip de mazmorras abisal"}, - Text{"a wet jingling ring", /*french*/"des efface-serrures humides", /*spanish*/"una cadena multiusos abisal"}, - Text{"a wet skeleton key", /*french*/"des crochets à porte humides", /*spanish*/"un anillo abisal contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Water Temple Key Ring", /*french*/"un trousseau de clés du Temple de l'Eau", /*spanish*/"un llavero del Templo del Agua"} - ); - hintTable[RHT_SPIRIT_TEMPLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a sandy toolbox for unlocking", /*french*/"des anti-portes sableux", /*spanish*/"un conjunto arenoso de cerrajero"}, - Text{"a sandy dungeon season pass", /*french*/"les rêves sableux d'un prisonnier", /*spanish*/"un pase vip de mazmorras arenoso"}, - Text{"a sandy jingling ring", /*french*/"des efface-serrures sableux", /*spanish*/"una cadena multiusos arenosa"}, - Text{"a sandy skeleton key", /*french*/"des crochets à porte sableux", /*spanish*/"un anillo arenoso contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Spirit Temple Key Ring", /*french*/"un trousseau de clés du Temple de l'Esprit", /*spanish*/"un llavero del Templo del Espíritu"} - ); - hintTable[RHT_SHADOW_TEMPLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a creepy toolbox for unlocking", /*french*/"des anti-portes sinistres", /*spanish*/"un conjunto tenebroso de cerrajero"}, - Text{"a creepy dungeon season pass", /*french*/"les rêves sinistres d'un prisonnier", /*spanish*/"un pase vip de mazmorras tenebroso"}, - Text{"a creepy jingling ring", /*french*/"des efface-serrures sinistres", /*spanish*/"una cadena multiusos tenebrosa"}, - Text{"a creepy skeleton key", /*french*/"des crochets à porte sinistres", /*spanish*/"un anillo tenebroso contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Shadow Temple Key Ring", /*french*/"un trousseau de clés du Temple de l'Ombre", /*spanish*/"un llavero del Templo de las Sombras"} - ); - hintTable[RHT_GERUDO_TRAINING_GROUNDS_KEY_RING] = HintText::Item({ - //obscure text - Text{"a labyrinthian toolbox for unlocking", /*french*/"des anti-portes labyrinthiques", /*spanish*/"un conjunto laberíntico de cerrajero"}, - Text{"a labyrinthian dungeon season pass", /*french*/"les rêves labyrinthiques d'un prisonnier", /*spanish*/"un pase vip de mazmorras laberíntico"}, - Text{"a labyrinthian jingling ring", /*french*/"des efface-serrures labyrinthiques", /*spanish*/"una cadena multiusos laberíntica"}, - Text{"a labyrinthian skeleton key", /*french*/"des crochets à porte labyrinthiques", /*spanish*/"un anillo laberíntico contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Gerudo Training Ground Key Ring", /*french*/"un trousseau de clés du Gymnase Gerudo", /*spanish*/"un llavero del Centro de Instrucción Gerudo"} - ); - hintTable[RHT_GERUDO_FORTRESS_KEY_RING] = HintText::Item({ - //obscure text - Text{"an imprisoned toolbox for unlocking", /*french*/"des anti-portes emprisonnés", /*spanish*/"un conjunto enjaulado de cerrajero"}, - Text{"an imprisoned dungeon season pass", /*french*/"les rêves emprisonnés d'un prisonnier", /*spanish*/"un pase vip de una mazmorra enjaulado"}, - Text{"an imprisoned jingling ring", /*french*/"des efface-serrures emprisonnés", /*spanish*/"una cadena multiusos enjaulada"}, - Text{"an imprisoned skeleton key", /*french*/"des crochets à porte emprisonnés", /*spanish*/"un anillo enjaulado contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Gerudo Fortress Key Ring", /*french*/"un trousseau de clés de la Repaire des Voleurs", /*spanish*/"un llavero de la Fortaleza Gerudo"} - ); - hintTable[RHT_BOTTOM_OF_THE_WELL_KEY_RING] = HintText::Item({ - //obscure text - Text{"a moldy toolbox for unlocking", /*french*/"des anti-portes moisis", /*spanish*/"un conjunto subterráneo de cerrajero"}, - Text{"a moldy dungeon season pass", /*french*/"les rêves moisis d'un prisonnier", /*spanish*/"un pase vip de una mazmorra subterráneo"}, - Text{"a moldy jingling ring", /*french*/"des efface-serrures moisis", /*spanish*/"una cadena multiusos subterránea"}, - Text{"a moldy skeleton key", /*french*/"des crochets à porte moisis", /*spanish*/"un anillo subterráneo contra cerrojos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Bottom of the Well Key Ring", /*french*/"un trousseau de clés du fond du Puits", /*spanish*/"un llavero del Fondo del pozo"} - ); - hintTable[RHT_GANONS_CASTLE_KEY_RING] = HintText::Item({ - //obscure text - Text{"a final toolbox for unlocking", /*french*/"des anti-portes finaux", /*spanish*/"un conjunto decisivo de cerrajero"}, - Text{"a final dungeon season pass", /*french*/"les rêves finaux d'un prisonnier", /*spanish*/"un pase vip de una mazmorra decisivo"}, - Text{"a final jingling ring", /*french*/"des efface-serrures finaux", /*spanish*/"una cadena multiusos decisiva"}, - Text{"a final skeleton key", /*french*/"des crochets à porte finaux", /*spanish*/"un anillo decisivo multiusos"}, - }, { - //ambiguous text - Text{"a key ring", /*french*/"un trousseau de clés", /*spanish*/"un llavero"}, - }, - //clear text - Text{"a Ganon's Castle Key Ring", /*french*/"un trousseau de clés du Château de Ganon", /*spanish*/"un llavero del Castillo de Ganon"} - ); - - hintTable[RHT_TREASURE_GAME_SMALL_KEY] = HintText::Item({ - //obscure text - Text{"a gambler's tool for unlocking", /*french*/"un anti-porte de parieur", /*spanish*/"una clave de un juego de azar"}, - Text{"a gambler's dungeon pass", /*french*/"le rêve d'un prisonnier parieur", /*spanish*/"un pase de un juego de azar"}, - Text{"a gambler's lock remover", /*french*/"un efface-serrure de parieur", /*spanish*/"un destructor de cerraduras del juego de azar"}, - Text{"a gambler's lockpick", /*french*/"un crochet à serrure de parieur", /*spanish*/"una apertura portentosa del juego de azar"}, - }, { - //ambiguous text - Text{"a small key", /*french*/"une petite clé", /*spanish*/"una llave pequeña"}, - }, - //clear text - Text{"a Treasure Chest Shop Small Key", /*french*/"une petite clé de la chasse aux trésors", /*spanish*/"una llave pequeña del Cofre del Tesoro"} - ); - - hintTable[RHT_KOKIRI_EMERALD] = HintText::Item({ - //obscure text - Text{"a green stone", /*french*/"une pierre verte", /*spanish*/"una piedra verde"}, - Text{"a gift before death", /*french*/"le dernier souffle d'un arbre", /*spanish*/"un obsequio testamentario"}, - }, { - //ambiguous text - Text{"a spiritual stone", /*french*/"une Pierre Ancestrale", /*spanish*/"una piedra espiritual"}, - }, - //clear text - Text{"the Kokiri Emerald", /*french*/"l'Émeraude Kokiri", /*spanish*/"la Esmeralda de los Kokiri"} - ); - - hintTable[RHT_GORON_RUBY] = HintText::Item({ - //obscure text - Text{"a red stone", /*french*/"une pierre rouge", /*spanish*/"una piedra carmín"}, - Text{"sworn brotherhood", /*french*/"un serment de fraternité", /*spanish*/"el juramento de hermanos de sangre"}, - }, { - //ambiguous text - Text{"a spiritual stone", /*french*/"une Pierre Ancestrale", /*spanish*/"una piedra espiritual"}, - }, - //clear text - Text{"the Goron Ruby", /*french*/"le Rubis Goron", /*spanish*/"el Rubí de los Goron"} - ); - - hintTable[RHT_ZORA_SAPPHIRE] = HintText::Item({ - //obscure text - Text{"a blue stone", /*french*/"une pierre bleue", /*spanish*/"una piedra celeste"}, - Text{"an engagement gift", /*french*/"un cadeau de mariage", /*spanish*/"un regalo de compromiso"}, - }, { - //ambiguous text - Text{"a spiritual stone", /*french*/"une Pierre Ancestrale", /*spanish*/"una piedra espiritual"}, - }, - //clear text - Text{"the Zora Sapphire", /*french*/"le Saphir Zora", /*spanish*/"el Zafiro de los Zora"} - ); - - hintTable[RHT_FOREST_MEDALLION] = HintText::Item({ - //obscure text - Text{"a green coin", /*french*/"une pièce verte", /*spanish*/"una moneda esmeralda"}, - Text{"Saria's friendship", /*french*/"l'amitié de Saria", /*spanish*/"la amistad de Saria"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Forest Medallion", /*french*/"le Médaillon de la Forêt", /*spanish*/"el Medallón del Bosque"} - ); - - hintTable[RHT_FIRE_MEDALLION] = HintText::Item({ - //obscure text - Text{"a red coin", /*french*/"une pièce rouge", /*spanish*/"una moneda rubí"}, - Text{"Darunia's power", /*french*/"la fraternité de Darunia", /*spanish*/"la fraternidad de Darunia"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Fire Medallion", /*french*/"le Médaillon du Feu", /*spanish*/"el Medallón del Fuego"} - ); - - hintTable[RHT_WATER_MEDALLION] = HintText::Item({ - //obscure text - Text{"a blue coin", /*french*/"une pièce bleue", /*spanish*/"una moneda zafiro"}, - Text{"Ruto's power", /*french*/"l'amour de Ruto", /*spanish*/"el amor de Ruto"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Water Medallion", /*french*/"le Médaillon de l'Eau", /*spanish*/"el Medallón del Agua"} - ); - - hintTable[RHT_SPIRIT_MEDALLION] = HintText::Item({ - //obscure text - Text{"an orange coin", /*french*/"une pièce orange", /*spanish*/"una moneda ámbar"}, - Text{"Nabooru's power", /*french*/"le respect de Nabooru", /*spanish*/"el respeto de Nabooru"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Spirit Medallion", /*french*/"le Médaillon de l'Esprit", /*spanish*/"el Medallón del Espíritu"} - ); - - hintTable[RHT_SHADOW_MEDALLION] = HintText::Item({ - //obscure text - Text{"a purple coin", /*french*/"une pièce pourpre", /*spanish*/"una moneda malva"}, - Text{"Impa's power", /*french*/"la confiance d'Impa", /*spanish*/"la confianza de Impa"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Shadow Medallion", /*french*/"le Médaillon de l'Ombre", /*spanish*/"el Medallón de la Sombra"} - ); - - hintTable[RHT_LIGHT_MEDALLION] = HintText::Item({ - //obscure text - Text{"a yellow coin", /*french*/"une pièce jaune", /*spanish*/"una moneda resplandeciente"}, - Text{"Rauru's power", /*french*/"la foi de Rauru", /*spanish*/"la fe de Rauru"}, - }, { - //ambiguous text - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - }, - //clear text - Text{"the Light Medallion", /*french*/"le Médaillon de la Lumière", /*spanish*/"el Medallón de la Luz"} - ); - - hintTable[RHT_RECOVERY_HEART] = HintText::Item({ - //obscure text - Text{"a free heal", /*french*/"un bec-au-bobo", /*spanish*/"una cura de regalo"}, - Text{"a hearty meal", /*french*/"un petit amour", /*spanish*/"una sanación romántica"}, - Text{"a Band-Aid", /*french*/"un diachylon", /*spanish*/"un corazoncito sanador"}, - }, { - //ambiguous text - Text{"something heart-shaped", /*french*/"une chose en forme de coeur", /*spanish*/"algo con forma de corazón"}, - }, - //clear text - Text{"a Recovery Heart", /*french*/"un coeur de vie", /*spanish*/"un corazón"} - ); - - hintTable[RHT_GREEN_RUPEE] = HintText::Item({ - //obscure text - Text{"a unique coin", /*french*/"un rubis bien mérité", /*spanish*/"una singular moneda"}, - Text{"a penny", /*french*/"un sou", /*spanish*/"un peso hyliano"}, - Text{"a green gem", /*french*/"un joyau vert", /*spanish*/"una gema verde"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Green Rupee", /*french*/"un rubis vert", /*spanish*/"una rupia verde"} - ); - - hintTable[RHT_GREG_RUPEE] = HintText::Item({ - //obscure text - Text{"an old friend", /*french*/"Greg", /*spanish*/"Greg"}, - Text{"a glorious gem", /*french*/"Greg", /*spanish*/"Greg"}, - }, { - //ambiguous text - Text{"a Green Rupee", /*french*/"un rubis vert", /*spanish*/"una rupia verde"} - }, - //clear text - Text{"Greg", /*french*/"Greg", /*spanish*/"Greg"} - ); - - hintTable[RHT_BLUE_RUPEE] = HintText::Item({ - //obscure text - Text{"a common coin", /*french*/"quelques sous", /*spanish*/"una moneda usual"}, - Text{"a blue gem", /*french*/"un joyau bleu", /*spanish*/"una gema azul"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Blue Rupee", /*french*/"un rubis bleu", /*spanish*/"una rupia azul"} - ); - - hintTable[RHT_RED_RUPEE] = HintText::Item({ - //obscure text - Text{"couch cash", /*french*/"un peu de fric", /*spanish*/"una buena moneda"}, - Text{"a red gem", /*french*/"un joyau rouge", /*spanish*/"una gema roja"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Red Rupee", /*french*/"un rubis rouge", /*spanish*/"una rupia roja"} - ); - - hintTable[RHT_PURPLE_RUPEE] = HintText::Item({ - //obscure text - Text{"big bucks", /*french*/"plein de fric", /*spanish*/"plata de calidad"}, - Text{"a purple gem", /*french*/"un joyau mauve", /*spanish*/"una gema morada"}, - Text{"wealth", /*french*/"la richesse", /*spanish*/"una buena riqueza"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Purple Rupee", /*french*/"un rubis pourpre", /*spanish*/"una rupia morada"} - ); - - hintTable[RHT_HUGE_RUPEE] = HintText::Item({ - //obscure text - Text{"a juicy jackpot", /*french*/"le jackpot", /*spanish*/"el premio gordo"}, - Text{"a yellow gem", /*french*/"un joyau doré", /*spanish*/"una gema amarilla"}, - Text{"a giant gem", /*french*/"un gros joyau", /*spanish*/"una gema descomunal"}, - Text{"great wealth", /*french*/"l'aisance financière", /*spanish*/"dinero a caudales"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Huge Rupee", /*french*/"un énorme rubis", /*spanish*/"una rupia gigante"} - ); - - hintTable[RHT_PIECE_OF_HEART] = HintText::Item({ - //obscure text - Text{"a little love", /*french*/"un peu plus d'amour", /*spanish*/"un cuarto de amor"}, - Text{"a broken heart", /*french*/"un coeur brisé", /*spanish*/"un corazón roto"}, - }, { - //ambiguous text - Text{"something heart-shaped", /*french*/"une chose en forme de coeur", /*spanish*/"algo con forma de corazón"}, - }, - //clear text - Text{"a Piece of Heart", /*french*/"un Quart de Coeur", /*spanish*/"una pieza de corazón"} - ); - - hintTable[RHT_HEART_CONTAINER] = HintText::Item({ - //obscure text - Text{"a lot of love", /*french*/"le grand amour", /*spanish*/"amor por doquier"}, - Text{"a Valentine's gift", /*french*/"un cadeau de Saint-Valentin", /*spanish*/"un contenedor de afección"}, - Text{"a boss's organ", /*french*/"un organe de monstre", /*spanish*/"los órganos de un jefe"}, - }, { - //ambiguous text - Text{"something heart-shaped", /*french*/"une chose en forme de coeur", /*spanish*/"algo con forma de corazón"}, - }, - //clear text - Text{"a Heart Container", /*french*/"un Réceptacle de Coeur", /*spanish*/"un contenedor de corazón"} - ); - - hintTable[RHT_ICE_TRAP] = HintText::Item({ - //obscure text - Text{"a gift from Ganon", /*french*/"un cadeau de Ganon", /*spanish*/"un regalo de Ganon"}, - Text{"a chilling discovery", /*french*/"une frissonante découverte", /*spanish*/"un escalofriante hallazgo"}, - Text{"frosty fun", /*french*/"une engelure", /*spanish*/"una gélida diversión"}, - }, { - //ambiguous text - Text{"a Great Fairy's power", /*french*/"le pouvoir d'une grande fée", /*spanish*/"el poder de una Gran Hada"}, - Text{"a magic arrow", /*french*/"une flèche magique", /*spanish*/"una flecha mágica"}, - Text{"a medallion", /*french*/"un médaillon", /*spanish*/"un medallón"}, - Text{"a spiritual stone", /*french*/"une Pierre Ancestrale", /*spanish*/"una piedra espiritual"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"an Ice Trap", /*french*/"un Piège de Glace", /*spanish*/"una trampa de hielo"} - ); - - //RHT_MILK - - hintTable[RHT_BOMBS_5] = HintText::Item({ - //obscure text - Text{"a few explosives", /*french*/"une poignée de pétards", /*spanish*/"un par de explosivos"}, - Text{"a few blast balls", /*french*/"une poignée de boules bleues", /*spanish*/"un par de estallidos"}, - }, { - //ambiguous text - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombs (5 pieces)", /*french*/"une demi-dizaine de bombes", /*spanish*/"unas (5) bombas"} - ); - - hintTable[RHT_BOMBS_10] = HintText::Item({ - //obscure text - Text{"some explosives", /*french*/"un paquet de pétards", /*spanish*/"unos cuantos explosivos"}, - Text{"some blast balls", /*french*/"un paquet de boules bleues", /*spanish*/"unos cuantos estallidos"}, - }, { - //ambiguous text - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombs (10 pieces)", /*french*/"une dizaine de bombes", /*spanish*/"unas (10) bombas"} - ); - - hintTable[RHT_BOMBS_20] = HintText::Item({ - //obscure text - Text{"lots-o-explosives", /*french*/"une abondance de pétards", /*spanish*/"un puñado de explosivos"}, - Text{"plenty of blast balls", /*french*/"une abondance de boules bleues", /*spanish*/"bastantes estallidos"}, - }, { - //ambiguous text - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombs (20 pieces)", /*french*/"une vingtaine de bombes", /*spanish*/"unas (20) bombas"} - ); - - hintTable[RHT_BOMBCHU_5] = HintText::Item({ - //obscure text - Text{"a few mice bombs", /*french*/"une poignée de mignons explosifs", /*spanish*/"un par de bombas roedoras"}, - Text{"a few proximity mice", /*french*/"une poignée de jouets à remonter", /*spanish*/"un par de explosivos ratoncitos"}, - Text{"a few wall crawlers", /*french*/"une poignée de rapides grimpeurs", /*spanish*/"un par de trepaparedes"}, - Text{"a few trail blazers", /*french*/"une poignée de zigzags éclatants", /*spanish*/"un par de ratas propulsadas"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombchus (5 pieces)", /*french*/"une demi-dizaine de Missiles", /*spanish*/"unos (5) bombchus"} - ); - - hintTable[RHT_BOMBCHU_10] = HintText::Item({ - //obscure text - Text{"some mice bombs", /*french*/"un paquet de mignons explosifs", /*spanish*/"unas cuantas bombas roedoras"}, - Text{"some proximity mice", /*french*/"un paquet de jouets à remonter", /*spanish*/"unos cuantos explosivos ratoncitos"}, - Text{"some wall crawlers", /*french*/"un paquet de rapides grimpeurs", /*spanish*/"unos cuantos trepaparedes"}, - Text{"some trail blazers", /*french*/"un paquet de zigzags éclatants", /*spanish*/"unas cuantas ratas propulsadas"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombchus (10 pieces)", /*french*/"une dizaine de Missiles", /*spanish*/"unos (10) bombchus"} - ); - - hintTable[RHT_BOMBCHU_20] = HintText::Item({ - //obscure text - Text{"plenty of mice bombs", /*french*/"une abondance de mignons explosifs", /*spanish*/"bastantes bombas roedoras"}, - Text{"plenty of proximity mice", /*french*/"une abondance de jouets à remonter", /*spanish*/"bastantes explosivos ratoncitos"}, - Text{"plenty of wall crawlers", /*french*/"une abondance de rapides grimpeurs", /*spanish*/"bastantes trepaparedes"}, - Text{"plenty of trail blazers", /*french*/"une abondance de zigzags éclatants", /*spanish*/"bastantes ratas propulsadas"}, - }, { - //ambiguous text - Text{"a prize of the House of Skulltulas", /*french*/"un prix de la maison des Skulltulas", /*spanish*/"un obsequio de la Casa Skulltula"}, - Text{"explosives", /*french*/"un paquet d'explosifs", /*spanish*/"un montón de explosivos"}, - }, - //clear text - Text{"Bombchus (20 pieces)", /*french*/"une vingtaine de Missiles", /*spanish*/"unos (20) bombchus"} - ); - - //RHT_BOMBCHU_DROP - - hintTable[RHT_ARROWS_5] = HintText::Item({ - //obscure text - Text{"a few danger darts", /*french*/"une poignée d'obus", /*spanish*/"un par de peligrosos dardos"}, - Text{"a few sharp shafts", /*french*/"une poignée de piquets", /*spanish*/"un par de puntas afiladas"}, - }, { - //ambiguous text - Text{"a projectile", /*french*/"un projectile", /*spanish*/"un proyectil"}, - }, - //clear text - Text{"Arrows (5 pieces)", /*french*/"une demi-dizaine de flèches", /*spanish*/"unas (5) flechas"} - ); - - hintTable[RHT_ARROWS_10] = HintText::Item({ - //obscure text - Text{"some danger darts", /*french*/"un paquet d'obus", /*spanish*/"unos cuantos peligrosos dardos"}, - Text{"some sharp shafts", /*french*/"un paquet de piquets", /*spanish*/"unas cuantas puntas afiladas"}, - }, { - //ambiguous text - Text{"a projectile", /*french*/"un projectile", /*spanish*/"un proyectil"}, - }, - //clear text - Text{"Arrows (10 pieces)", /*french*/"une dizaine de flèches", /*spanish*/"unas (10) flechas"} - ); - - hintTable[RHT_ARROWS_30] = HintText::Item({ - //obscure text - Text{"plenty of danger darts", /*french*/"une abondance d'obus", /*spanish*/"bastantes peligrosos dardos"}, - Text{"plenty of sharp shafts", /*french*/"une abondance de piquets", /*spanish*/"bastantes puntas afiladas"}, - }, { - //ambiguous text - Text{"a projectile", /*french*/"un projectile", /*spanish*/"un proyectil"}, - }, - //clear text - Text{"Arrows (30 pieces)", /*french*/"une trentaine de flèches", /*spanish*/"unas (30) flechas"} - ); - - hintTable[RHT_DEKU_NUTS_5] = HintText::Item({ - //obscure text - Text{"some nuts", /*french*/"une poignée de noisettes", /*spanish*/"un par de nueces"}, - Text{"some flashbangs", /*french*/"une poignée d'éclats", /*spanish*/"un par de semillas aturdidoras"}, - Text{"some scrub spit", /*french*/"une poignée de crachats Mojo", /*spanish*/"un par de escupitajos deku"}, - }, { - //ambiguous text - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"Deku Nuts (5 pieces)", /*french*/"une demi-dizaine de noix Mojo", /*spanish*/"unas (5) nueces deku"} - ); - - hintTable[RHT_DEKU_NUTS_10] = HintText::Item({ - //obscure text - Text{"lots-o-nuts", /*french*/"un paquet de noisettes", /*spanish*/"un puñado de nueces"}, - Text{"plenty of flashbangs", /*french*/"un paquet d'éclats", /*spanish*/"unas cuantas semillas aturdidoras"}, - Text{"plenty of scrub spit", /*french*/"un paquet de crachats Mojo", /*spanish*/"unos cuantos escupitajos deku"}, - }, { - //ambiguous text - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - Text{"something that can stun", /*french*/"une chose qui peut paralyser", /*spanish*/"algo que pueda paralizar"}, - }, - //clear text - Text{"Deku Nuts (10 pieces)", /*french*/"une dizaine de noix Mojo", /*spanish*/"unas (10) nueces deku"} - ); - - hintTable[RHT_DEKU_SEEDS_30] = HintText::Item({ - //obscure text - Text{"catapult ammo", /*french*/"un paquet de délicieuses munitions", /*spanish*/"un par de munición infantil"}, - Text{"lots-o-seeds", /*french*/"un paquet de germes séchés", /*spanish*/"un puñado de semillas"}, - }, { - //ambiguous text - Text{"a projectile", /*french*/"un projectile", /*spanish*/"un proyectil"}, - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - }, - //clear text - Text{"Deku Seeds (30 pieces)", /*french*/"une trentaine de graines Mojo", /*spanish*/"unas (30) semillas deku"} - ); - - hintTable[RHT_DEKU_STICK_1] = HintText::Item({ - //obscure text - Text{"a breakable branch", /*french*/"un bout de bois", /*spanish*/"un pequeño báculo"}, - }, { - //ambiguous text - Text{"some Deku munitions", /*french*/"un paquet de munitions Mojo", /*spanish*/"un montón de municiones Deku"}, - }, - //clear text - Text{"a Deku Stick", /*french*/"un bâton Mojo", /*spanish*/"un palo deku"} - ); - - hintTable[RHT_TREASURE_GAME_HEART] = HintText::Item({ - //obscure text - Text{"a victory valentine", /*french*/"un amour gagnant", /*spanish*/"el amor victorioso"}, - }, { - //ambiguous text - Text{"something heart-shaped", /*french*/"une chose en forme de coeur", /*spanish*/"algo con forma de corazón"}, - }, - //clear text - Text{"a Piece of Heart", /*french*/"un Quart de Coeur", /*spanish*/"el amor de la victoria"} - ); - - hintTable[RHT_TREASURE_GAME_GREEN_RUPEE] = HintText::Item({ - //obscure text - Text{"the dollar of defeat", /*french*/"le rubis de la défaite", /*spanish*/"el peso de la derrota"}, - }, { - //ambiguous text - Text{"some rupees", /*french*/"une quantité de rubis", /*spanish*/"una cantidad de rupias"}, - }, - //clear text - Text{"a Green Rupee", /*french*/"un rubis vert", /*spanish*/"una rupia verde"} - ); - - hintTable[RHT_TRIFORCE_PIECE] = HintText::Item({ - //obscure text - Text{"a triumph fork", /*french*/"la Tribosse", /*spanish*/"un trígono del triunfo"}, - Text{"cheese", /*french*/"du fromage", /*spanish*/"un porción de queso"}, - Text{"a gold fragment", /*french*/"un fragment d'or", /*spanish*/"un fragmento dorado"}, - }, {}, - //clear text - Text{"a Piece of the Triforce", /*french*/"un fragment de la Triforce", /*spanish*/"un fragmento de la Trifuerza"} - ); - - hintTable[RHT_GOHMA_SOUL] = HintText::Item({ - //obscure text - Text{"an invasive soul", "", ""}, - Text{"some spider essence", "", ""}, - }, { - //ambiguous text - Text{"something webbed", "", ""} - }, { - //clear text - Text{"the soul of Gohma", "", ""}} - ); - - hintTable[RHT_KING_DODONGO_SOUL] = HintText::Item({ - //obscure text - Text{"a royal soul", "", ""}, - Text{"some reptile essence", "", ""}, - }, { - //ambiguous text - Text{"something explosive", "", ""} - }, { - //clear text - Text{"the soul of King Dodongo", "", ""}} - ); - - hintTable[RHT_BARINADE_SOUL] = HintText::Item({ - //obscure text - Text{"an infectuous soul", "", ""}, - Text{"some parasitic essence", "", ""}, - }, { - //ambiguous text - Text{"something fishy", "", ""} - }, { - //clear text - Text("the soul of Barinade", "", "")} - ); - - hintTable[RHT_PHANTOM_GANON_SOUL] = HintText::Item({ - //obscure text - Text{"a duplicate soul", "", ""}, - Text{"some illusionary essence", "", ""}, - }, { - //ambiguous text - Text{"something spectral", "", ""} - }, { - //clear text - Text{"the soul of Phantom Ganon", "", ""}} - ); - - hintTable[RHT_VOLVAGIA_SOUL] = HintText::Item({ - //obscure text - Text{"a draconic soul", "", ""}, - Text{"some magmatic essence", "", ""}, - }, { - //ambiguous text - Text{"something hot", "", ""} - }, { - //clear text - Text{"the soul of Volvagia", "", ""}} - ); - - hintTable[RHT_MORPHA_SOUL] = HintText::Item({ - //obscure text - Text{"an aquatic soul", "", ""}, - Text{"some liquid essence", "", ""}, - }, { - //ambiguous text - Text{"something wet", "", ""} - }, { - //clear text - Text{"the soul of Barinade", "", ""}} - ); - - hintTable[RHT_BONGO_BONGO_SOUL] = HintText::Item({ - //obscure text - Text{"a shadowy soul", "", ""}, - Text{"some handy essence", "", ""}, - }, { - //ambiguous text - Text{"something dark", "", ""} - }, { - //clear text - Text{"the soul of Bongo Bongo", "", ""}} - ); - - hintTable[RHT_TWINROVA_SOUL] = HintText::Item({ - //obscure text - Text{"old souls", "", ""}, - Text{"twin essences", "", ""}, - }, { - //ambiguous text - Text{"something spiritual", "", ""} - }, { - //clear text - Text{"the soul of Twinrova", "", ""}} - ); - - hintTable[RHT_GANON_SOUL] = HintText::Item({ - //obscure text - Text{"an evil soul", "", ""}, - Text{"some powerful essence", "", ""}, - }, { - //ambiguous text - Text{"something strong", "", ""} - }, { - //clear text - Text{"the soul of Ganon", "", ""}} - ); - - hintTable[RHT_OCARINA_A_BUTTON] = HintText::Item({ - //obscure text - Text{"a musical letter", /*french*/"une lettre musicale", /*spanish*/"una letra musical"}, - }, { - //ambiguous text - Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"} - }, { - //clear text - Text{"an Ocarina A Button", /*french*/"la Touche A de l'Ocarina", /*spanish*/"un botón A de Ocarina"}} - ); - - hintTable[RHT_OCARINA_C_UP_BUTTON] = HintText::Item({ - //obscure text - Text{"a high tone", /*french*/"une tonalité élevée", /*spanish*/"un tono alto"}, - }, { - //ambiguous text - Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"} - }, { - //clear text - Text{"an Ocarina C Up Button", /*french*/"la Touche C-Haut de l'Ocarina", /*spanish*/"un botón C superior de Ocarina"}} - ); - - hintTable[RHT_OCARINA_C_DOWN_BUTTON] = HintText::Item({ - //obscure text - Text{"a low tone", /*french*/"une tonalité basse", /*spanish*/"un tono bajo"}, - }, { - //ambiguous text - Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"} - }, { - //clear text - Text{"an Ocarina C Down Button", /*french*/"la Touche C-Bas de l'Ocarina", /*spanish*/"un botón C inferior de Ocarina"}} - ); - - hintTable[RHT_OCARINA_C_LEFT_BUTTON] = HintText::Item({ - //obscure text - Text{"a leftward tone", /*french*/"une tonalité vers la gauche", /*spanish*/"un tono hacia la izquierda"}, - }, { - //ambiguous text - Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"} - }, { - //clear text - Text{"an Ocarina C Left Button", /*french*/"la Touche C-Gauche de l'Ocarina", /*spanish*/"un botón C izquierdo de Ocarina"}} - ); - - hintTable[RHT_OCARINA_C_RIGHT_BUTTON] = HintText::Item({ - //obscure text - Text{"a rightward tone", /*french*/"une tonalité vers la droite", /*spanish*/"un tono hacia la derecha"}, - }, { - //ambiguous text - Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"} - }, { - //clear text - Text{"an Ocarina C Right Button", /*french*/"la Touche C-Droit de l'Ocarina", /*spanish*/"un botón C derecho de Ocarina"}} - ); - - hintTable[RHT_FISHING_POLE] = HintText::Item({ - //obscure text - Text{"a fish-puller", /*french*/"(canne à pêche)", /*spanish*/"(caña de pescar)"}, - }, { - //ambiguous text - Text{"the pond owner's property", /*french*/"(canne à pêche)", /*spanish*/"(caña de pescar)"}, - }, - //clear text - Text{"a fishing pole", /*french*/"canne à pêche", /*spanish*/"caña de pescar"} - ); - - hintTable[RHT_EPONA] = HintText::Item({ - //obscure text - Text{"a horse", /*french*/"un fidèle destrier", /*spanish*/"una yegua"}, - Text{"a four legged friend", /*french*/"un puissant animal", /*spanish*/"una amiga cuadrúpeda"}, - }, { - //ambiguous text - Text{"something from Malon", /*french*/"un cadeau de Malon", /*spanish*/"un obsequio de Malon"}, - Text{"a song sung by frogs", /*french*/"une chanson aimée des grenouilles", /*spanish*/"una melodía de ranas"}, - Text{"something to cross a broken bridge", /*french*/"une chose pour traverser un pont brisé", /*spanish*/"algo para cruzar un puente roto"}, - }, - //clear text - Text{"Epona", /*french*/"Epona", /*spanish*/"a Epona"} - ); - hintTable[RHT_HINT_MYSTERIOUS] = HintText::Item({ - Text{"something mysterious", /*french*/"un sacré mystère", /*spanish*/"algo misterioso", /*german*/"etwas Unvorhergesehenes"}, - Text{"an unknown treasure", /*french*/"un trésor inconnu", /*spanish*/"un desconocido tesoro", /*german*/"ein unbekannter Schatz"}, - }); - - // [RHT_HINT_ERROR] = HintText::Item({ - // //obscure text - // Text{"something mysterious", /*french*/"un sacré mystère", /*spanish*/"algo misterioso"}, - // Text{"an unknown treasure", /*french*/"un trésor inconnu", /*spanish*/"un desconocido tesoro"}, - // }, - // //clear text - // Text{"An Error (Please Report This)", /*french*/"une erreur (signaler S.V.P.)", /*spanish*/"un error (repórtelo si es posible)"} - // ); +#include "../../static_data.h" +#include "../hints.hpp" +#include "../../../custom-message/CustomMessageManager.h" + +namespace Rando { + +void StaticData::HintTable_Init_Item() { + + hintTextTable[RHT_KOKIRI_SWORD] = HintText(CustomMessage("the Kokiri Sword", /*german*/"", /*french*/"l'Épée Kokiri"), + // /*spanish*/la Espada Kokiri + { + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("a butter knife", /*german*/"", /*french*/"un couteau à beurre"), + // /*spanish*/un ágil puñal + CustomMessage("a starter slasher", /*german*/"", /*french*/"une arme de débutant"), + // /*spanish*/una hoja de principiantes + CustomMessage("a switchblade", /*german*/"", /*french*/"un canif")}); + // /*spanish*/una navaja + + hintTextTable[RHT_MASTER_SWORD] = HintText(CustomMessage("the Master Sword", /*german*/"", /*french*/"l'Épée de Légende"), + // /*spanish*/la Espada Maestra + { + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("evil's bane", /*german*/"", /*french*/"le fléau du mal"), + // /*spanish*/la destructora del mal + CustomMessage("a seven year limbo", /*german*/"", /*french*/"une stase de sept ans")}); + // /*spanish*/unos siete años de espera + + hintTextTable[RHT_GIANTS_KNIFE] = HintText(CustomMessage("the Giant's Knife", /*german*/"", /*french*/"la Lame des Géants"), + // /*spanish*/la daga gigante + { + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("a fragile blade", /*german*/"", /*french*/"une lame fragile"), + // /*spanish*/una frágil hoja + CustomMessage("a breakable cleaver", /*german*/"", /*french*/"un espadon de verre")}); + // /*spanish*/un rompible acero + + hintTextTable[RHT_BIGGORON_SWORD] = HintText(CustomMessage("the Biggoron Sword", /*german*/"", /*french*/"l'Épée de Biggoron"), + // /*spanish*/la Espada de Biggoron + { + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("the biggest blade", /*german*/"", /*french*/"une lame gigantesque"), + // /*spanish*/el mayor mandoble + CustomMessage("a colossal cleaver", /*german*/"", /*french*/"un espadon colossal")}); + // /*spanish*/un estoque colosal + + hintTextTable[RHT_DEKU_SHIELD] = HintText(CustomMessage("a Deku Shield", /*german*/"", /*french*/"un Bouclier Mojo"), + // /*spanish*/un escudo deku + { + CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + // /*spanish*/un escudo + }, { + CustomMessage("a wooden ward", /*german*/"", /*french*/"un écu d'écorce"), + // /*spanish*/una protección del bosque + CustomMessage("a burnable barrier", /*german*/"", /*french*/"une protection inflammable")}); + // /*spanish*/una barrera quemable + + hintTextTable[RHT_HYLIAN_SHIELD] = HintText(CustomMessage("a Hylian Shield", /*german*/"", /*french*/"un Bouclier Hylien"), + // /*spanish*/un escudo hyliano + { + CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + // /*spanish*/un escudo + }, { + CustomMessage("a steel safeguard", /*german*/"", /*french*/"une carapace d'acier"), + // /*spanish*/una protección de acero + CustomMessage("Like Like's metal meal", /*german*/"", /*french*/"un amuse-gueule de Pudding")}); + // /*spanish*/un alimento de Like Like + + hintTextTable[RHT_MIRROR_SHIELD] = HintText(CustomMessage("the Mirror Shield", /*german*/"", /*french*/"le Bouclier Miroir"), + // /*spanish*/el escudo espejo + { + CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + // /*spanish*/un escudo + }, { + CustomMessage("a reflective rampart", /*german*/"", /*french*/"un capteur de lumière"), + // /*spanish*/una muralla reflectora + CustomMessage("Medusa's weakness", /*german*/"", /*french*/"la faiblesse de Méduse"), + // /*spanish*/la debilidad de Medusa + CustomMessage("a silvered surface", /*german*/"", /*french*/"une surface argentée")}); + // /*spanish*/una superficie plateada + + hintTextTable[RHT_GORON_TUNIC] = HintText(CustomMessage("a Goron Tunic", /*german*/"", /*french*/"une Tunique Goron"), + // /*spanish*/un sayo goron + { + CustomMessage("a tunic", /*german*/"", /*french*/"une tunique") + // /*spanish*/un sayo + }, { + CustomMessage("ruby robes", /*german*/"", /*french*/"un pigment rouge"), + // /*spanish*/una vestimenta rubí + CustomMessage("fireproof fabric", /*german*/"", /*french*/"un trésor anti-flamme"), + // /*spanish*/una ignífuga prenda + CustomMessage("cooking clothes", /*german*/"", /*french*/"une tenue de cuisine")}); + // /*spanish*/unos abrasantes ropajes + + hintTextTable[RHT_ZORA_TUNIC] = HintText(CustomMessage("a Zora Tunic", /*german*/"", /*french*/"une Tunique Zora"), + // /*spanish*/un sayo zora + { + CustomMessage("a tunic", /*german*/"", /*french*/"une tunique"), + // /*spanish*/un sayo + CustomMessage("something expensive", /*german*/"", /*french*/"une chose dispendieuse") + // /*spanish*/algo caro + }, { + CustomMessage("a sapphire suit", /*german*/"", /*french*/"un pigment bleuté"), + // /*spanish*/una vestidura zafiro + CustomMessage("scuba gear", /*german*/"", /*french*/"un habit de plongée"), + // /*spanish*/un traje impermeable + CustomMessage("a swimsuit", /*german*/"", /*french*/"un costume de baignade")}); + // /*spanish*/unos ropajes sumergibles + + hintTextTable[RHT_IRON_BOOTS] = HintText(CustomMessage("the Iron Boots", /*german*/"", /*french*/"une paire de Bottes de plomb"), + // /*spanish*/las botas de hierro + { + CustomMessage("some boots", /*german*/"", /*french*/"une paire de bottes"), + // /*spanish*/un par de botas + CustomMessage("a feature of the Water Temple", /*german*/"", /*french*/"une particularité du Temple de l'Eau"), + // /*spanish*/algo particular del Templo del Agua + CustomMessage("something heavy", /*german*/"", /*french*/"une chose pesante") + // /*spanish*/algo de lo más pesado + }, { + CustomMessage("sink shoes", /*german*/"", /*french*/"un boulet de fer"), + // /*spanish*/un calzado de las profundidades + CustomMessage("clank cleats", /*german*/"", /*french*/"une paire de talons bruyants")}); + // /*spanish*/unas suelas férreas + + hintTextTable[RHT_HOVER_BOOTS] = HintText(CustomMessage("the Hover Boots", /*german*/"", /*french*/"une paire de Bottes des airs"), + // /*spanish*/las botas voladoras + { + CustomMessage("some boots", /*german*/"", /*french*/"une paire de bottes") + // /*spanish*/un par de botas + }, { + CustomMessage("butter boots", /*german*/"", /*french*/"une paire de patins de beurre"), + // /*spanish*/unas suelas resvaladizas + CustomMessage("sacred slippers", /*german*/"", /*french*/"une paire de pantoufles sacrées"), + // /*spanish*/unos escurridizos botines + CustomMessage("spacewalkers", /*german*/"", /*french*/"une paire de bottes spatiales")}); + // /*spanish*/un calzado antigravitatorio + + hintTextTable[RHT_ZELDAS_LETTER] = HintText(CustomMessage("Zelda's Letter", /*german*/"", /*french*/"la Lettre de Zelda"), + // /*spanish*/la carta de Zelda + {}, { + CustomMessage("an autograph", /*german*/"", /*french*/"un autographe"), + // /*spanish*/un autógrafo + CustomMessage("royal stationery", /*german*/"", /*french*/"du papier royal"), + // /*spanish*/un escrito real + CustomMessage("royal snail mail", /*german*/"", /*french*/"une enveloppe royale")}); + // /*spanish*/correo de la realeza + + hintTextTable[RHT_WEIRD_EGG] = HintText(CustomMessage("the Weird Egg", /*german*/"", /*french*/"l'Oeuf Curieux"), + // /*spanish*/el huevo extraño + { + CustomMessage("an egg", /*german*/"", /*french*/"un oeuf") + // /*spanish*/un huevo + }, { + CustomMessage("a chicken dilemma", /*german*/"", /*french*/"un drôle d'ovale")}); + // /*spanish*/el dilema de la gallina + + hintTextTable[RHT_BOOMERANG] = HintText(CustomMessage("the Boomerang", /*german*/"", /*french*/"le Boomerang"), + // /*spanish*/el bumerán + { + CustomMessage("something that can grab things", /*german*/"", /*french*/"une chose qui peut attraper"), + // /*spanish*/algo que pueda agarrar cosas + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("a banana", /*german*/"", /*french*/"une banane"), + // /*spanish*/un plátano + CustomMessage("a stun stick", /*german*/"", /*french*/"un bâton étourdissant"), + // /*spanish*/un palo aturdidor + CustomMessage("a yellow angle", /*german*/"", /*french*/"un angle jaune")}); + // /*spanish*/un ángulo amarillo + + hintTextTable[RHT_LENS_OF_TRUTH] = HintText(CustomMessage("the Lens of Truth", /*german*/"", /*french*/"le Monocle de Vérité"), + // /*spanish*/la Lupa de la Verdad + { + CustomMessage("a secret-finding tool", /*german*/"", /*french*/"un cherche-secrets") + // /*spanish*/un instrumento para hallar objetos + }, { + CustomMessage("a lie detector", /*german*/"", /*french*/"un détecteur de mensonges"), + // /*spanish*/el detector de ilusiones + CustomMessage("a ghost tracker", /*german*/"", /*french*/"un trouve-fantôme"), + // /*spanish*/el rastreador paranormal + CustomMessage("true sight", /*german*/"", /*french*/"le troisième œil"), + // /*spanish*/el ojo que todo ve + CustomMessage("a detective's tool", /*german*/"", /*french*/"un trésor Sheikah")}); + // /*spanish*/la revelación verdadera + + hintTextTable[RHT_MEGATON_HAMMER] = HintText(CustomMessage("the Megaton Hammer", /*german*/"", /*french*/"la Masse des Titans"), + // /*spanish*/el martillo Megatón + { + CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + // /*spanish*/algo que pueda quitar rocas + }, { + CustomMessage("the dragon smasher", /*german*/"", /*french*/"le tueur de dragons"), + // /*spanish*/un destructor de dragones + CustomMessage("the metal mallet", /*german*/"", /*french*/"un outil de construction"), + // /*spanish*/un mazo de metal + CustomMessage("the heavy hitter", /*german*/"", /*french*/"un poids lourd")}); + // /*spanish*/un machacador + + hintTextTable[RHT_STONE_OF_AGONY] = HintText(CustomMessage("the Stone of Agony", /*german*/"", /*french*/"la Pierre de Souffrance"), + // /*spanish*/la Piedra de la Agonía + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + // /*spanish*/un obsequio de la Casa Skulltula + CustomMessage("a secret-finding tool", /*german*/"", /*french*/"un cherche-secrets") + // /*spanish*/un instrumento para hallar objetos + }, { + CustomMessage("the shake stone", /*german*/"", /*french*/"le fragment vibrant"), + // /*spanish*/el fragmento tintineante + CustomMessage("a gray alarm", /*german*/"", /*french*/"une alerte bleue")}); + // /*spanish*/una azul alarma + + hintTextTable[RHT_DINS_FIRE] = HintText(CustomMessage("Din's Fire", /*german*/"", /*french*/"le Feu de Din"), + // /*spanish*/el Fuego de Din + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + // /*spanish*/el poder de una Gran Hada + }, { + CustomMessage("an inferno", /*german*/"", /*french*/"un brasier"), + // /*spanish*/un incendio + CustomMessage("a heat wave", /*german*/"", /*french*/"une vague de chaleur"), + // /*spanish*/una onda de calor + CustomMessage("a red ball", /*german*/"", /*french*/"une explosion de flammes")}); + // /*spanish*/una roja esfera + + hintTextTable[RHT_FARORES_WIND] = HintText(CustomMessage("Farore's Wind", /*german*/"", /*french*/"le Vent de Farore"), + // /*spanish*/el Viento de Farore + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + // /*spanish*/el poder de una Gran Hada + }, { + CustomMessage("teleportation", /*german*/"", /*french*/"la téléportation"), + // /*spanish*/un teletransportador + CustomMessage("a relocation rune", /*german*/"", /*french*/"une rune de relocation"), + // /*spanish*/una runa de transporte + CustomMessage("a green ball", /*german*/"", /*french*/"une boule verte")}); + // /*spanish*/una verde esfera + + hintTextTable[RHT_NAYRUS_LOVE] = HintText(CustomMessage("Nayru's Love", /*german*/"", /*french*/"l'Amour de Nayru"), + // /*spanish*/el Amor de Nayru + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + // /*spanish*/el poder de una Gran Hada + }, { + CustomMessage("a safe space", /*german*/"", /*french*/"une bulle de cristal"), + // /*spanish*/una seguridad temporal + CustomMessage("an impregnable aura", /*german*/"", /*french*/"un aura impénétrable"), + // /*spanish*/un aura impenetrable + CustomMessage("a blue barrier", /*german*/"", /*french*/"une toison bleu")}); + // /*spanish*/una barrera azul + + hintTextTable[RHT_FIRE_ARROWS] = HintText(CustomMessage("the Fire Arrows", /*german*/"", /*french*/"les Flèches de Feu"), + // /*spanish*/la flecha de fuego + { + CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique") + // /*spanish*/una flecha mágica + }, { + CustomMessage("the furnace firearm", /*german*/"", /*french*/"une fusée solaire"), + // /*spanish*/el ardiente aguijón + CustomMessage("the burning bolts", /*german*/"", /*french*/"un obus enflammé"), + // /*spanish*/las puntas ígneas + CustomMessage("a magma missile", /*german*/"", /*french*/"un missile volcanique")}); + // /*spanish*/el misil abrasador + + hintTextTable[RHT_ICE_ARROWS] = HintText(CustomMessage("the Ice Arrows", /*german*/"", /*french*/"les Flèches de Glace"), + // /*spanish*/la flecha de hielo + { + CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique"), + // /*spanish*/una flecha mágica + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("the refrigerator rocket", /*german*/"", /*french*/"un missile pétrifiant"), + // /*spanish*/el misil congelador + CustomMessage("the frostbite bolts", /*german*/"", /*french*/"un froid mordant"), + // /*spanish*/las puntas gélidas + CustomMessage("an iceberg maker", /*german*/"", /*french*/"une aiguille glaciale")}); + // /*spanish*/el control de escarcha + + hintTextTable[RHT_LIGHT_ARROWS] = HintText(CustomMessage("the Light Arrows", /*german*/"", /*french*/"les Flèches de Lumière"), + // /*spanish*/la flecha de luz + { + CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique") + // /*spanish*/una flecha mágica + }, { + CustomMessage("the shining shot", /*german*/"", /*french*/"l'arme brillante"), + // /*spanish*/el haz de luz + CustomMessage("the luminous launcher", /*german*/"", /*french*/"un jet de lumière"), + // /*spanish*/el disparo luminoso + CustomMessage("Ganondorf's bane", /*german*/"", /*french*/"le fléau de Ganondorf"), + // /*spanish*/la perdición de Ganondorf + CustomMessage("the lighting bolts", /*german*/"", /*french*/"l'éclair sacré")}); + // /*spanish*/las puntas resplandecientes + + hintTextTable[RHT_GERUDO_MEMBERSHIP_CARD] = HintText(CustomMessage("the Gerudo Membership Card", /*german*/"", /*french*/"la Carte Gerudo"), + // /*spanish*/el pase de socio gerudo + { + CustomMessage("a token of recognition", /*german*/"", /*french*/"une preuve de reconnaissance") + // /*spanish*/una prueba de reconocimiento + }, { + CustomMessage("a girl club membership", /*german*/"", /*french*/"une carte de membre"), + // /*spanish*/una fémina membresía + CustomMessage("a desert tribe's pass", /*german*/"", /*french*/"un laissez-passer")}); + // /*spanish*/el vale del desierto + + hintTextTable[RHT_MAGIC_BEAN] = HintText(CustomMessage("a Magic Bean", /*german*/"", /*french*/"un Haricot Magique"), + // /*spanish*/una judía mágica + { + CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + // /*spanish*/algo a veces enterrado + }, { + CustomMessage("a wizardly legume", /*german*/"", /*french*/"un légume ensorcelé")}); + // /*spanish*/una legumbre hechizada + + hintTextTable[RHT_MAGIC_BEAN_PACK] = HintText(CustomMessage("Magic Beans", /*german*/"", /*french*/"un Paquet de Haricots Magiques"), + // /*spanish*/unas judías mágicas + { + CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + // /*spanish*/algo a veces enterrado + }, { + CustomMessage("wizardly legumes", /*german*/"", /*french*/"un paquet de légumes ensorcelés")}); + // /*spanish*/unas legumbres hechizadas + + hintTextTable[RHT_DOUBLE_DEFENSE] = HintText(CustomMessage("Double Defense", /*german*/"", /*french*/"la Double Défence"), + // /*spanish*/la doble defensa + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée"), + // /*spanish*/el poder de una Gran Hada + CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + // /*spanish*/algo con forma de corazón + }, { + CustomMessage("a white outline", /*german*/"", /*french*/"un rebord blanc"), + // /*spanish*/un contorno blanco + CustomMessage("damage decrease", /*german*/"", /*french*/"une protection supplémentaire"), + // /*spanish*/una reducción de daño + CustomMessage("strengthened love", /*german*/"", /*french*/"un amour coriace")}); + // /*spanish*/un amor fortalecido + + hintTextTable[RHT_GOLD_SKULLTULA_TOKEN] = HintText(CustomMessage("a Gold Skulltula Token", /*german*/"", /*french*/"un Symbole de Skulltula d'or"), + // /*spanish*/un símbolo de skulltula dorada + { + CustomMessage("a token of recognition", /*german*/"", /*french*/"une preuve de reconnaissance"), + // /*spanish*/una prueba de reconocimiento + CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + // /*spanish*/algo a veces enterrado + }, { + CustomMessage("proof of destruction", /*german*/"", /*french*/"un certificat d'élimination"), + // /*spanish*/una prueba de la destrucción + CustomMessage("an arachnid chip", /*german*/"", /*french*/"un symbole cranien"), + // /*spanish*/una figura arácnida + CustomMessage("spider remains", /*german*/"", /*french*/"une dépouille dorée"), + // /*spanish*/unos restos dorados + CustomMessage("one percent of a curse", /*german*/"", /*french*/"un centième de malédiction")}); + // /*spanish*/una centésima de una maldición + + hintTextTable[RHT_POCKET_EGG] = HintText(CustomMessage("the Pocket Egg", /*german*/"", /*french*/"l'Oeuf de Poche"), + // /*spanish*/el huevo de bolsillo + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges"), + // /*spanish*/un objeto de una misión secundaria + CustomMessage("an egg", /*german*/"", /*french*/"un oeuf") + // /*spanish*/un huevo + }, { + CustomMessage("a Cucco container", /*german*/"", /*french*/"un réservoir à Cocotte"), + // /*spanish*/cuco contenido + CustomMessage("a Cucco, eventually", /*german*/"", /*french*/"un poussin éventuel"), + // /*spanish*/un futuro cuco + CustomMessage("a fowl youth", /*german*/"", /*french*/"une omelette crue")}); + // /*spanish*/una dulce juventud + + hintTextTable[RHT_POCKET_CUCCO] = HintText(CustomMessage("the Pocket Cucco", /*german*/"", /*french*/"la Cocotte de Poche"), + // /*spanish*/el cuco de bolsillo + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a little clucker", /*german*/"", /*french*/"un petit glousseur")}); + // /*spanish*/un pollito chiquito + + hintTextTable[RHT_COJIRO] = HintText(CustomMessage("Cojiro", /*german*/"", /*french*/"le p'tit poulet"), + // /*spanish*/a Cojiro + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a cerulean capon", /*german*/"", /*french*/"un paon azur")}); + // /*spanish*/un cerúleo capón + + hintTextTable[RHT_ODD_MUSHROOM] = HintText(CustomMessage("an Odd Mushroom", /*german*/"", /*french*/"un Champignon Suspect"), + // /*spanish*/un champiñón extraño + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a powder ingredient", /*german*/"", /*french*/"un ingrédient à poudre")}); + // /*spanish*/un oloroso ingrediente + + hintTextTable[RHT_ODD_POTION] = HintText(CustomMessage("an Odd Potion", /*german*/"", /*french*/"une Mixture Suspecte"), + // /*spanish*/una medicina rara + { + CustomMessage("something that contains medicine", /*german*/"", /*french*/"une chose médicamenteuse"), + // /*spanish*/algo que contenga medicina + CustomMessage("something with a strange smell", /*german*/"", /*french*/"une chose qui sent bizarre"), + // /*spanish*/algo con un olor extraño + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("Granny's goodies", /*german*/"", /*french*/"la confiserie de mamie")}); + // /*spanish*/la especialidad de la abuela + + hintTextTable[RHT_POACHERS_SAW] = HintText(CustomMessage("the Poacher's Saw", /*german*/"", /*french*/"la Scie du Chasseur"), + // /*spanish*/la sierra del furtivo + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a tree killer", /*german*/"", /*french*/"un coupeur d'arbres")}); + // /*spanish*/un destructor de árboles + + hintTextTable[RHT_BROKEN_SWORD] = HintText(CustomMessage("the Broken Goron's Sword", /*german*/"", /*french*/"l'Épée Brisée de Goron"), + // /*spanish*/la espada goron rota + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges"), + // /*spanish*/un objeto de una misión secundaria + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("a shattered slicer", /*german*/"", /*french*/"une arme cassée")}); + // /*spanish*/una rebanadora rota + + hintTextTable[RHT_PRESCRIPTION] = HintText(CustomMessage("the Prescription", /*german*/"", /*french*/"une Ordonnance"), + // /*spanish*/la receta + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a pill pamphlet", /*german*/"", /*french*/"un document urgent"), + // /*spanish*/un instructivo medicinal + CustomMessage("a doctor's note", /*german*/"", /*french*/"un papier médical")}); + // /*spanish*/unas notas del doctor + + hintTextTable[RHT_EYEBALL_FROG] = HintText(CustomMessage("the Eyeball Frog", /*german*/"", /*french*/"le Crapaud-qui-louche"), + // /*spanish*/la rana de ojos saltones + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a perceiving polliwog", /*german*/"", /*french*/"un amphibien")}); + // /*spanish*/un variopinto batracio + + hintTextTable[RHT_EYEDROPS] = HintText(CustomMessage("the Eyedrops", /*german*/"", /*french*/"une phiole de Super-Gouttes"), + // /*spanish*/las supergotas oculares + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a vision vial", /*german*/"", /*french*/"une solution oculaire")}); + // /*spanish*/un remedio para la vista + + hintTextTable[RHT_CLAIM_CHECK] = HintText(CustomMessage("the Claim Check", /*german*/"", /*french*/"un Certificat"), + // /*spanish*/el recibo + { + CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + // /*spanish*/un objeto de una misión secundaria + }, { + CustomMessage("a three day wait", /*german*/"", /*french*/"un rendez-vous dans trois jours")}); + // /*spanish*/unos tres días de espera + + hintTextTable[RHT_PROGRESSIVE_HOOKSHOT] = HintText(CustomMessage("a Hookshot", /*german*/"", /*french*/"un Grappin"), + // /*spanish*/un gancho + { + CustomMessage("something that can grab things", /*german*/"", /*french*/"une chose qui peut attraper"), + // /*spanish*/algo que pueda agarrar cosas + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("Dampé's keepsake", /*german*/"", /*french*/"l'héritage d'Igor"), + // /*spanish*/un recuerdo de Dampé + CustomMessage("the Grapple Beam", /*german*/"", /*french*/"le rayon grippeur"), + // /*spanish*/una garra metálica + CustomMessage("the RHT_BOING! chain", /*german*/"", /*french*/"la chaîne de RHT_BOING!")}); + // /*spanish*/una cadena retráctil + + hintTextTable[RHT_PROGRESSIVE_STRENGTH] = HintText(CustomMessage("a Strength Upgrade", /*german*/"", /*french*/"une Amélioration de Force"), + // /*spanish*/un aumento de fuerza + { + CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + // /*spanish*/algo que pueda quitar rocas + }, { + CustomMessage("power gloves", /*german*/"", /*french*/"une paire de gants de travail"), + // /*spanish*/unos poderosos guanteletes + CustomMessage("metal mittens", /*german*/"", /*french*/"une paire de mitaines"), + // /*spanish*/unas manoplas metálicas + CustomMessage("the heavy lifty", /*german*/"", /*french*/"la puissance de dix hommes")}); + // /*spanish*/un levantamiento pesado + + hintTextTable[RHT_PROGRESSIVE_BOMB_BAG] = HintText(CustomMessage("a Bomb Bag", /*german*/"", /*french*/"un Sac de Bombes"), + // /*spanish*/un saco de bombas + { + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs"), + // /*spanish*/un montón de explosivos + CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + // /*spanish*/algo que pueda quitar rocas + }, { + CustomMessage("an explosive container", /*german*/"", /*french*/"un porte-grenade"), + // /*spanish*/un recipiente explosivo + CustomMessage("a blast bag", /*german*/"", /*french*/"un estomac de Dodongo")}); + // /*spanish*/un zurrón de estallidos + + hintTextTable[RHT_PROGRESSIVE_BOW] = HintText(CustomMessage("a Bow", /*german*/"", /*french*/"l'Arc des Fées"), + // /*spanish*/un arco de las hadas + { + CustomMessage("a projectile shooter", /*german*/"", /*french*/"un tire-projectile") + // /*spanish*/un arma de proyectil + }, { + CustomMessage("an archery enabler", /*german*/"", /*french*/"un facilitateur de tir"), + // /*spanish*/un tiro al blanco + CustomMessage("a danger dart launcher", /*german*/"", /*french*/"un tire-fléchette")}); + // /*spanish*/un peligroso lanzadardos + + hintTextTable[RHT_PROGRESSIVE_SLINGSHOT] = HintText(CustomMessage("a Slingshot", /*german*/"", /*french*/"un Lance-Pierre"), + // /*spanish*/una resortera de las hadas + { + CustomMessage("a projectile shooter", /*german*/"", /*french*/"un tire-projectile") + // /*spanish*/un arma de proyectil + }, { + CustomMessage("a seed shooter", /*german*/"", /*french*/"un lance-noix"), + // /*spanish*/un lanzasemillas + CustomMessage("a rubberband", /*german*/"", /*french*/"un élastique"), + // /*spanish*/un tirachinas + CustomMessage("a child's catapult", /*german*/"", /*french*/"un jouet d'enfant")}); + // /*spanish*/una catapulta infantil + + hintTextTable[RHT_PROGRESSIVE_WALLET] = HintText(CustomMessage("a Wallet", /*german*/"", /*french*/"une Bourse"), + // /*spanish*/una bolsa de rupias + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas") + // /*spanish*/un obsequio de la Casa Skulltula + }, { + CustomMessage("a mo' money holder", /*german*/"", /*french*/"un sac à sous"), + // /*spanish*/una cartera de dinero + CustomMessage("a gem purse", /*german*/"", /*french*/"une sacoche"), + // /*spanish*/un zurrón de gemas + CustomMessage("a portable bank", /*german*/"", /*french*/"une petite banque")}); + // /*spanish*/un banco portable + + hintTextTable[RHT_PROGRESSIVE_SCALE] = HintText(CustomMessage("a Zora Scale", /*german*/"", /*french*/"une Écaille Zora"), + // /*spanish*/una escama Zora + { + CustomMessage("a diving tool", /*german*/"", /*french*/"un outil de plongée") + // /*spanish*/un instrumento de buceo + }, { + CustomMessage("a deeper dive", /*german*/"", /*french*/"une bulle de plongée"), + // /*spanish*/un profundo buceo + CustomMessage("a piece of Zora", /*german*/"", /*french*/"un morceau de Zora")}); + // /*spanish*/un fragmento de Zora + + hintTextTable[RHT_PROGRESSIVE_NUT_UPGRADE] = HintText(CustomMessage("Deku Nut Capacity", /*german*/"", /*french*/"une Augmentation de Noix Mojo"), + // /*spanish*/un aumento de nueces deku + { + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + // /*spanish*/un montón de municiones Deku + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("more nuts", /*german*/"", /*french*/"ecnore plus de noix"), + // /*spanish*/más semillas de nogal + CustomMessage("flashbang storage", /*german*/"", /*french*/"un sac à noix")}); + // /*spanish*/más frutos aturdidores + + hintTextTable[RHT_PROGRESSIVE_STICK_UPGRADE] = HintText(CustomMessage("Deku Stick Capacity", /*german*/"", /*french*/"une augmentation de bâtons Mojo"), + // /*spanish*/un aumento de palos deku + { + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + // /*spanish*/un montón de municiones Deku + }, { + CustomMessage("a lumber rack", /*german*/"", /*french*/"un paquet de bois"), + // /*spanish*/más bastones + CustomMessage("more flammable twigs", /*german*/"", /*french*/"beaucoup de branches")}); + // /*spanish*/más varas + + hintTextTable[RHT_PROGRESSIVE_MAGIC_METER] = HintText(CustomMessage("a Magic Meter", /*german*/"", /*french*/"une Jauge de Magie"), + // /*spanish*/un aumento de poder mágico + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + // /*spanish*/el poder de una Gran Hada + }, { + CustomMessage("mystic training", /*german*/"", /*french*/"un potentiel magique"), + // /*spanish*/una maestría mística + CustomMessage("pixie dust", /*german*/"", /*french*/"de la poudre de fée"), + // /*spanish*/un polvo de hada + CustomMessage("a green rectangle", /*german*/"", /*french*/"un rectangle vert")}); + // /*spanish*/una verduzca barra + + hintTextTable[RHT_PROGRESSIVE_OCARINA] = HintText(CustomMessage("an Ocarina", /*german*/"", /*french*/"un ocarina"), + // /*spanish*/una ocarina + { + CustomMessage("something given by Saria", /*german*/"", /*french*/"un cadeau de Saria"), + // /*spanish*/un obsequio de Saria + CustomMessage("something kept by the royal family", /*german*/"", /*french*/"une chose qui paralyse") + // /*spanish*/algo guardado por la familia real + }, { + CustomMessage("a flute", /*german*/"", /*french*/"un bec musical"), + // /*spanish*/un utensilio musical + CustomMessage("a music maker", /*german*/"", /*french*/"un porteur de chansons")}); + // /*spanish*/un instrumento + + hintTextTable[RHT_PROGRESSIVE_BOMBCHUS] = HintText(CustomMessage("Bombchus", /*german*/"", /*french*/"un paquet de Missiles"), + // /*spanish*/unos bombchus + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + // /*spanish*/un obsequio de la Casa Skulltula + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("mice bombs", /*german*/"", /*french*/"un adorable explosif"), + // /*spanish*/unas bombas roedoras + CustomMessage("proximity mice", /*german*/"", /*french*/"une mine anti-rongeur"), + // /*spanish*/unos explosivos ratoncitos + CustomMessage("wall crawlers", /*german*/"", /*french*/"un rapide grimpeur"), + // /*spanish*/unos trepaparedes + CustomMessage("trail blazers", /*german*/"", /*french*/"un zigzag éclatant")}); + // /*spanish*/unas ratas propulsadas + + hintTextTable[RHT_PROGRESSIVE_GORONSWORD] = HintText(CustomMessage("a Goron Sword", /*german*/"", /*french*/"une épée Goron"), + // /*spanish*/una espada goron + { + CustomMessage("a sword", /*german*/"", /*french*/"une épée") + // /*spanish*/una espada + }, { + CustomMessage("a long blade", /*german*/"", /*french*/"une longue lame"), + // /*spanish*/una gran hoja + CustomMessage("a Goron weapon", /*german*/"", /*french*/"une arme Goron")}); + // /*spanish*/un arma goron + + hintTextTable[RHT_EMPTY_BOTTLE] = HintText(CustomMessage("a Bottle", /*german*/"", /*french*/"un flacon vide"), + // /*spanish*/una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a glass container", /*german*/"", /*french*/"un cylindre de cristal"), + // /*spanish*/un recipiente de cristal + CustomMessage("an empty jar", /*german*/"", /*french*/"une jarre incassable"), + // /*spanish*/un frasco vacío + CustomMessage("encased air", /*german*/"", /*french*/"un bocal d'air")}); + // /*spanish*/aire a presión + + hintTextTable[RHT_BOTTLE_WITH_MILK] = HintText(CustomMessage("a Milk Bottle", /*german*/"", /*french*/"un flacon de lait"), + // /*spanish*/una botella de leche + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("cow juice", /*german*/"", /*french*/"une source de calcium"), + // /*spanish*/una fuente de calcio + CustomMessage("a white liquid", /*german*/"", /*french*/"un liquide blanc"), + // /*spanish*/una bebida nutritiva + CustomMessage("a baby's breakfast", /*german*/"", /*french*/"du jus pour bébé")}); + // /*spanish*/un trago para bebés + + hintTextTable[RHT_BOTTLE_WITH_RED_POTION] = HintText(CustomMessage("a Red Potion Bottle", /*german*/"", /*french*/"un flacon de potion rouge"), + // /*spanish*/una botella de poción roja + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a vitality vial", /*german*/"", /*french*/"un mélange de vitalité"), + // /*spanish*/una pócima vitalicia + CustomMessage("a red liquid", /*german*/"", /*french*/"un liquide rouge")}); + // /*spanish*/un remedio rojizo + + hintTextTable[RHT_BOTTLE_WITH_GREEN_POTION] = HintText(CustomMessage("a Green Potion Bottle", /*german*/"", /*french*/"un flacon de potion verte"), + // /*spanish*/una botella de poción verde + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a magic mixture", /*german*/"", /*french*/"une réserve magique"), + // /*spanish*/un potingue mágico + CustomMessage("a green liquid", /*german*/"", /*french*/"un liquide vert")}); + // /*spanish*/un remedio verduzco + + hintTextTable[RHT_BOTTLE_WITH_BLUE_POTION] = HintText(CustomMessage("a Blue Potion Bottle", /*german*/"", /*french*/"un flacon de potion bleue"), + // /*spanish*/una botella de poción azul + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("an ailment antidote", /*german*/"", /*french*/"l'élixir ultime"), + // /*spanish*/un antídoto para el dolor + CustomMessage("a blue liquid", /*german*/"", /*french*/"un liquide bleu")}); + // /*spanish*/un remedio índigo + + hintTextTable[RHT_BOTTLE_WITH_FAIRY] = HintText(CustomMessage("a Fairy Bottle", /*german*/"", /*french*/"une fée en flacon"), + // /*spanish*/un hada en una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("an imprisoned fairy", /*german*/"", /*french*/"une fée emprisonnée"), + // /*spanish*/un hada atrapada + CustomMessage("an extra life", /*german*/"", /*french*/"une vie de rechange"), + // /*spanish*/una oportunidad más + CustomMessage("Navi's cousin", /*german*/"", /*french*/"le cousin de Navi")}); + // /*spanish*/una prima de Navi + + hintTextTable[RHT_BOTTLE_WITH_FISH] = HintText(CustomMessage("a Fish Bottle", /*german*/"", /*french*/"un poisson en flacon"), + // /*spanish*/un pez en una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("an aquarium", /*german*/"", /*french*/"un aquarium"), + // /*spanish*/un escamado ser + CustomMessage("a deity's snack", /*german*/"", /*french*/"le repas d'un dieu marin")}); + // /*spanish*/un tentempié de cierta deidad + + hintTextTable[RHT_BOTTLE_WITH_BLUE_FIRE] = HintText(CustomMessage("a Blue Fire Bottle", /*german*/"", /*french*/"une flamme bleue en flacon"), + // /*spanish*/una botella de fuego azul + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a conflagration canteen", /*german*/"", /*french*/"une mystérieuse flamme"), + // /*spanish*/un incendio retenido + CustomMessage("an icemelt jar", /*german*/"", /*french*/"un brasier glacial")}); + // /*spanish*/unas brasas enfrascadas + + hintTextTable[RHT_BOTTLE_WITH_BUGS] = HintText(CustomMessage("a Bug Bottle", /*german*/"", /*french*/"un insecte en flacon"), + // /*spanish*/unos insectos en una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("an insectarium", /*german*/"", /*french*/"un insectarium"), + // /*spanish*/unos invertebrados seres + CustomMessage("Skulltula finders", /*german*/"", /*french*/"une poignée de trouve-Skulltula")}); + // /*spanish*/unos rastreadores de skulltulas + + hintTextTable[RHT_BOTTLE_WITH_POE] = HintText(CustomMessage("a Poe Bottle", /*german*/"", /*french*/"un Esprit en flacon"), + // /*spanish*/un Poe en una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a spooky ghost", /*german*/"", /*french*/"un effroyable fantôme"), + // /*spanish*/un espantoso espectro + CustomMessage("a face in the jar", /*german*/"", /*french*/"un visage dans un bocal")}); + // /*spanish*/una expresión enfrascada + + hintTextTable[RHT_BOTTLE_WITH_BIG_POE] = HintText(CustomMessage("a Big Poe Bottle", /*german*/"", /*french*/"une Ame en flacon"), + // /*spanish*/un Gran Poe en una botella + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("the spookiest ghost", /*german*/"", /*french*/"un épouvantable spectre"), + // /*spanish*/el espectro más espeluznante + CustomMessage("a sidequest spirit", /*german*/"", /*french*/"un précieux esprit")}); + // /*spanish*/un buen valorado espíritu + + hintTextTable[RHT_RUTOS_LETTER] = HintText(CustomMessage("Ruto's Letter", /*german*/"", /*french*/"la lettre de Ruto"), + // /*spanish*/la carta de Ruto + { + CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + // /*spanish*/una botella + }, { + CustomMessage("a call for help", /*german*/"", /*french*/"un appel au secours"), + // /*spanish*/una llamada de auxilio + CustomMessage("the note that Mweeps", /*german*/"", /*french*/"un message qui fait mwip"), + // /*spanish*/un escrito mweep + CustomMessage("an RHT_SOS call", /*german*/"", /*french*/"un signal RHT_SOS"), + // /*spanish*/una nota de socorro + CustomMessage("a fishy stationery", /*german*/"", /*french*/"un papier mouillé")}); + // /*spanish*/un mensaje de ayuda + + hintTextTable[RHT_ZELDAS_LULLABY] = HintText(CustomMessage("Zelda's Lullaby", /*german*/"", /*french*/"la berceuse de Zelda"), + // /*spanish*/la Nana de Zelda + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + // /*spanish*/una cancion normal + CustomMessage("something kept by the royal family", /*german*/"", /*french*/"une chose qui paralyse") + // /*spanish*/algo guardado por la familia real + }, { + CustomMessage("a song of royal slumber", /*german*/"", /*french*/"une chanson royale"), + // /*spanish*/la canción real + CustomMessage("a triforce tune", /*german*/"", /*french*/"la musique sacrée")}); + // /*spanish*/la melodía de la trifuerza + + hintTextTable[RHT_EPONAS_SONG] = HintText(CustomMessage("Epona's Song", /*german*/"", /*french*/"le chant d'Epona"), + // /*spanish*/la Canción de Epona + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + // /*spanish*/una cancion normal + }, { + CustomMessage("an equestrian etude", /*german*/"", /*french*/"une hymne équestre"), + // /*spanish*/una copla ecuestre + CustomMessage("Malon's melody", /*german*/"", /*french*/"la mélodie des vaches"), + // /*spanish*/la sonata de Malon + CustomMessage("a ranch song", /*german*/"", /*french*/"le chant des champs")}); + // /*spanish*/un canto rupestre + + hintTextTable[RHT_SARIAS_SONG] = HintText(CustomMessage("Saria's Song", /*german*/"", /*french*/"le chant de Saria"), + // /*spanish*/la Canción de Saria + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + // /*spanish*/una cancion normal + CustomMessage("something given by Saria", /*german*/"", /*french*/"un cadeau de Saria") + // /*spanish*/un obsequio de Saria + }, { + CustomMessage("a song of dancing Gorons", /*german*/"", /*french*/"une chanson danceuse"), + // /*spanish*/un pegadizo tono goron + CustomMessage("Saria's phone number", /*german*/"", /*french*/"le téléphone d'une amie")}); + // /*spanish*/una consulta de asistencia + + hintTextTable[RHT_SUNS_SONG] = HintText(CustomMessage("the Sun's Song", /*german*/"", /*french*/"le chant du soleil"), + // /*spanish*/la Canción del Sol + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + // /*spanish*/una cancion normal + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("Sunny Day", /*german*/"", /*french*/"Zénith"), + // /*spanish*/un día soleado + CustomMessage("the ReDead's bane", /*german*/"", /*french*/"le fléau des Éffrois"), + // /*spanish*/la destructora de Redeads + CustomMessage("the Gibdo's bane", /*german*/"", /*french*/"le fléau des Gibdo")}); + // /*spanish*/la destructora de Gibdos + + hintTextTable[RHT_SONG_OF_TIME] = HintText(CustomMessage("the Song of Time", /*german*/"", /*french*/"le chant du temps"), + // /*spanish*/la Canción del tiempo + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + // /*spanish*/una cancion normal + }, { + CustomMessage("a song 7 years long", /*german*/"", /*french*/"le flot du temps"), + // /*spanish*/la setenada canción + CustomMessage("the tune of ages", /*german*/"", /*french*/"le Chant des Âges")}); + // /*spanish*/la melodía eónica + + hintTextTable[RHT_SONG_OF_STORMS] = HintText(CustomMessage("the Song of Storms", /*german*/"", /*french*/"le chant des tempêtes"), + // /*spanish*/la Canción de la Tormenta + { + CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + // /*spanish*/una cancion normal + }, { + CustomMessage("Rain Dance", /*german*/"", /*french*/"Danse Pluie"), + // /*spanish*/la danza de la lluvia + CustomMessage("a thunderstorm tune", /*german*/"", /*french*/"une hymne foudroyante"), + // /*spanish*/una sonata tormentosa + CustomMessage("windmill acceleration", /*german*/"", /*french*/"l'accélérateur de moulins")}); + // /*spanish*/el arranque de molinos + + hintTextTable[RHT_MINUET_OF_FOREST] = HintText(CustomMessage("the Minuet of Forest", /*german*/"", /*french*/"le menuet de la forêt"), + // /*spanish*/el Minueto del bosque + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("the song of tall trees", /*german*/"", /*french*/"le bruit des arbres"), + // /*spanish*/la canción de las copas + CustomMessage("an arboreal anthem", /*german*/"", /*french*/"l'hymne sylvestre"), + // /*spanish*/el himno forestal + CustomMessage("a green spark trail", /*german*/"", /*french*/"une comète verte")}); + // /*spanish*/el sendero esmeralda + + hintTextTable[RHT_BOLERO_OF_FIRE] = HintText(CustomMessage("the Bolero of Fire", /*german*/"", /*french*/"le boléro du feu"), + // /*spanish*/el Bolero del fuego + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("a song of lethal lava", /*german*/"", /*french*/"une musique enflammée"), + // /*spanish*/la canción de la lava + CustomMessage("a red spark trail", /*german*/"", /*french*/"une comète rouge"), + // /*spanish*/el sendero rubí + CustomMessage("a volcanic verse", /*german*/"", /*french*/"le souffle du volcan")}); + // /*spanish*/el verso volcánico + + hintTextTable[RHT_SERENADE_OF_WATER] = HintText(CustomMessage("the Serenade of Water", /*german*/"", /*french*/"la sérénade de l'eau"), + // /*spanish*/la Serenata del agua + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("a song of a damp ditch", /*german*/"", /*french*/"le calme de l'eau"), + // /*spanish*/la canción del estanque + CustomMessage("a blue spark trail", /*german*/"", /*french*/"une comète bleue"), + // /*spanish*/el sendero zafiro + CustomMessage("the lake's lyric", /*german*/"", /*french*/"la voix du lac")}); + // /*spanish*/la letra del lago + + hintTextTable[RHT_REQUIEM_OF_SPIRIT] = HintText(CustomMessage("the Requiem of Spirit", /*german*/"", /*french*/"le requiem des esprits"), + // /*spanish*/el Réquiem del espíritu + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("a song of sandy statues", /*german*/"", /*french*/"la mélodie d'une grande statue"), + // /*spanish*/la canción de la gran estatua + CustomMessage("an orange spark trail", /*german*/"", /*french*/"une comète orange"), + // /*spanish*/el sendero ámbar + CustomMessage("the desert ditty", /*german*/"", /*french*/"le vent du désert")}); + // /*spanish*/la estrofa del desierto + + hintTextTable[RHT_NOCTURNE_OF_SHADOW] = HintText(CustomMessage("the Nocturne of Shadow", /*german*/"", /*french*/"le nocturne de l'ombre"), + // /*spanish*/el Nocturno de la sombra + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("a song of spooky spirits", /*german*/"", /*french*/"une hymne de chair de poule"), + // /*spanish*/la canción de los espectros + CustomMessage("a graveyard boogie", /*german*/"", /*french*/"un boogie de fantômes"), + // /*spanish*/una honra fúnebre + CustomMessage("a haunted hymn", /*german*/"", /*french*/"une chanson lugubre"), + // /*spanish*/una estrofa encantada + CustomMessage("a purple spark trail", /*german*/"", /*french*/"une comète mauve")}); + // /*spanish*/el sendero malva + + hintTextTable[RHT_PRELUDE_OF_LIGHT] = HintText(CustomMessage("the Prelude of Light", /*german*/"", /*french*/"le prélude de la lumière"), + // /*spanish*/el Preludio de la luz + { + CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + // /*spanish*/una canción de teletransportación + }, { + CustomMessage("a luminous prologue melody", /*german*/"", /*french*/"une matine illuminée"), + // /*spanish*/la melodía refulgente + CustomMessage("a yellow spark trail", /*german*/"", /*french*/"une comète jaune"), + // /*spanish*/el sendero resplandeciente + CustomMessage("the temple traveler", /*german*/"", /*french*/"un chant de sanctuaire")}); + // /*spanish*/la ruta del templo + + hintTextTable[RHT_DEKU_TREE_MAP] = HintText(CustomMessage("the Deku Tree Map", /*german*/"", /*french*/"la carte de l'Arbre Mojo"), + // /*spanish*/el mapa del Gran Árbol Deku + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a mossy atlas", /*german*/"", /*french*/"un atlas boisé"), + // /*spanish*/un atlas musgoso + CustomMessage("some mossy blueprints", /*german*/"", /*french*/"un plan boisé")}); + // /*spanish*/unos planos musgosos + + hintTextTable[RHT_DODONGOS_CAVERN_MAP] = HintText(CustomMessage("the Dodongo's Cavern Map", /*german*/"", /*french*/"la carte de la Caverne Dodongo"), + // /*spanish*/el mapa de la Cueva de los Dodongos + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a rocky atlas", /*german*/"", /*french*/"un atlas rocheux"), + // /*spanish*/un atlas rocoso + CustomMessage("some rocky blueprints", /*german*/"", /*french*/"un plan rocheux")}); + // /*spanish*/unos planos rocosos + + hintTextTable[RHT_JABU_JABUS_BELLY_MAP] = HintText(CustomMessage("the Jabu-Jabu's Belly Map", /*german*/"", /*french*/"la carte de Jabu-Jabu"), + // /*spanish*/el mapa de la Tripa de Jabu-Jabu + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a fishy atlas", /*german*/"", /*french*/"un atlas digéré"), + // /*spanish*/un atlas digesto + CustomMessage("some fishy blueprints", /*german*/"", /*french*/"un plan digéré")}); + // /*spanish*/unos planos digestos + + hintTextTable[RHT_FOREST_TEMPLE_MAP] = HintText(CustomMessage("the Forest Temple Map", /*german*/"", /*french*/"la carte du Temple de la Forêt"), + // /*spanish*/el mapa del Templo del Bosque + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a sylvan atlas", /*german*/"", /*french*/"un atlas sylvestre"), + // /*spanish*/un atlas enselvado + CustomMessage("some sylvan blueprints", /*german*/"", /*french*/"un plan sylvestre")}); + // /*spanish*/unos planos enselvados + + hintTextTable[RHT_FIRE_TEMPLE_MAP] = HintText(CustomMessage("the Fire Temple Map", /*german*/"", /*french*/"la carte du Temple du Feu"), + // /*spanish*/el mapa del Templo del Fuego + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a molten atlas", /*german*/"", /*french*/"un atlas fondu"), + // /*spanish*/un atlas fundido + CustomMessage("some molten blueprints", /*german*/"", /*french*/"un plan fondu")}); + // /*spanish*/unos planos fundidos + + hintTextTable[RHT_WATER_TEMPLE_MAP] = HintText(CustomMessage("the Water Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Eau"), + // /*spanish*/el mapa del Templo del Agua + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a wet atlas", /*german*/"", /*french*/"un atlas humide"), + // /*spanish*/un atlas mojado + CustomMessage("some wet blueprints", /*german*/"", /*french*/"un plan humide")}); + // /*spanish*/unos planos mojados + + hintTextTable[RHT_SPIRIT_TEMPLE_MAP] = HintText(CustomMessage("the Spirit Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Esprit"), + // /*spanish*/el mapa del Templo del Espíritu + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a sandy atlas", /*german*/"", /*french*/"un atlas sableux"), + // /*spanish*/un atlas arenoso + CustomMessage("some sandy blueprints", /*german*/"", /*french*/"un plan sableux")}); + // /*spanish*/unos planos arenosos + + hintTextTable[RHT_SHADOW_TEMPLE_MAP] = HintText(CustomMessage("the Shadow Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Ombre"), + // /*spanish*/el mapa del Templo de las Sombras + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a creepy atlas", /*german*/"", /*french*/"un atlas sinistre"), + // /*spanish*/un atlas siniestra + CustomMessage("some creepy blueprints", /*german*/"", /*french*/"un plan sinistre")}); + // /*spanish*/unos planos siniestras + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MAP] = HintText(CustomMessage("the Bottom of the Well Map", /*german*/"", /*french*/"la carte du fond du Puits"), + // /*spanish*/el mapa del Fondo del pozo + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a moldy atlas", /*german*/"", /*french*/"un atlas moisi"), + // /*spanish*/un atlas mohoso + CustomMessage("some moldy blueprints", /*german*/"", /*french*/"un plan moisi")}); + // /*spanish*/unos planos mohosos + + hintTextTable[RHT_ICE_CAVERN_MAP] = HintText(CustomMessage("the Ice Cavern Map", /*german*/"", /*french*/"la carte de la Caverne Polaire"), + // /*spanish*/el mapa de la Caverna de hielo + { + CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + // /*spanish*/un mapa + }, { + CustomMessage("a polar atlas", /*german*/"", /*french*/"un atlas polaire"), + // /*spanish*/un atlas polar + CustomMessage("some polar blueprints", /*german*/"", /*french*/"un plan polaire")}); + // /*spanish*/unos planos polars + + hintTextTable[RHT_DEKU_TREE_COMPASS] = HintText(CustomMessage("the Deku Tree Compass", /*german*/"", /*french*/"la boussole de l'Arbre Mojo"), + // /*spanish*/la brújula del Gran Árbol Deku + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a mossy treasure tracker", /*german*/"", /*french*/"un cherche-trésor boisé"), + // /*spanish*/un zahorí musgoso + CustomMessage("a mossy magnetic needle", /*german*/"", /*french*/"une aimant boisée")}); + // /*spanish*/un imán musgoso + + hintTextTable[RHT_DODONGOS_CAVERN_COMPASS] = HintText(CustomMessage("the Dodongo's Cavern Compass", /*german*/"", /*french*/"la boussole de la Caverne Dodongo"), + // /*spanish*/la brújula de la Cueva de los Dodongos + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a rocky treasure tracker", /*german*/"", /*french*/"un cherche-trésor rocheux"), + // /*spanish*/un zahorí rocoso + CustomMessage("a rocky magnetic needle", /*german*/"", /*french*/"une aimant rocheux")}); + // /*spanish*/un imán rocoso + + hintTextTable[RHT_JABU_JABUS_BELLY_COMPASS] = HintText(CustomMessage("the Jabu-Jabu's Belly Compass", /*german*/"", /*french*/"la boussole de Jabu-Jabu"), + // /*spanish*/la brújula de la Tripa de Jabu-Jabu + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a fishy treasure tracker", /*german*/"", /*french*/"un cherche-trésor digéré"), + // /*spanish*/un zahorí digesto + CustomMessage("a fishy magnetic needle", /*german*/"", /*french*/"une aimant digéré")}); + // /*spanish*/un imán digesto + + hintTextTable[RHT_FOREST_TEMPLE_COMPASS] = HintText(CustomMessage("the Forest Temple Compass", /*german*/"", /*french*/"la boussole du Temple de la Forêt"), + // /*spanish*/la brújula del Templo del Bosque + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a sylvan treasure tracker", /*german*/"", /*french*/"un cherche-trésor sylvestre"), + // /*spanish*/un zahorí enselvado + CustomMessage("a sylvan magnetic needle", /*german*/"", /*french*/"une aimant sylvestre")}); + // /*spanish*/un imán enselvado + + hintTextTable[RHT_FIRE_TEMPLE_COMPASS] = HintText(CustomMessage("the Fire Temple Compass", /*german*/"", /*french*/"la boussole du Temple du Feu"), + // /*spanish*/la brújula del Templo del Fuego + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a molten treasure tracker", /*german*/"", /*french*/"un cherche-trésor fondu"), + // /*spanish*/un zahorí fundido + CustomMessage("a molten magnetic needle", /*german*/"", /*french*/"une aimant fondu")}); + // /*spanish*/un imán fundido + + hintTextTable[RHT_WATER_TEMPLE_COMPASS] = HintText(CustomMessage("the Water Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Eau"), + // /*spanish*/la brújula del Templo del Agua + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a wet treasure tracker", /*german*/"", /*french*/"un cherche-trésor humide"), + // /*spanish*/un zahorí mojado + CustomMessage("a wet magnetic needle", /*german*/"", /*french*/"une aimant humide")}); + // /*spanish*/un imán mojado + + hintTextTable[RHT_SPIRIT_TEMPLE_COMPASS] = HintText(CustomMessage("the Spirit Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Esprit"), + // /*spanish*/la brújula del Templo del Espíritu + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a sandy treasure tracker", /*german*/"", /*french*/"un cherche-trésor sableux"), + // /*spanish*/un zahorí arenoso + CustomMessage("a sandy magnetic needle", /*german*/"", /*french*/"une aimant sableux")}); + // /*spanish*/un imán arenoso + + hintTextTable[RHT_SHADOW_TEMPLE_COMPASS] = HintText(CustomMessage("the Shadow Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Ombre"), + // /*spanish*/la brújula del Templo de las Sombras + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a creepy treasure tracker", /*german*/"", /*french*/"un cherche-trésor sinistre"), + // /*spanish*/un zahorí siniestra + CustomMessage("a creepy magnetic needle", /*german*/"", /*french*/"une aimant sinistre")}); + // /*spanish*/un imán siniestra + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_COMPASS] = HintText(CustomMessage("the Bottom of the Well Compass", /*german*/"", /*french*/"la boussole du fond du Puits"), + // /*spanish*/la brújula del Fondo del pozo + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a dank treasure tracker", /*german*/"", /*french*/"un cherche-trésor moisi"), + // /*spanish*/un zahorí mohoso + CustomMessage("a dank magnetic needle", /*german*/"", /*french*/"une aimant moisi")}); + // /*spanish*/un imán mohoso + + hintTextTable[RHT_ICE_CAVERN_COMPASS] = HintText(CustomMessage("the Ice Cavern Compass", /*german*/"", /*french*/"la Boussole de la Caverne Polaire"), + // /*spanish*/la brújula de la Caverna de hielo + { + CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + // /*spanish*/una brújula + }, { + CustomMessage("a polar treasure tracker", /*german*/"", /*french*/"un cherche-trésor polaire"), + // /*spanish*/un zahorí polar + CustomMessage("a polar magnetic needle", /*german*/"", /*french*/"une aimant polaire")}); + // /*spanish*/un imán polar + + hintTextTable[RHT_FOREST_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Forest Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de la Forêt"), + // /*spanish*/la gran llave del Templo del Bosque + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a sylvan master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sylvestre"), + // /*spanish*/la clave enselvada de un jefe + CustomMessage("a sylvan dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sylvestree")}); + // /*spanish*/el pase maestro enselvado + + hintTextTable[RHT_FIRE_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Fire Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple du Feu"), + // /*spanish*/la gran llave del Templo del Fuego + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a molten master of unlocking", /*german*/"", /*french*/"un anti-grosse porte fondu"), + // /*spanish*/la clave fundido de un jefe + CustomMessage("a molten dungeon's master pass", /*german*/"", /*french*/"une clé maléfique fondu")}); + // /*spanish*/el pase maestro fundido + + hintTextTable[RHT_WATER_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Water Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Eau"), + // /*spanish*/la gran llave del Templo del Agua + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a wet master of unlocking", /*german*/"", /*french*/"un anti-grosse porte humide"), + // /*spanish*/la clave mojado de un jefe + CustomMessage("a wet dungeon's master pass", /*german*/"", /*french*/"une clé maléfique humide")}); + // /*spanish*/el pase maestro mojado + + hintTextTable[RHT_SPIRIT_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Spirit Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Esprit"), + // /*spanish*/la gran llave del Templo del Espíritu + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a sandy master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sableux"), + // /*spanish*/la clave arenoso de un jefe + CustomMessage("a sandy dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sableux")}); + // /*spanish*/el pase maestro arenoso + + hintTextTable[RHT_SHADOW_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Shadow Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Ombre"), + // /*spanish*/la gran llave del Templo de las Sombras + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a creepy master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sinistre"), + // /*spanish*/la clave siniestra de un jefe + CustomMessage("a creepy dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sinistre")}); + // /*spanish*/el pase maestro siniestra + + hintTextTable[RHT_GANONS_CASTLE_BOSS_KEY] = HintText(CustomMessage("the Ganon's Castle Boss Key", /*german*/"", /*french*/"la Clé d'Or du Château de Ganon"), + // /*spanish*/la gran llave del Castillo de Ganon + { + CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + // /*spanish*/una gran llave + }, { + CustomMessage("a final master of unlocking", /*german*/"", /*french*/"un anti-grosse porte final"), + // /*spanish*/la clave final de un jefe + CustomMessage("a final dungeon's master pass", /*german*/"", /*french*/"une clé maléfique final")}); + // /*spanish*/el pase maestro final + + hintTextTable[RHT_FOREST_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Forest Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de la Forêt"), + // /*spanish*/una llave pequeña del Templo del Bosque + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a sylvan tool for unlocking", /*german*/"", /*french*/"un anti-porte sylvestre"), + // /*spanish*/una clave de una entrada enselvada + CustomMessage("a sylvan dungeon pass", /*german*/"", /*french*/"le rêve sylvestre d'un prisonnier"), + // /*spanish*/un pase de una mazmorra enselvada + CustomMessage("a sylvan lock remover", /*german*/"", /*french*/"un efface-serrure sylvestre"), + // /*spanish*/un destructor de cerraduras enselvada + CustomMessage("a sylvan lockpick", /*german*/"", /*french*/"un crochet à porte sylvestre")}); + // /*spanish*/una apertura portentosa enselvada + + hintTextTable[RHT_FIRE_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Fire Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple du Feu"), + // /*spanish*/una llave pequeña del Templo del Fuego + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a molten tool for unlocking", /*german*/"", /*french*/"un anti-porte fondu"), + // /*spanish*/una clave de una entrada fundida + CustomMessage("a molten dungeon pass", /*german*/"", /*french*/"le rêve fondu d'un prisonnier"), + // /*spanish*/un pase de una mazmorra fundida + CustomMessage("a molten lock remover", /*german*/"", /*french*/"un efface-serrure fondu"), + // /*spanish*/un destructor de cerraduras fundida + CustomMessage("a molten lockpick", /*german*/"", /*french*/"un crochet à porte fondu")}); + // /*spanish*/una apertura portentosa fundida + + hintTextTable[RHT_WATER_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Water Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Eau"), + // /*spanish*/una llave pequeña del Templo del Agua + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a wet tool for unlocking", /*german*/"", /*french*/"un anti-porte humide"), + // /*spanish*/una clave de una entrada mojada + CustomMessage("a wet dungeon pass", /*german*/"", /*french*/"le rêve humide d'un prisonnier"), + // /*spanish*/un pase de una mazmorra mojada + CustomMessage("a wet lock remover", /*german*/"", /*french*/"un efface-serrure humide"), + // /*spanish*/un destructor de cerraduras mojada + CustomMessage("a wet lockpick", /*german*/"", /*french*/"un crochet à porte humide")}); + // /*spanish*/una apertura portentosa mojada + + hintTextTable[RHT_SPIRIT_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Spirit Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Esprit"), + // /*spanish*/una llave pequeña del Templo del Espíritu + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a sandy tool for unlocking", /*german*/"", /*french*/"un anti-porte sableux"), + // /*spanish*/una clave de una entrada arenosa + CustomMessage("a sandy dungeon pass", /*german*/"", /*french*/"le rêve sableux d'un prisonnier"), + // /*spanish*/un pase de una mazmorra arenosa + CustomMessage("a sandy lock remover", /*german*/"", /*french*/"un efface-serrure sableux"), + // /*spanish*/un destructor de cerraduras arenosa + CustomMessage("a sandy lockpick", /*german*/"", /*french*/"un crochet à porte sableux")}); + // /*spanish*/una apertura portentosa arenosa + + hintTextTable[RHT_SHADOW_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Shadow Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Ombre"), + // /*spanish*/una llave pequeña del Templo de las Sombras + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a creepy tool for unlocking", /*german*/"", /*french*/"un anti-porte sinistre"), + // /*spanish*/una clave de una entrada siniestra:a + CustomMessage("a creepy dungeon pass", /*german*/"", /*french*/"le rêve sinistre d'un prisonnier"), + // /*spanish*/un pase de una mazmorra siniestra:a + CustomMessage("a creepy lock remover", /*german*/"", /*french*/"un efface-serrure sinistre"), + // /*spanish*/un destructor de cerraduras siniestra:a + CustomMessage("a creepy lockpick", /*german*/"", /*french*/"un crochet à porte sinistre")}); + // /*spanish*/una apertura portentosa siniestra:a + + hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Training Ground Small Key", /*german*/"", /*french*/"une petite clé du Gymnase Gerudo"), + // /*spanish*/una llave pequeña del Centro de Instrucción Gerudo + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a labyrinthian tool for unlocking", /*german*/"", /*french*/"un anti-porte labyrinthique"), + // /*spanish*/una clave de una entrada laberíntica + CustomMessage("a labyrinthian dungeon pass", /*german*/"", /*french*/"le rêve labyrinthique d'un prisonnier"), + // /*spanish*/un pase de una mazmorra laberíntica + CustomMessage("a labyrinthian lock remover", /*german*/"", /*french*/"un efface-serrure labyrinthique"), + // /*spanish*/un destructor de cerraduras laberíntica + CustomMessage("a labyrinthian lockpick", /*german*/"", /*french*/"un crochet à porte labyrinthique")}); + // /*spanish*/una apertura portentosa laberíntica + + hintTextTable[RHT_GERUDO_FORTRESS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Fortress Small Key", /*german*/"", /*french*/"une petite clé de la Repaire des Voleurs"), + // /*spanish*/una llave pequeña de la Fortaleza Gerudo + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("an imprisoned tool for unlocking", /*german*/"", /*french*/"un anti-porte emprisonné"), + // /*spanish*/una clave de una entrada encarcelada + CustomMessage("an imprisoned dungeon pass", /*german*/"", /*french*/"le rêve emprisonné d'un prisonnier"), + // /*spanish*/un pase de una mazmorra encarcelada + CustomMessage("an imprisoned lock remover", /*german*/"", /*french*/"un efface-serrure emprisonné"), + // /*spanish*/un destructor de cerraduras encarcelada + CustomMessage("an imprisoned lockpick", /*german*/"", /*french*/"un crochet à porte emprisonné")}); + // /*spanish*/una apertura portentosa encarcelada + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_SMALL_KEY] = HintText(CustomMessage("a Bottom of the Well Small Key", /*german*/"", /*french*/"une petite clé du fond du Puits"), + // /*spanish*/una llave pequeña del Fondo del pozo + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a moldy tool for unlocking", /*german*/"", /*french*/"un anti-porte moisi"), + // /*spanish*/una clave de una entrada mohosa + CustomMessage("a moldy dungeon pass", /*german*/"", /*french*/"le rêve moisi d'un prisonnier"), + // /*spanish*/un pase de una mazmorra mohosa + CustomMessage("a moldy lock remover", /*german*/"", /*french*/"un efface-serrure moisi"), + // /*spanish*/un destructor de cerraduras mohosa + CustomMessage("a moldy lockpick", /*german*/"", /*french*/"un crochet à porte moisi")}); + // /*spanish*/una apertura portentosa mohosa + + hintTextTable[RHT_GANONS_CASTLE_SMALL_KEY] = HintText(CustomMessage("a Ganon's Castle Small Key", /*german*/"", /*french*/"une petite clé du Château de Ganon"), + // /*spanish*/una llave pequeña del Castillo de Ganon + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a final tool for unlocking", /*german*/"", /*french*/"un anti-porte final"), + // /*spanish*/una clave de una entrada final + CustomMessage("a final dungeon pass", /*german*/"", /*french*/"le rêve final d'un prisonnier"), + // /*spanish*/un pase de una mazmorra final + CustomMessage("a final lock remover", /*german*/"", /*french*/"un efface-serrure final"), + // /*spanish*/un destructor de cerraduras final + CustomMessage("a final lockpick", /*german*/"", /*french*/"un crochet à porte final")}); + // /*spanish*/una apertura portentosa final + + hintTextTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText(CustomMessage("a Forest Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de la Forêt"), + // /*spanish*/un llavero del Templo del Bosque + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a sylvan toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sylvestres"), + // /*spanish*/un conjunto silvestre de cerrajero + CustomMessage("a sylvan dungeon season pass", /*german*/"", /*french*/"les rêves sylvestres d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras silvestre + CustomMessage("a sylvan jingling ring", /*german*/"", /*french*/"des efface-serrures sylvestres"), + // /*spanish*/una cadena multiusos silvestre + CustomMessage("a sylvan skeleton key", /*german*/"", /*french*/"des crochets à porte sylvestres")}); + // /*spanish*/un anillo silvestre contra cerrojos + + hintTextTable[RHT_FIRE_TEMPLE_KEY_RING] = HintText(CustomMessage("a Fire Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple du Feu"), + // /*spanish*/un llavero del Templo del Fuego + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a molten toolbox for unlocking", /*german*/"", /*french*/"des anti-portes fondus"), + // /*spanish*/un conjunto fundido de cerrajero + CustomMessage("a molten dungeon season pass", /*german*/"", /*french*/"les rêves fondus d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras fundido + CustomMessage("a molten jingling ring", /*german*/"", /*french*/"des efface-serrures fondus"), + // /*spanish*/una cadena multiusos fundida + CustomMessage("a molten skeleton key", /*german*/"", /*french*/"des crochets à porte fondus")}); + // /*spanish*/un anillo fundido contra cerrojos + + hintTextTable[RHT_WATER_TEMPLE_KEY_RING] = HintText(CustomMessage("a Water Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Eau"), + // /*spanish*/un llavero del Templo del Agua + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a wet toolbox for unlocking", /*german*/"", /*french*/"des anti-portes humides"), + // /*spanish*/un conjunto abisal de cerrajero + CustomMessage("a wet dungeon season pass", /*german*/"", /*french*/"les rêves humides d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras abisal + CustomMessage("a wet jingling ring", /*german*/"", /*french*/"des efface-serrures humides"), + // /*spanish*/una cadena multiusos abisal + CustomMessage("a wet skeleton key", /*german*/"", /*french*/"des crochets à porte humides")}); + // /*spanish*/un anillo abisal contra cerrojos + + hintTextTable[RHT_SPIRIT_TEMPLE_KEY_RING] = HintText(CustomMessage("a Spirit Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Esprit"), + // /*spanish*/un llavero del Templo del Espíritu + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a sandy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sableux"), + // /*spanish*/un conjunto arenoso de cerrajero + CustomMessage("a sandy dungeon season pass", /*german*/"", /*french*/"les rêves sableux d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras arenoso + CustomMessage("a sandy jingling ring", /*german*/"", /*french*/"des efface-serrures sableux"), + // /*spanish*/una cadena multiusos arenosa + CustomMessage("a sandy skeleton key", /*german*/"", /*french*/"des crochets à porte sableux")}); + // /*spanish*/un anillo arenoso contra cerrojos + + hintTextTable[RHT_SHADOW_TEMPLE_KEY_RING] = HintText(CustomMessage("a Shadow Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Ombre"), + // /*spanish*/un llavero del Templo de las Sombras + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a creepy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sinistres"), + // /*spanish*/un conjunto tenebroso de cerrajero + CustomMessage("a creepy dungeon season pass", /*german*/"", /*french*/"les rêves sinistres d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras tenebroso + CustomMessage("a creepy jingling ring", /*german*/"", /*french*/"des efface-serrures sinistres"), + // /*spanish*/una cadena multiusos tenebrosa + CustomMessage("a creepy skeleton key", /*german*/"", /*french*/"des crochets à porte sinistres")}); + // /*spanish*/un anillo tenebroso contra cerrojos + + hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_KEY_RING] = HintText(CustomMessage("a Gerudo Training Ground Key Ring", /*german*/"", /*french*/"un trousseau de clés du Gymnase Gerudo"), + // /*spanish*/un llavero del Centro de Instrucción Gerudo + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a labyrinthian toolbox for unlocking", /*german*/"", /*french*/"des anti-portes labyrinthiques"), + // /*spanish*/un conjunto laberíntico de cerrajero + CustomMessage("a labyrinthian dungeon season pass", /*german*/"", /*french*/"les rêves labyrinthiques d'un prisonnier"), + // /*spanish*/un pase vip de mazmorras laberíntico + CustomMessage("a labyrinthian jingling ring", /*german*/"", /*french*/"des efface-serrures labyrinthiques"), + // /*spanish*/una cadena multiusos laberíntica + CustomMessage("a labyrinthian skeleton key", /*german*/"", /*french*/"des crochets à porte labyrinthiques")}); + // /*spanish*/un anillo laberíntico contra cerrojos + + hintTextTable[RHT_GERUDO_FORTRESS_KEY_RING] = HintText(CustomMessage("a Gerudo Fortress Key Ring", /*german*/"", /*french*/"un trousseau de clés de la Repaire des Voleurs"), + // /*spanish*/un llavero de la Fortaleza Gerudo + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("an imprisoned toolbox for unlocking", /*german*/"", /*french*/"des anti-portes emprisonnés"), + // /*spanish*/un conjunto enjaulado de cerrajero + CustomMessage("an imprisoned dungeon season pass", /*german*/"", /*french*/"les rêves emprisonnés d'un prisonnier"), + // /*spanish*/un pase vip de una mazmorra enjaulado + CustomMessage("an imprisoned jingling ring", /*german*/"", /*french*/"des efface-serrures emprisonnés"), + // /*spanish*/una cadena multiusos enjaulada + CustomMessage("an imprisoned skeleton key", /*german*/"", /*french*/"des crochets à porte emprisonnés")}); + // /*spanish*/un anillo enjaulado contra cerrojos + + hintTextTable[RHT_BOTTOM_OF_THE_WELL_KEY_RING] = HintText(CustomMessage("a Bottom of the Well Key Ring", /*german*/"", /*french*/"un trousseau de clés du fond du Puits"), + // /*spanish*/un llavero del Fondo del pozo + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a moldy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes moisis"), + // /*spanish*/un conjunto subterráneo de cerrajero + CustomMessage("a moldy dungeon season pass", /*german*/"", /*french*/"les rêves moisis d'un prisonnier"), + // /*spanish*/un pase vip de una mazmorra subterráneo + CustomMessage("a moldy jingling ring", /*german*/"", /*french*/"des efface-serrures moisis"), + // /*spanish*/una cadena multiusos subterránea + CustomMessage("a moldy skeleton key", /*german*/"", /*french*/"des crochets à porte moisis")}); + // /*spanish*/un anillo subterráneo contra cerrojos + + hintTextTable[RHT_GANONS_CASTLE_KEY_RING] = HintText(CustomMessage("a Ganon's Castle Key Ring", /*german*/"", /*french*/"un trousseau de clés du Château de Ganon"), + // /*spanish*/un llavero del Castillo de Ganon + { + CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + // /*spanish*/un llavero + }, { + CustomMessage("a final toolbox for unlocking", /*german*/"", /*french*/"des anti-portes finaux"), + // /*spanish*/un conjunto decisivo de cerrajero + CustomMessage("a final dungeon season pass", /*german*/"", /*french*/"les rêves finaux d'un prisonnier"), + // /*spanish*/un pase vip de una mazmorra decisivo + CustomMessage("a final jingling ring", /*german*/"", /*french*/"des efface-serrures finaux"), + // /*spanish*/una cadena multiusos decisiva + CustomMessage("a final skeleton key", /*german*/"", /*french*/"des crochets à porte finaux")}); + // /*spanish*/un anillo decisivo multiusos + + hintTextTable[RHT_TREASURE_GAME_SMALL_KEY] = HintText(CustomMessage("a Treasure Chest Shop Small Key", /*german*/"", /*french*/"une petite clé de la chasse aux trésors"), + // /*spanish*/una llave pequeña del Cofre del Tesoro + { + CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + // /*spanish*/una llave pequeña + }, { + CustomMessage("a gambler's tool for unlocking", /*german*/"", /*french*/"un anti-porte de parieur"), + // /*spanish*/una clave de un juego de azar + CustomMessage("a gambler's dungeon pass", /*german*/"", /*french*/"le rêve d'un prisonnier parieur"), + // /*spanish*/un pase de un juego de azar + CustomMessage("a gambler's lock remover", /*german*/"", /*french*/"un efface-serrure de parieur"), + // /*spanish*/un destructor de cerraduras del juego de azar + CustomMessage("a gambler's lockpick", /*german*/"", /*french*/"un crochet à serrure de parieur")}); + // /*spanish*/una apertura portentosa del juego de azar + + hintTextTable[RHT_KOKIRI_EMERALD] = HintText(CustomMessage("the Kokiri Emerald", /*german*/"", /*french*/"l'Émeraude Kokiri"), + // /*spanish*/la Esmeralda de los Kokiri + { + CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + // /*spanish*/una piedra espiritual + }, { + CustomMessage("a green stone", /*german*/"", /*french*/"une pierre verte"), + // /*spanish*/una piedra verde + CustomMessage("a gift before death", /*german*/"", /*french*/"le dernier souffle d'un arbre")}); + // /*spanish*/un obsequio testamentario + + hintTextTable[RHT_GORON_RUBY] = HintText(CustomMessage("the Goron Ruby", /*german*/"", /*french*/"le Rubis Goron"), + // /*spanish*/el Rubí de los Goron + { + CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + // /*spanish*/una piedra espiritual + }, { + CustomMessage("a red stone", /*german*/"", /*french*/"une pierre rouge"), + // /*spanish*/una piedra carmín + CustomMessage("sworn brotherhood", /*german*/"", /*french*/"un serment de fraternité")}); + // /*spanish*/el juramento de hermanos de sangre + + hintTextTable[RHT_ZORA_SAPPHIRE] = HintText(CustomMessage("the Zora Sapphire", /*german*/"", /*french*/"le Saphir Zora"), + // /*spanish*/el Zafiro de los Zora + { + CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + // /*spanish*/una piedra espiritual + }, { + CustomMessage("a blue stone", /*german*/"", /*french*/"une pierre bleue"), + // /*spanish*/una piedra celeste + CustomMessage("an engagement gift", /*german*/"", /*french*/"un cadeau de mariage")}); + // /*spanish*/un regalo de compromiso + + hintTextTable[RHT_FOREST_MEDALLION] = HintText(CustomMessage("the Forest Medallion", /*german*/"", /*french*/"le Médaillon de la Forêt"), + // /*spanish*/el Medallón del Bosque + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("a green coin", /*german*/"", /*french*/"une pièce verte"), + // /*spanish*/una moneda esmeralda + CustomMessage("Saria's friendship", /*german*/"", /*french*/"l'amitié de Saria")}); + // /*spanish*/la amistad de Saria + + hintTextTable[RHT_FIRE_MEDALLION] = HintText(CustomMessage("the Fire Medallion", /*german*/"", /*french*/"le Médaillon du Feu"), + // /*spanish*/el Medallón del Fuego + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("a red coin", /*german*/"", /*french*/"une pièce rouge"), + // /*spanish*/una moneda rubí + CustomMessage("Darunia's power", /*german*/"", /*french*/"la fraternité de Darunia")}); + // /*spanish*/la fraternidad de Darunia + + hintTextTable[RHT_WATER_MEDALLION] = HintText(CustomMessage("the Water Medallion", /*german*/"", /*french*/"le Médaillon de l'Eau"), + // /*spanish*/el Medallón del Agua + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("a blue coin", /*german*/"", /*french*/"une pièce bleue"), + // /*spanish*/una moneda zafiro + CustomMessage("Ruto's power", /*german*/"", /*french*/"l'amour de Ruto")}); + // /*spanish*/el amor de Ruto + + hintTextTable[RHT_SPIRIT_MEDALLION] = HintText(CustomMessage("the Spirit Medallion", /*german*/"", /*french*/"le Médaillon de l'Esprit"), + // /*spanish*/el Medallón del Espíritu + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("an orange coin", /*german*/"", /*french*/"une pièce orange"), + // /*spanish*/una moneda ámbar + CustomMessage("Nabooru's power", /*german*/"", /*french*/"le respect de Nabooru")}); + // /*spanish*/el respeto de Nabooru + + hintTextTable[RHT_SHADOW_MEDALLION] = HintText(CustomMessage("the Shadow Medallion", /*german*/"", /*french*/"le Médaillon de l'Ombre"), + // /*spanish*/el Medallón de la Sombra + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("a purple coin", /*german*/"", /*french*/"une pièce pourpre"), + // /*spanish*/una moneda malva + CustomMessage("Impa's power", /*german*/"", /*french*/"la confiance d'Impa")}); + // /*spanish*/la confianza de Impa + + hintTextTable[RHT_LIGHT_MEDALLION] = HintText(CustomMessage("the Light Medallion", /*german*/"", /*french*/"le Médaillon de la Lumière"), + // /*spanish*/el Medallón de la Luz + { + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + // /*spanish*/un medallón + }, { + CustomMessage("a yellow coin", /*german*/"", /*french*/"une pièce jaune"), + // /*spanish*/una moneda resplandeciente + CustomMessage("Rauru's power", /*german*/"", /*french*/"la foi de Rauru")}); + // /*spanish*/la fe de Rauru + + hintTextTable[RHT_RECOVERY_HEART] = HintText(CustomMessage("a Recovery Heart", /*german*/"", /*french*/"un coeur de vie"), + // /*spanish*/un corazón + { + CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + // /*spanish*/algo con forma de corazón + }, { + CustomMessage("a free heal", /*german*/"", /*french*/"un bec-au-bobo"), + // /*spanish*/una cura de regalo + CustomMessage("a hearty meal", /*german*/"", /*french*/"un petit amour"), + // /*spanish*/una sanación romántica + CustomMessage("a Band-Aid", /*german*/"", /*french*/"un diachylon")}); + // /*spanish*/un corazoncito sanador + + hintTextTable[RHT_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert"), + // /*spanish*/una rupia verde + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("a unique coin", /*german*/"", /*french*/"un rubis bien mérité"), + // /*spanish*/una singular moneda + CustomMessage("a penny", /*german*/"", /*french*/"un sou"), + // /*spanish*/un peso hyliano + CustomMessage("a green gem", /*german*/"", /*french*/"un joyau vert")}); + // /*spanish*/una gema verde + + hintTextTable[RHT_GREG_RUPEE] = HintText(CustomMessage("Greg", /*german*/"", /*french*/"Greg"), + // /*spanish*/Greg + { + CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert") + // /*spanish*/una rupia verde + }, { + CustomMessage("an old friend", /*german*/"", /*french*/"Greg"), + // /*spanish*/Greg + CustomMessage("a glorious gem", /*german*/"", /*french*/"Greg")}); + // /*spanish*/Greg + + hintTextTable[RHT_BLUE_RUPEE] = HintText(CustomMessage("a Blue Rupee", /*german*/"", /*french*/"un rubis bleu"), + // /*spanish*/una rupia azul + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("a common coin", /*german*/"", /*french*/"quelques sous"), + // /*spanish*/una moneda usual + CustomMessage("a blue gem", /*german*/"", /*french*/"un joyau bleu")}); + // /*spanish*/una gema azul + + hintTextTable[RHT_RED_RUPEE] = HintText(CustomMessage("a Red Rupee", /*german*/"", /*french*/"un rubis rouge"), + // /*spanish*/una rupia roja + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("couch cash", /*german*/"", /*french*/"un peu de fric"), + // /*spanish*/una buena moneda + CustomMessage("a red gem", /*german*/"", /*french*/"un joyau rouge")}); + // /*spanish*/una gema roja + + hintTextTable[RHT_PURPLE_RUPEE] = HintText(CustomMessage("a Purple Rupee", /*german*/"", /*french*/"un rubis pourpre"), + // /*spanish*/una rupia morada + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("big bucks", /*german*/"", /*french*/"plein de fric"), + // /*spanish*/plata de calidad + CustomMessage("a purple gem", /*german*/"", /*french*/"un joyau mauve"), + // /*spanish*/una gema morada + CustomMessage("wealth", /*german*/"", /*french*/"la richesse")}); + // /*spanish*/una buena riqueza + + hintTextTable[RHT_HUGE_RUPEE] = HintText(CustomMessage("a Huge Rupee", /*german*/"", /*french*/"un énorme rubis"), + // /*spanish*/una rupia gigante + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("a juicy jackpot", /*german*/"", /*french*/"le jackpot"), + // /*spanish*/el premio gordo + CustomMessage("a yellow gem", /*german*/"", /*french*/"un joyau doré"), + // /*spanish*/una gema amarilla + CustomMessage("a giant gem", /*german*/"", /*french*/"un gros joyau"), + // /*spanish*/una gema descomunal + CustomMessage("great wealth", /*german*/"", /*french*/"l'aisance financière")}); + // /*spanish*/dinero a caudales + + hintTextTable[RHT_PIECE_OF_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"", /*french*/"un Quart de Coeur"), + // /*spanish*/una pieza de corazón + { + CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + // /*spanish*/algo con forma de corazón + }, { + CustomMessage("a little love", /*german*/"", /*french*/"un peu plus d'amour"), + // /*spanish*/un cuarto de amor + CustomMessage("a broken heart", /*german*/"", /*french*/"un coeur brisé")}); + // /*spanish*/un corazón roto + + hintTextTable[RHT_HEART_CONTAINER] = HintText(CustomMessage("a Heart Container", /*german*/"", /*french*/"un Réceptacle de Coeur"), + // /*spanish*/un contenedor de corazón + { + CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + // /*spanish*/algo con forma de corazón + }, { + CustomMessage("a lot of love", /*german*/"", /*french*/"le grand amour"), + // /*spanish*/amor por doquier + CustomMessage("a Valentine's gift", /*german*/"", /*french*/"un cadeau de Saint-Valentin"), + // /*spanish*/un contenedor de afección + CustomMessage("a boss's organ", /*german*/"", /*french*/"un organe de monstre")}); + // /*spanish*/los órganos de un jefe + + hintTextTable[RHT_ICE_TRAP] = HintText(CustomMessage("an Ice Trap", /*german*/"", /*french*/"un Piège de Glace"), + // /*spanish*/una trampa de hielo + { + CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée"), + // /*spanish*/el poder de una Gran Hada + CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique"), + // /*spanish*/una flecha mágica + CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon"), + // /*spanish*/un medallón + CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale"), + // /*spanish*/una piedra espiritual + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("a gift from Ganon", /*german*/"", /*french*/"un cadeau de Ganon"), + // /*spanish*/un regalo de Ganon + CustomMessage("a chilling discovery", /*german*/"", /*french*/"une frissonante découverte"), + // /*spanish*/un escalofriante hallazgo + CustomMessage("frosty fun", /*german*/"", /*french*/"une engelure")}); + // /*spanish*/una gélida diversión + + hintTextTable[RHT_BOMBS_5] = HintText(CustomMessage("Bombs (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de bombes"), + // /*spanish*/unas (5) bombas + { + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("a few explosives", /*german*/"", /*french*/"une poignée de pétards"), + // /*spanish*/un par de explosivos + CustomMessage("a few blast balls", /*german*/"", /*french*/"une poignée de boules bleues")}); + // /*spanish*/un par de estallidos + + hintTextTable[RHT_BOMBS_10] = HintText(CustomMessage("Bombs (10 pieces)", /*german*/"", /*french*/"une dizaine de bombes"), + // /*spanish*/unas (10) bombas + { + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("some explosives", /*german*/"", /*french*/"un paquet de pétards"), + // /*spanish*/unos cuantos explosivos + CustomMessage("some blast balls", /*german*/"", /*french*/"un paquet de boules bleues")}); + // /*spanish*/unos cuantos estallidos + + hintTextTable[RHT_BOMBS_20] = HintText(CustomMessage("Bombs (20 pieces)", /*german*/"", /*french*/"une vingtaine de bombes"), + // /*spanish*/unas (20) bombas + { + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("lots-o-explosives", /*german*/"", /*french*/"une abondance de pétards"), + // /*spanish*/un puñado de explosivos + CustomMessage("plenty of blast balls", /*german*/"", /*french*/"une abondance de boules bleues")}); + // /*spanish*/bastantes estallidos + + hintTextTable[RHT_BOMBCHU_5] = HintText(CustomMessage("Bombchus (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de Missiles"), + // /*spanish*/unos (5) bombchus + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + // /*spanish*/un obsequio de la Casa Skulltula + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("a few mice bombs", /*german*/"", /*french*/"une poignée de mignons explosifs"), + // /*spanish*/un par de bombas roedoras + CustomMessage("a few proximity mice", /*german*/"", /*french*/"une poignée de jouets à remonter"), + // /*spanish*/un par de explosivos ratoncitos + CustomMessage("a few wall crawlers", /*german*/"", /*french*/"une poignée de rapides grimpeurs"), + // /*spanish*/un par de trepaparedes + CustomMessage("a few trail blazers", /*german*/"", /*french*/"une poignée de zigzags éclatants")}); + // /*spanish*/un par de ratas propulsadas + + hintTextTable[RHT_BOMBCHU_10] = HintText(CustomMessage("Bombchus (10 pieces)", /*german*/"", /*french*/"une dizaine de Missiles"), + // /*spanish*/unos (10) bombchus + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + // /*spanish*/un obsequio de la Casa Skulltula + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("some mice bombs", /*german*/"", /*french*/"un paquet de mignons explosifs"), + // /*spanish*/unas cuantas bombas roedoras + CustomMessage("some proximity mice", /*german*/"", /*french*/"un paquet de jouets à remonter"), + // /*spanish*/unos cuantos explosivos ratoncitos + CustomMessage("some wall crawlers", /*german*/"", /*french*/"un paquet de rapides grimpeurs"), + // /*spanish*/unos cuantos trepaparedes + CustomMessage("some trail blazers", /*german*/"", /*french*/"un paquet de zigzags éclatants")}); + // /*spanish*/unas cuantas ratas propulsadas + + hintTextTable[RHT_BOMBCHU_20] = HintText(CustomMessage("Bombchus (20 pieces)", /*german*/"", /*french*/"une vingtaine de Missiles"), + // /*spanish*/unos (20) bombchus + { + CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + // /*spanish*/un obsequio de la Casa Skulltula + CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + // /*spanish*/un montón de explosivos + }, { + CustomMessage("plenty of mice bombs", /*german*/"", /*french*/"une abondance de mignons explosifs"), + // /*spanish*/bastantes bombas roedoras + CustomMessage("plenty of proximity mice", /*german*/"", /*french*/"une abondance de jouets à remonter"), + // /*spanish*/bastantes explosivos ratoncitos + CustomMessage("plenty of wall crawlers", /*german*/"", /*french*/"une abondance de rapides grimpeurs"), + // /*spanish*/bastantes trepaparedes + CustomMessage("plenty of trail blazers", /*german*/"", /*french*/"une abondance de zigzags éclatants")}); + // /*spanish*/bastantes ratas propulsadas + + hintTextTable[RHT_ARROWS_5] = HintText(CustomMessage("Arrows (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de flèches"), + // /*spanish*/unas (5) flechas + { + CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + // /*spanish*/un proyectil + }, { + CustomMessage("a few danger darts", /*german*/"", /*french*/"une poignée d'obus"), + // /*spanish*/un par de peligrosos dardos + CustomMessage("a few sharp shafts", /*german*/"", /*french*/"une poignée de piquets")}); + // /*spanish*/un par de puntas afiladas + + hintTextTable[RHT_ARROWS_10] = HintText(CustomMessage("Arrows (10 pieces)", /*german*/"", /*french*/"une dizaine de flèches"), + // /*spanish*/unas (10) flechas + { + CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + // /*spanish*/un proyectil + }, { + CustomMessage("some danger darts", /*german*/"", /*french*/"un paquet d'obus"), + // /*spanish*/unos cuantos peligrosos dardos + CustomMessage("some sharp shafts", /*german*/"", /*french*/"un paquet de piquets")}); + // /*spanish*/unas cuantas puntas afiladas + + hintTextTable[RHT_ARROWS_30] = HintText(CustomMessage("Arrows (30 pieces)", /*german*/"", /*french*/"une trentaine de flèches"), + // /*spanish*/unas (30) flechas + { + CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + // /*spanish*/un proyectil + }, { + CustomMessage("plenty of danger darts", /*german*/"", /*french*/"une abondance d'obus"), + // /*spanish*/bastantes peligrosos dardos + CustomMessage("plenty of sharp shafts", /*german*/"", /*french*/"une abondance de piquets")}); + // /*spanish*/bastantes puntas afiladas + + hintTextTable[RHT_DEKU_NUTS_5] = HintText(CustomMessage("Deku Nuts (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de noix Mojo"), + // /*spanish*/unas (5) nueces deku + { + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + // /*spanish*/un montón de municiones Deku + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("some nuts", /*german*/"", /*french*/"une poignée de noisettes"), + // /*spanish*/un par de nueces + CustomMessage("some flashbangs", /*german*/"", /*french*/"une poignée d'éclats"), + // /*spanish*/un par de semillas aturdidoras + CustomMessage("some scrub spit", /*german*/"", /*french*/"une poignée de crachats Mojo")}); + // /*spanish*/un par de escupitajos deku + + hintTextTable[RHT_DEKU_NUTS_10] = HintText(CustomMessage("Deku Nuts (10 pieces)", /*german*/"", /*french*/"une dizaine de noix Mojo"), + // /*spanish*/unas (10) nueces deku + { + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + // /*spanish*/un montón de municiones Deku + CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + // /*spanish*/algo que pueda paralizar + }, { + CustomMessage("lots-o-nuts", /*german*/"", /*french*/"un paquet de noisettes"), + // /*spanish*/un puñado de nueces + CustomMessage("plenty of flashbangs", /*german*/"", /*french*/"un paquet d'éclats"), + // /*spanish*/unas cuantas semillas aturdidoras + CustomMessage("plenty of scrub spit", /*german*/"", /*french*/"un paquet de crachats Mojo")}); + // /*spanish*/unos cuantos escupitajos deku + + hintTextTable[RHT_DEKU_SEEDS_30] = HintText(CustomMessage("Deku Seeds (30 pieces)", /*german*/"", /*french*/"une trentaine de graines Mojo"), + // /*spanish*/unas (30) semillas deku + { + CustomMessage("a projectile", /*german*/"", /*french*/"un projectile"), + // /*spanish*/un proyectil + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + // /*spanish*/un montón de municiones Deku + }, { + CustomMessage("catapult ammo", /*german*/"", /*french*/"un paquet de délicieuses munitions"), + // /*spanish*/un par de munición infantil + CustomMessage("lots-o-seeds", /*german*/"", /*french*/"un paquet de germes séchés")}); + // /*spanish*/un puñado de semillas + + hintTextTable[RHT_DEKU_STICK_1] = HintText(CustomMessage("a Deku Stick", /*german*/"", /*french*/"un bâton Mojo"), + // /*spanish*/un palo deku + { + CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + // /*spanish*/un montón de municiones Deku + }, { + CustomMessage("a breakable branch", /*german*/"", /*french*/"un bout de bois")}); + // /*spanish*/un pequeño báculo + + hintTextTable[RHT_TREASURE_GAME_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"", /*french*/"un Quart de Coeur"), + // /*spanish*/el amor de la victoria + { + CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + // /*spanish*/algo con forma de corazón + }, { + CustomMessage("a victory valentine", /*german*/"", /*french*/"un amour gagnant")}); + // /*spanish*/el amor victorioso + + hintTextTable[RHT_TREASURE_GAME_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert"), + // /*spanish*/una rupia verde + { + CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + // /*spanish*/una cantidad de rupias + }, { + CustomMessage("the dollar of defeat", /*german*/"", /*french*/"le rubis de la défaite")}); + // /*spanish*/el peso de la derrota + + hintTextTable[RHT_TRIFORCE_PIECE] = HintText(CustomMessage("a Piece of the Triforce", /*german*/"", /*french*/"un fragment de la Triforce"), + // /*spanish*/un fragmento de la Trifuerza + {}, { + CustomMessage("a triumph fork", /*german*/"", /*french*/"la Tribosse"), + // /*spanish*/un trígono del triunfo + CustomMessage("cheese", /*german*/"", /*french*/"du fromage"), + // /*spanish*/un porción de queso + CustomMessage("a gold fragment", /*german*/"", /*french*/"un fragment d'or")}); + // /*spanish*/un fragmento dorado + + hintTextTable[RHT_GOHMA_SOUL] = HintText(CustomMessage("the soul of Gohma", /*german*/"", /*french*/""), + { + CustomMessage("something webbed", /*german*/"", /*french*/"") + }, { + CustomMessage("an invasive soul", /*german*/"", /*french*/""), + CustomMessage("some spider essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_KING_DODONGO_SOUL] = HintText(CustomMessage("the soul of King Dodongo", /*german*/"", /*french*/""), + { + CustomMessage("something explosive", /*german*/"", /*french*/"") + }, { + CustomMessage("a royal soul", /*german*/"", /*french*/""), + CustomMessage("some reptile essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_BARINADE_SOUL] = HintText(CustomMessage("the soul of Barinade", /*german*/"", /*french*/""), + { + CustomMessage("something fishy", /*german*/"", /*french*/"") + }, { + CustomMessage("an infectuous soul", /*german*/"", /*french*/""), + CustomMessage("some parasitic essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_PHANTOM_GANON_SOUL] = HintText(CustomMessage("the soul of Phantom Ganon", /*german*/"", /*french*/""), + { + CustomMessage("something spectral", /*german*/"", /*french*/"") + }, { + CustomMessage("a duplicate soul", /*german*/"", /*french*/""), + + CustomMessage("some illusionary essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_VOLVAGIA_SOUL] = HintText(CustomMessage("the soul of Volvagia", /*german*/"", /*french*/""), + { + CustomMessage("something hot", /*german*/"", /*french*/"") + }, { + CustomMessage("a draconic soul", /*german*/"", /*french*/""), + CustomMessage("some magmatic essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_MORPHA_SOUL] = HintText(CustomMessage("the soul of Barinade", /*german*/"", /*french*/""), + { + CustomMessage("something wet", /*german*/"", /*french*/"") + }, { + CustomMessage("an aquatic soul", /*german*/"", /*french*/""), + CustomMessage("some liquid essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_BONGO_BONGO_SOUL] = HintText(CustomMessage("the soul of Bongo Bongo", /*german*/"", /*french*/""), + { + CustomMessage("something dark", /*german*/"", /*french*/"") + }, { + CustomMessage("a shadowy soul", /*german*/"", /*french*/""), + CustomMessage("some handy essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_TWINROVA_SOUL] = HintText(CustomMessage("the soul of Twinrova", /*german*/"", /*french*/""), + { + CustomMessage("something spiritual", /*german*/"", /*french*/"") + }, { + CustomMessage("old souls", /*german*/"", /*french*/""), + CustomMessage("twin essences", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_GANON_SOUL] = HintText(CustomMessage("the soul of Ganon", /*german*/"", /*french*/""), + { + CustomMessage("something strong", /*german*/"", /*french*/"") + }, { + CustomMessage("an evil soul", /*german*/"", /*french*/""), + CustomMessage("some powerful essence", /*german*/"", /*french*/"")}); + + hintTextTable[RHT_OCARINA_A_BUTTON] = HintText(CustomMessage("an Ocarina A Button", /*german*/"", /*french*/"la Touche A de l'Ocarina"), + // /*spanish*/un botón A de Ocarina + { + CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + // /*spanish*/algo melódico + }, { + CustomMessage("a musical letter", /*german*/"", /*french*/"une lettre musicale")}); + // /*spanish*/una letra musical + + hintTextTable[RHT_OCARINA_C_UP_BUTTON] = HintText(CustomMessage("an Ocarina C Up Button", /*german*/"", /*french*/"la Touche C-Haut de l'Ocarina"), + // /*spanish*/un botón C superior de Ocarina + { + CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + // /*spanish*/algo melódico + }, { + CustomMessage("a high tone", /*german*/"", /*french*/"une tonalité élevée")}); + // /*spanish*/un tono alto + + hintTextTable[RHT_OCARINA_C_DOWN_BUTTON] = HintText(CustomMessage("an Ocarina C Down Button", /*german*/"", /*french*/"la Touche C-Bas de l'Ocarina"), + // /*spanish*/un botón C inferior de Ocarina + { + CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + // /*spanish*/algo melódico + }, { + CustomMessage("a low tone", /*german*/"", /*french*/"une tonalité basse")}); + // /*spanish*/un tono bajo + + hintTextTable[RHT_OCARINA_C_LEFT_BUTTON] = HintText(CustomMessage("an Ocarina C Left Button", /*german*/"", /*french*/"la Touche C-Gauche de l'Ocarina"), + // /*spanish*/un botón C izquierdo de Ocarina + { + CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + // /*spanish*/algo melódico + }, { + CustomMessage("a leftward tone", /*german*/"", /*french*/"une tonalité vers la gauche")}); + // /*spanish*/un tono hacia la izquierda + + hintTextTable[RHT_OCARINA_C_RIGHT_BUTTON] = HintText(CustomMessage("an Ocarina C Right Button", /*german*/"", /*french*/"la Touche C-Droit de l'Ocarina"), + // /*spanish*/un botón C derecho de Ocarina + { + CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + // /*spanish*/algo melódico + }, { + CustomMessage("a rightward tone", /*german*/"", /*french*/"une tonalité vers la droite")}); + // /*spanish*/un tono hacia la derecha + + hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"", /*french*/"canne à pêche"), + // /*spanish*/caña de pescar + { + CustomMessage("the pond owner's property", /*german*/"", /*french*/"(canne à pêche)") + // /*spanish*/(caña de pescar) + }, { + CustomMessage("a fish-puller", /*german*/"", /*french*/"(canne à pêche)")}); + // /*spanish*/(caña de pescar) + + hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"", /*french*/"Epona"), + // /*spanish*/a Epona + { + CustomMessage("something from Malon", /*german*/"", /*french*/"un cadeau de Malon"), + // /*spanish*/un obsequio de Malon + CustomMessage("a song sung by frogs", /*german*/"", /*french*/"une chanson aimée des grenouilles"), + // /*spanish*/una melodía de ranas + CustomMessage("something to cross a broken bridge", /*german*/"", /*french*/"une chose pour traverser un pont brisé") + // /*spanish*/algo para cruzar un puente roto + }, { + CustomMessage("a horse", /*german*/"", /*french*/"un fidèle destrier"), + // /*spanish*/una yegua + CustomMessage("a four legged friend", /*german*/"", /*french*/"un puissant animal")}); + // /*spanish*/una amiga cuadrúpeda + + //What is this used for? + hintTextTable[RHT_HINT_MYSTERIOUS] = HintText(CustomMessage("something mysterious", /*german*/"etwas Unvorhergesehenes", /*french*/"un sacré mystère")); + // /*spanish*/algo misterioso + + hintTextTable[RHT_MYSTERIOUS_ITEM] = HintText(CustomMessage("mysterious item", /*german*/"mysteriösen Gegenstand", /*french*/"objet mystérieux")); + // /*spanish*/algo misterioso + } +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index e007c06af..1c1edd62d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -4,38 +4,87 @@ #include "random.hpp" #include "spoiler_log.hpp" #include "fill.hpp" -#include "hint_list.hpp" #include "../trial.h" #include "../entrance.h" #include "z64item.h" #include #include "../randomizerTypes.h" -#include "../context.h" #include "pool_functions.hpp" +#include "../hint.h" +#include "../static_data.h" -#define QM_WHITE "%w" -#define QM_RED "%r" -#define QM_GREEN "%g" -#define QM_BLUE "%b" -#define QM_LBLUE "%c" -#define QM_PINK "%p" -#define QM_YELLOW "%y" -#define QM_BLACK "%B" using namespace Rando; -const Text& HintText::GetText() const { - auto ctx = Rando::Context::GetInstance(); +HintDistributionSetting::HintDistributionSetting(std::string _name, + HintType _type, + uint32_t _weight, + uint8_t _fixed, + uint8_t _copies, + std::function _filter, + uint8_t _dungeonLimit){ + name = _name; + type = _type; + weight = _weight; + fixed = _fixed; + copies = _copies; + filter = _filter; + dungeonLimit = _dungeonLimit; + } + +HintText::HintText(CustomMessage clearText_, std::vector ambiguousText_, std::vector obscureText_) +: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)){} + +const CustomMessage& HintText::GetClear() const { + return clearText; +} + +const CustomMessage& HintText::GetObscure() const { + return obscureText.size() > 0 ? RandomElement(obscureText) : clearText; +} + +const CustomMessage& HintText::GetObscure(uint8_t selection) const { + if (obscureText.size() > selection){ + return obscureText[selection]; + } else if (obscureText.size() > 0) { + return obscureText[0]; + } + return clearText; +} + +const CustomMessage& HintText::GetAmbiguous() const { + return ambiguousText.size() > 0 ? RandomElement(ambiguousText) : clearText; +} + +const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const { + if (ambiguousText.size() > selection){ + return ambiguousText[selection]; + } else if (ambiguousText.size() > 0) { + return ambiguousText[0]; + } + return clearText; +} + +uint8_t HintText::GetAmbiguousSize() const{ + return ambiguousText.size(); +} + +uint8_t HintText::GetObscureSize() const{ + return obscureText.size(); +} + +const CustomMessage& HintText::GetHintMessage(uint8_t selection) const { + auto ctx = Rando::Context::GetInstance(); if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) { - return GetObscure(); + return GetObscure(selection); } else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) { - return GetAmbiguous(); + return GetAmbiguous(selection); } else { return GetClear(); } } -const Text HintText::GetTextCopy() const { +const CustomMessage HintText::GetMessageCopy() const { auto ctx = Rando::Context::GetInstance(); if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) { return GetObscure(); @@ -46,33 +95,34 @@ const Text HintText::GetTextCopy() const { } } -std::array hintTypeNames = { - "Static", - "Trial", - "WotH", - "Barren", - "Entrance", - "Item Area", - "Item Location", - "Junk" -}; +bool HintText::operator==(const HintText& right) const { + return obscureText == right.obscureText && + ambiguousText == right.ambiguousText && + clearText == right.clearText; +} + +bool HintText::operator!=(const HintText& right) const { + return !operator==(right); +} + +StaticHintInfo::StaticHintInfo(HintType _type, std::vector _hintKeys, RandomizerSettingKey _setting, + std::variant _condition, std::vector _targetChecks, + std::vector _targetItems, std::vector _hintChecks, bool _yourPocket, int _num): + type(_type), hintKeys(_hintKeys), setting(_setting), condition(_condition), targetChecks(_targetChecks), + targetItems(_targetItems), hintChecks(_hintChecks), yourPocket(_yourPocket), num(_num){} + +RandomizerHintTextKey GetRandomJunkHint(){ + //temp code to handle random junk hints now I work in keys instead of a vector of HintText + // Will be replaced with a better system once more customisable hint pools are added + uint32_t range = RHT_JUNK_SG_8 - RHT_JUNK02; + return (RandomizerHintTextKey)(Random(0, range) + RHT_JUNK02); +} + +RandomizerHintTextKey GetRandomGanonJoke(){ + uint32_t range = RHT_GANON_JOKE11 - RHT_GANON_JOKE01; + return (RandomizerHintTextKey)(Random(0, range) + RHT_GANON_JOKE01); +} -std::array, 14> staticHintLocations = {{ - {RC_KAK_10_GOLD_SKULLTULA_REWARD, RSK_KAK_10_SKULLS_HINT}, - {RC_KAK_20_GOLD_SKULLTULA_REWARD, RSK_KAK_20_SKULLS_HINT}, - {RC_KAK_30_GOLD_SKULLTULA_REWARD, RSK_KAK_30_SKULLS_HINT}, - {RC_KAK_40_GOLD_SKULLTULA_REWARD, RSK_KAK_40_SKULLS_HINT}, - {RC_KAK_50_GOLD_SKULLTULA_REWARD, RSK_KAK_50_SKULLS_HINT}, - {RC_KAK_100_GOLD_SKULLTULA_REWARD, RSK_KAK_100_SKULLS_HINT}, - {RC_SONG_FROM_IMPA, RSK_SKIP_CHILD_ZELDA}, - {RC_ZR_FROGS_OCARINA_GAME, RSK_FROGS_HINT}, - {RC_DMT_TRADE_CLAIM_CHECK, RSK_BIGGORON_HINT}, - {RC_MARKET_10_BIG_POES, RSK_BIG_POES_HINT}, - {RC_KAK_ANJU_AS_CHILD, RSK_CHICKENS_HINT}, - {RC_KF_LINKS_HOUSE_COW, RSK_MALON_HINT}, - {RC_GF_HBA_1000_POINTS, RSK_HBA_HINT}, - {RC_GF_HBA_1500_POINTS, RSK_HBA_HINT}, - }}; bool FilterWotHLocations(RandomizerCheck loc){ auto ctx = Rando::Context::GetInstance(); @@ -125,14 +175,14 @@ const std::array hintSettingTable{{ .trialCopies = 1, .junkWeight = 6, .distTable = { - {"WotH", HINT_TYPE_WOTH, 7, 0, 1, FilterWotHLocations, 2}, - {"Barren", HINT_TYPE_BARREN, 4, 0, 1, FilterBarrenLocations, 1}, + {"WotH", HINT_TYPE_WOTH, 7, 0, 1, FilterWotHLocations, 2}, + {"Barren", HINT_TYPE_FOOLISH, 4, 0, 1, FilterBarrenLocations, 1}, //("Entrance", HINT_TYPE_ENTRANCE, 6, 0, 1), //not yet implemented - {"Song", HINT_TYPE_ITEM_LOCATION, 2, 0, 1, FilterSongLocations}, - {"Overworld", HINT_TYPE_ITEM_LOCATION, 4, 0, 1, FilterOverworldLocations}, - {"Dungeon", HINT_TYPE_ITEM_LOCATION, 3, 0, 1, FilterDungeonLocations}, - {"Named Item", HINT_TYPE_ITEM_AREA, 10, 0, 1, FilterGoodItems}, - {"Random" , HINT_TYPE_ITEM_AREA, 12, 0, 1, NoFilter} + {"Song", HINT_TYPE_ITEM, 2, 0, 1, FilterSongLocations}, + {"Overworld", HINT_TYPE_ITEM, 4, 0, 1, FilterOverworldLocations}, + {"Dungeon", HINT_TYPE_ITEM, 3, 0, 1, FilterDungeonLocations}, + {"Named Item", HINT_TYPE_ITEM_AREA, 10, 0, 1, FilterGoodItems}, + {"Random" , HINT_TYPE_ITEM_AREA, 12, 0, 1, NoFilter} } }, // Strong hints @@ -141,14 +191,14 @@ const std::array hintSettingTable{{ .trialCopies = 1, .junkWeight = 0, .distTable = { - {"WotH", HINT_TYPE_WOTH, 12, 0, 2, FilterWotHLocations, 2}, - {"Barren", HINT_TYPE_BARREN, 12, 0, 1, FilterBarrenLocations, 1}, + {"WotH", HINT_TYPE_WOTH, 12, 0, 2, FilterWotHLocations, 2}, + {"Barren", HINT_TYPE_FOOLISH, 12, 0, 1, FilterBarrenLocations, 1}, //{"Entrance", HINT_TYPE_ENTRANCE, 4, 0, 1}, //not yet implemented - {"Song", HINT_TYPE_ITEM_LOCATION, 4, 0, 1, FilterSongLocations}, - {"Overworld", HINT_TYPE_ITEM_LOCATION, 6, 0, 1, FilterOverworldLocations}, - {"Dungeon", HINT_TYPE_ITEM_LOCATION, 6, 0, 1, FilterDungeonLocations}, - {"Named Item", HINT_TYPE_ITEM_AREA, 8, 0, 1, FilterGoodItems}, - {"Random" , HINT_TYPE_ITEM_AREA, 8, 0, 1, NoFilter}, + {"Song", HINT_TYPE_ITEM, 4, 0, 1, FilterSongLocations}, + {"Overworld", HINT_TYPE_ITEM, 6, 0, 1, FilterOverworldLocations}, + {"Dungeon", HINT_TYPE_ITEM, 6, 0, 1, FilterDungeonLocations}, + {"Named Item", HINT_TYPE_ITEM_AREA, 8, 0, 1, FilterGoodItems}, + {"Random" , HINT_TYPE_ITEM_AREA, 8, 0, 1, NoFilter}, }, }, // Very strong hints @@ -157,169 +207,111 @@ const std::array hintSettingTable{{ .trialCopies = 1, .junkWeight = 0, .distTable = { - {"WotH", HINT_TYPE_WOTH, 15, 0, 2, FilterWotHLocations}, - {"Barren", HINT_TYPE_BARREN, 15, 0, 1, FilterBarrenLocations}, + {"WotH", HINT_TYPE_WOTH, 15, 0, 2, FilterWotHLocations}, + {"Barren", HINT_TYPE_FOOLISH, 15, 0, 1, FilterBarrenLocations}, //{"Entrance", HINT_TYPE_ENTRANCE, 10, 0, 1}, //not yet implemented - {"Song", HINT_TYPE_ITEM_LOCATION, 2, 0, 1, FilterSongLocations}, - {"Overworld", HINT_TYPE_ITEM_LOCATION, 7, 0, 1, FilterOverworldLocations}, - {"Dungeon", HINT_TYPE_ITEM_LOCATION, 7, 0, 1, FilterDungeonLocations}, - {"Named Item", HINT_TYPE_ITEM_AREA, 5, 0, 1, FilterGoodItems}, + {"Song", HINT_TYPE_ITEM, 2, 0, 1, FilterSongLocations}, + {"Overworld", HINT_TYPE_ITEM, 7, 0, 1, FilterOverworldLocations}, + {"Dungeon", HINT_TYPE_ITEM, 7, 0, 1, FilterDungeonLocations}, + {"Named Item", HINT_TYPE_ITEM_AREA, 5, 0, 1, FilterGoodItems}, }, }, }}; -static std::map pixelWidthTable = { - { " ", 6 }, { "!", 6 }, { "\"", 5 }, { "#", 7 }, { "$", 7 }, { "%", 11 }, { "&", 9 }, { "\'", 3 }, - { "(", 6 }, { ")", 6 }, { "*", 6 }, { "+", 7 }, { ",", 3 }, { "-", 5 }, { ".", 3 }, { "/", 7 }, - { "0", 8 }, { "1", 4 }, { "2", 7 }, { "3", 7 }, { "4", 8 }, { "5", 7 }, { "6", 7 }, { "7", 7 }, - { "8", 7 }, { "9", 7 }, { ":", 5 }, { ";", 5 }, { "<", 7 }, { "=", 9 }, { ">", 7 }, { "?", 9 }, - { "@", 10 }, { "A", 9 }, { "B", 7 }, { "C", 9 }, { "D", 9 }, { "E", 6 }, { "F", 6 }, { "G", 9 }, - { "H", 8 }, { "I", 3 }, { "J", 6 }, { "K", 8 }, { "L", 6 }, { "M", 10 }, { "N", 9 }, { "O", 10 }, - { "P", 7 }, { "Q", 10 }, { "R", 8 }, { "S", 8 }, { "T", 7 }, { "U", 8 }, { "V", 9 }, { "W", 12 }, - { "X", 9 }, { "Y", 8 }, { "Z", 8 }, { "[", 6 }, { "\\", 8 }, { "]", 6 }, { "^", 8 }, { "_", 7 }, - { "`", 4 }, { "a", 6 }, { "b", 7 }, { "c", 6 }, { "d", 7 }, { "e", 7 }, { "f", 5 }, { "g", 7 }, - { "h", 6 }, { "i", 3 }, { "j", 5 }, { "k", 6 }, { "l", 3 }, { "m", 9 }, { "n", 7 }, { "o", 7 }, - { "p", 7 }, { "q", 7 }, { "r", 6 }, { "s", 6 }, { "t", 6 }, { "u", 6 }, { "v", 7 }, { "w", 9 }, - { "x", 6 }, { "y", 7 }, { "z", 6 }, { "{", 6 }, { "¦", 4 }, { "}", 6 }, { "¡", 5 }, { "¢", 7 }, - { "£", 8 }, { "¤", 7 }, { "¥", 8 }, { "|", 4 }, { "§", 12 }, { "¨", 12 }, { "©", 10 }, { "ª", 5 }, - { "«", 8 }, { "¬", 7 }, { "\u00AD", 6 }, { "®", 10 }, { "¯", 8 }, { "°", 12 }, { "±", 12 }, { "²", 5 }, - { "³", 5 }, { "µ", 6 }, { "¶", 8 }, { "·", 4 }, { "¹", 4 }, { "º", 5 }, { "»", 9 }, { "¼", 9 }, - { "½", 9 }, { "¾", 10 }, { "¿", 7 }, { "À", 11 }, { "Á", 9 }, { "Â", 9 }, { "Ã", 9 }, { "Ä", 9 }, - { "Å", 9 }, { "Æ", 12 }, { "Ç", 9 }, { "È", 6 }, { "É", 6 }, { "Ê", 6 }, { "Ë", 6 }, { "Ì", 5 }, - { "Í", 5 }, { "Î", 5 }, { "Ï", 5 }, { "Ð", 10 }, { "Ñ", 9 }, { "Ò", 10 }, { "Ó", 10 }, { "Ô", 10 }, - { "Õ", 10 }, { "Ö", 10 }, { "×", 9 }, { "Ø", 10 }, { "Ù", 8 }, { "Ú", 8 }, { "Û", 8 }, { "Ü", 8 }, - { "Ý", 10 }, { "Þ", 8 }, { "ß", 7 }, { "à", 6 }, { "á", 6 }, { "â", 6 }, { "ã", 6 }, { "ä", 6 }, - { "å", 6 }, { "æ", 11 }, { "ç", 6 }, { "è", 7 }, { "é", 7 }, { "ê", 7 }, { "ë", 7 }, { "ì", 5 }, - { "í", 5 }, { "î", 5 }, { "ï", 5 }, { "ð", 7 }, { "ñ", 7 }, { "ò", 7 }, { "ó", 7 }, { "ô", 7 }, - { "õ", 7 }, { "ö", 7 }, { "÷", 11 }, { "ø", 9 }, { "ù", 7 }, { "ú", 7 }, { "û", 7 }, { "ü", 7 }, - { "ý", 8 }, { "þ", 8 }, { "ÿ", 8 }, { "Œ", 11 }, { "œ", 11 }, { "„", 5 }, { "”", 5 }, { "€", 10 }, - { "Ÿ", 10 }, { "~", 8 } +uint8_t StonesRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); + uint8_t stones = 0; + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value(); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 6; + } else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 6; + } + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + stones = std::max({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Value() }); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 6 )}); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { + stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 6 )}); + } + return stones; +} + +uint8_t MedallionsRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); + uint8_t medallions = 0; + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value(); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 3; + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 3; + } + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { + medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value() }); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { + medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 3 )}); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { + medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 3 )}); + } + return medallions; +} + +uint8_t TokensRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); + uint8_t tokens = 0; + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { + tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value(); + } + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { + tokens = std::max({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value() }); + } + return tokens; +} + +std::vector>> conditionalAlwaysHints = { + std::make_pair(RC_MARKET_10_BIG_POES, []() { + auto ctx = Rando::Context::GetInstance(); + return ctx->GetOption(RSK_BIG_POE_COUNT).Value() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); + }), // Remember, the option's value being 3 means 4 are required + std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); + }), + std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), + std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), + std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), + std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_BIGGORON_HINT); + }), + std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_KAK_30_SKULLS_HINT) && TokensRequiredBySettings() < 30; + }), + std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_KAK_40_SKULLS_HINT) && TokensRequiredBySettings() < 40; + }), + std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_KAK_50_SKULLS_HINT) && TokensRequiredBySettings() < 50; + }), + std::make_pair(RC_ZR_FROGS_OCARINA_GAME, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_FROGS_HINT); + }), + std::make_pair(RC_KF_LINKS_HOUSE_COW, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_MALON_HINT); + }), + std::make_pair(RC_KAK_100_GOLD_SKULLTULA_REWARD, []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && TokensRequiredBySettings() < 100; + }), }; -static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) { - const size_t maxLinePixelWidth = hasIcon ? 200 : 216; - - - size_t totalPixelWidth = 0; - size_t currentPos = lastNewline; - - // Looping through the string from the lastNewline until the total - // width of counted characters exceeds the maximum pixels in a line. - size_t nextPosJump = 0; - while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { - // Skip over control codes - if (textStr->at(currentPos) == '%') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '$') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '@') { - nextPosJump = 1; - // Assume worst case for player name 12 * 8 (widest character * longest name length) - totalPixelWidth += 96; - } else { - // Some characters only one byte while others are two bytes - // So check both possibilities when checking for a character - if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; - nextPosJump = 1; - } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; - nextPosJump = 2; - } else { - SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); - SPDLOG_DEBUG("Full string: " + *textStr); - nextPosJump = 1; - } - } - currentPos += nextPosJump; - } - // return the total number of characters we looped through - if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') { - return currentPos - lastNewline - nextPosJump; - } else { - return currentPos - lastNewline; - } -} - -Text AutoFormatHintText(const Text& unformattedHintText, const std::vector& colors = {}) { - std::array strings; - for (int i = 0; i < LANGUAGE_MAX; i++) { - std::string textStr = unformattedHintText.GetForLanguage(i); - - for (const auto& color: colors) { - if (const size_t firstHashtag = textStr.find('#'); firstHashtag != std::string::npos) { - textStr.replace(firstHashtag, 1, color); - if (const size_t secondHashtag = textStr.find('#', firstHashtag + 1); secondHashtag != std::string::npos) { - textStr.replace(secondHashtag, 1, QM_WHITE); - } else { - SPDLOG_DEBUG("non-matching hashtags in string: \"%s\"", textStr); - } - } - } - // Remove any remaining '#' characters. - std::erase(textStr, '#'); - - // insert newlines either manually or when encountering a '&' - size_t lastNewline = 0; - const bool hasIcon = textStr.find('$', 0) != std::string::npos; - size_t lineLength = NextLineLength(&textStr, lastNewline, hasIcon); - while (lastNewline + lineLength < textStr.length()) { - const size_t carrot = textStr.find('^', lastNewline); - const size_t ampersand = textStr.find('&', lastNewline); - const size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength); - const size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength); - // replace '&' first if it's within the newline range - if (ampersand < lastNewline + lineLength) { - lastNewline = ampersand + 1; - // 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, ".&"); - lastNewline = lastPeriod + 2; - } else { - textStr.replace(lastSpace, 1, "&"); - lastNewline = lastSpace + 1; - } - lineLength = NextLineLength(&textStr, lastNewline, hasIcon); - } - strings[i] = textStr; - } - - return {strings[0], strings[2], ""/*spanish*/, strings[1]}; -} - -std::array dungeonInfoData; - -Text childAltarText; -Text adultAltarText; -Text ganonText; -Text ganonHintText; -Text sheikText; -Text warpMinuetText; -Text warpBoleroText; -Text warpSerenadeText; -Text warpRequiemText; -Text warpNocturneText; -Text warpPreludeText; - -std::string masterSwordHintLoc; -std::string lightArrowHintLoc; - -void SetGanonText(Text text){ - ganonText = text; -} - - -std::string GetMasterSwordHintLoc() { - return masterSwordHintLoc; -} - -std::string GetLightArrowHintLoc() { - return lightArrowHintLoc; -} - static std::vector GetEmptyGossipStones() { auto emptyGossipStones = GetEmptyLocations(Rando::StaticData::gossipStoneLocations); return emptyGossipStones; @@ -365,34 +357,32 @@ static void SetAllInRegionAsHinted(RandomizerArea area, std::vectorGetItemLocation(loc)->GetArea() == area; }); for(RandomizerCheck loc: locsInRegion){ - ctx->GetItemLocation(loc)->SetAsHinted(); + ctx->GetItemLocation(loc)->SetHintAccesible(); } } -static void AddGossipStoneHint(Text hint, - const RandomizerCheck gossipStone, - const std::vector& colors, - HintType hintType, - std::string distributionName, - const RandomizerCheck hintedLocation) { - //save hints as dummy items for writing to the spoiler log - //NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE}); - //GetLocation(gossipStone)->SetPlacedItem(gossipStone); +static void AddGossipStoneHint( const RandomizerCheck gossipStone, + const HintType hintType, + const std::string distributionName, + const std::vector hintKeys, + const std::vector locations, + const std::vector trials) { auto ctx = Rando::Context::GetInstance(); - ctx->AddHint((RandomizerHintKey)((gossipStone - RC_COLOSSUS_GOSSIP_STONE) + 1), AutoFormatHintText(hint, colors), hintedLocation, hintType, distributionName, ctx->GetItemLocation(hintedLocation)->GetArea()); + ctx->AddHint(StaticData::gossipStoneCheckToHint[gossipStone], Hint(StaticData::gossipStoneCheckToHint[gossipStone], hintType, distributionName, hintKeys, locations, {}, trials)); ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT); //RANDOTODO, better gossip stone to location to hint key system } static void AddGossipStoneHintCopies(uint8_t copies, - Text hint, - std::vector colours, - HintType type, - std::string distributionName, - RandomizerCheck location = RC_UNKNOWN_CHECK, - RandomizerCheck firstStone = RC_UNKNOWN_CHECK){ + const HintType hintType, + const std::string distributionName, + const std::vector hintKeys = {}, + const std::vector locations = {}, + const std::vector trials = {}, + RandomizerCheck firstStone = RC_UNKNOWN_CHECK){ + if (firstStone != RC_UNKNOWN_CHECK && copies > 0){ - AddGossipStoneHint(hint, firstStone, colours, type, distributionName, location); + AddGossipStoneHint(firstStone, hintType, distributionName, hintKeys, locations, trials); copies -= 1; } for(int c=0; c gossipStoneLocations; - gossipStoneLocations = GetAccessibleGossipStones(hintedLocation); + //get a gossip stone accessible without the hinted item + std::vector gossipStoneLocations = GetAccessibleGossipStones(location); if (gossipStoneLocations.empty()) { SPDLOG_DEBUG("\tNO IN LOGIC GOSSIP STONE\n\n"); return false; } - RandomizerCheck gossipStone = RandomElement(gossipStoneLocations); //make hint text - Text finalHint; - Text prefix = ::Hint(RHT_PREFIX).GetText(); - std::vector colours; - if (type == HINT_TYPE_WOTH){ - Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText(); - finalHint = prefix + "#" + areaText + "#" + ::Hint(RHT_WAY_OF_THE_HERO).GetText(); - colours = {QM_RED, QM_LBLUE}; - } - else if(type == HINT_TYPE_BARREN){ - Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText(); - finalHint = prefix + ::Hint(RHT_PLUNDERING).GetText() + "#" + areaText + "#" + ::Hint(RHT_FOOLISH).GetText(); - colours = {QM_RED, QM_PINK}; - } - else { - Text itemText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText(); - if (type == HINT_TYPE_ITEM_LOCATION){ - Text locationText = Rando::StaticData::GetLocation(hintedLocation)->GetHint()->GetText(); - finalHint = prefix + locationText + " #"+itemText+"#."; - colours = {QM_RED, QM_GREEN}; - } - else if (type == HINT_TYPE_ITEM_AREA){ - Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText(); - if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) { - finalHint = prefix+"#"+areaText+"# "+::Hint(RHT_HOARDS).GetText()+" #"+itemText+"#."; - colours = {QM_RED, QM_GREEN}; - } else { - finalHint = prefix+"#"+itemText+"# "+::Hint(RHT_CAN_BE_FOUND_AT).GetText()+" #"+areaText+"#."; - colours = {QM_GREEN, QM_RED}; - } - } - else{ - SPDLOG_DEBUG("\tINVALID HINT TYPE\n\n"); - return false; - } - } - - ctx->GetItemLocation(hintedLocation)->SetAsHinted(); - SPDLOG_DEBUG("\tMessage: "); - SPDLOG_DEBUG(finalHint.english); - SPDLOG_DEBUG("\n\n"); - - AddGossipStoneHintCopies(copies, finalHint, colours, type, distributionName, hintedLocation, gossipStone); + ctx->GetItemLocation(location)->SetHintAccesible(); + AddGossipStoneHintCopies(copies, type, distribution, {}, {location}, {}, gossipStone); return true; } @@ -501,7 +448,7 @@ static RandomizerCheck CreateRandomHint(std::vector& possibleHi placed = CreateHint(hintedLocation, copies, type, distributionName); } - if (type == HINT_TYPE_BARREN){ + if (type == HINT_TYPE_FOOLISH){ SetAllInRegionAsHinted(ctx->GetItemLocation(hintedLocation)->GetArea(), possibleHintLocations); } return hintedLocation; @@ -511,7 +458,7 @@ static std::vector FilterHintability(std::vector extraFilter = NoFilter){ auto ctx = Rando::Context::GetInstance(); return FilterFromPool(locations, [extraFilter, ctx](const RandomizerCheck loc) { - return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt()) + return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsAHintAccessible()) && extraFilter(loc); }); } @@ -519,426 +466,60 @@ static std::vector FilterHintability(std::vector 0) { auto ctx = Rando::Context::GetInstance(); - Text prefix = ::Hint(RHT_PREFIX).GetText(); - //six trials - if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) { - AddGossipStoneHintCopies(copies, prefix + ::Hint(RHT_SIX_TRIALS).GetText(), {QM_PINK}, HINT_TYPE_TRIAL, "Trial"); - //zero trials - } else if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { - AddGossipStoneHintCopies(copies, prefix + ::Hint(RHT_ZERO_TRIALS).GetText(), {QM_YELLOW}, HINT_TYPE_TRIAL, "Trial"); - //4 or 5 required trials - } else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(5) || ctx->GetOption(RSK_TRIAL_COUNT).Is(4)) { - //get skipped trials - std::vector trials = {}; - auto trialList = ctx->GetTrials()->GetTrialList(); - 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) { - //make hint - auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText(); - AddGossipStoneHintCopies(copies, hint, {QM_YELLOW}, HINT_TYPE_TRIAL, "Trial"); - } - //1 to 3 trials - } else if (ctx->GetOption(RSK_TRIAL_COUNT).Value() >= 1 && ctx->GetOption(RSK_TRIAL_COUNT).Value() <= 3) { - //get requried trials - std::vector trials = {}; - auto trialList = ctx->GetTrials()->GetTrialList(); - 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) { - //make hint - auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_ONE_TO_THREE_TRIALS).GetText(); - AddGossipStoneHintCopies(copies, hint, {QM_PINK}, HINT_TYPE_TRIAL, "Trial"); - } - } - } -} - -//RANDOTODO clean this mess up once starting items are expanded -void CreateGanonAndSheikText() { - auto ctx = Rando::Context::GetInstance(); - if(ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){ - //Get the location of the light arrows - auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { - return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS; - }); - RandomizerArea lightArrowArea = ctx->GetItemLocation(lightArrowLocation[0])->GetArea(); - Text LightArrowAreaText = ::Hint(lightArrowArea).GetText(); - std::vector locsToCheck = {RC_GANONDORF_HINT}; - - //If there is no light arrow location, it was in the player's inventory at the start - auto hint = ::Hint(RHT_LIGHT_ARROW_LOCATION_HINT); - if (lightArrowLocation.empty()) { - ganonHintText = hint.GetText()+::Hint(RHT_YOUR_POCKET).GetText(); - lightArrowHintLoc = "Link's Pocket"; + if (ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) {//six trials + AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_SIX_TRIALS}); + } else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) {//zero trials + AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_ZERO_TRIALS}); } else { - ganonHintText = hint.GetText() + "%r" + LightArrowAreaText + "%w"; - lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName(); - } - ganonHintText = ganonHintText + "!"; - - //Get the location of the master sword - auto masterSwordLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { - return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_MASTER_SWORD; - }); - Text masterSwordArea = ::Hint(ctx->GetItemLocation(masterSwordLocation[0])->GetArea()).GetText(); - - if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { - // Add second text box - ganonHintText = ganonHintText + "^"; - if (masterSwordLocation.empty()) { - ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + ::Hint(RHT_YOUR_POCKET).GetText() + "%w"; - masterSwordHintLoc = "Link's Pocket"; - } else { - ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + masterSwordArea + "%w"; - masterSwordHintLoc = Rando::StaticData::GetLocation(masterSwordLocation[0])->GetName(); + std::vector trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment + if (ctx->GetOption(RSK_TRIAL_COUNT).Value() >= 4) {//4 or 5 required trials, get skipped trials + trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();}); + } else {//1 to 3 trials, get requried trials + auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();}); } - ganonHintText = ganonHintText + "!"; - } - - ctx->AddHint(RH_GANONDORF_HINT, AutoFormatHintText(ganonHintText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea); - ctx->AddHint(RH_GANONDORF_NOHINT, AutoFormatHintText(ganonText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea); - - if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { - sheikText = ::Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + LightArrowAreaText + "%w."; - locsToCheck = {RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC}; - - if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { - sheikText = sheikText + "^" + ::Hint(RHT_SHEIK_MASTER_SWORD_LOCATION_HINT).GetText() + masterSwordArea + "%w."; - } - } - - if (IsReachableWithout(locsToCheck, lightArrowLocation[0], true)) { - ctx->GetItemLocation(lightArrowLocation[0])->SetAsHinted(); - } - ctx->AddHint(RH_SHEIK_LIGHT_ARROWS, AutoFormatHintText(sheikText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea); - - if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { - if (IsReachableWithout(locsToCheck, masterSwordLocation[0], true)) { - ctx->GetItemLocation(masterSwordLocation[0])->AddHintedBy(RH_GANONDORF_HINT); - ctx->GetItemLocation(masterSwordLocation[0])->SetAsHinted(); + for (auto& trial : trials) {//create a hint for each hinted trial + AddGossipStoneHintCopies(copies, HINT_TYPE_TRIAL, "Trial", {}, {}, {trial->GetTrialKey()}); } } } } -//Find the location which has the given itemKey and create the generic altar text for the reward -static Text BuildDungeonRewardText(const ItemID itemID, const RandomizerGet itemKey) { - auto ctx = Rando::Context::GetInstance(); - RandomizerCheck altarLoc = RC_ALTAR_HINT_ADULT; - if (itemKey == RG_KOKIRI_EMERALD || itemKey == RG_GORON_RUBY || itemKey == RG_ZORA_SAPPHIRE) { - altarLoc = RC_ALTAR_HINT_CHILD; - } - const RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) { - return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey; - })[0]; - if (IsReachableWithout({altarLoc}, location, true) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ //RANDOTODO check if works properly - ctx->GetItemLocation(location)->SetAsHinted(); - } - - std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD); - - // RANDOTODO implement colors for locations - return Text() + rewardString + "#" + - ::Hint(ctx->GetItemLocation(location)->GetArea()).GetText().Capitalize() + - "#...^"; -} - -static Text BuildDoorOfTimeText() { - auto ctx = Rando::Context::GetInstance(); - std::string itemObtained; - Text doorOfTimeText; - - if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { - itemObtained = "$o"; - doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText(); - - } else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY)) { - itemObtained = "$c"; - doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText(); - - } else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_CLOSED)) { - itemObtained = "$i"; - doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText(); - } - - return Text()+itemObtained+doorOfTimeText; -} - -//insert the required number into the hint and set the singular/plural form -static Text BuildCountReq(const RandomizerHintTextKey req, const Rando::Option& count) { - Text requirement = ::Hint(req).GetTextCopy(); - if (count.Value() == 1) { - requirement.SetForm(SINGULAR); - } else { - requirement.SetForm(PLURAL); - } - requirement.Replace("%d", std::to_string(count.Value())); - return requirement; -} - -static Text BuildBridgeReqsText() { - auto ctx = Rando::Context::GetInstance(); - Text bridgeText; - - if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN)) { - bridgeText = ::Hint(RHT_BRIDGE_OPEN_HINT).GetText(); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA)) { - bridgeText = ::Hint(RHT_BRIDGE_VANILLA_HINT).GetText(); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { - bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT)); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT)); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT)); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT)); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT)); - - } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) { - bridgeText = ::Hint(RHT_BRIDGE_GREG_HINT).GetText(); - } - - return Text()+"$l"+bridgeText+"^"; -} - -static Text BuildGanonBossKeyText() { - auto ctx = Rando::Context::GetInstance(); - Text ganonBossKeyText; - - if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_START_WITH_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_VANILLA_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_VANILLA)) { - ganonBossKeyText = ::Hint(RHT_LACS_VANILLA_HINT).GetText(); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, ctx->GetOption(RSK_LACS_STONE_COUNT)); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, ctx->GetOption(RSK_LACS_MEDALLION_COUNT)); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, ctx->GetOption(RSK_LACS_REWARD_COUNT)); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, ctx->GetOption(RSK_LACS_DUNGEON_COUNT)); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, ctx->GetOption(RSK_LACS_TOKEN_COUNT)); - - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { - ganonBossKeyText = ::Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText(); - } - - return Text()+"$b"+ganonBossKeyText+"^"; -} - -void CreateAltarText() { - auto ctx = Rando::Context::GetInstance(); - - //Child Altar Text - if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { - childAltarText = ::Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ - //Spiritual Stones - // TODO: Starting Inventory Dungeon Rewards - (/*StartingKokiriEmerald.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_KOKIRI_EMERALD, RG_KOKIRI_EMERALD)) + - (/*StartingGoronRuby.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_GORON_RUBY, RG_GORON_RUBY)) + - (/*StartingZoraSapphire.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_ZORA_SAPPHIRE, RG_ZORA_SAPPHIRE)) + - //How to open Door of Time, the event trigger is necessary to read the altar multiple times - BuildDoorOfTimeText(); - } else { - childAltarText = BuildDoorOfTimeText(); - } - ctx->AddHint(RH_ALTAR_CHILD, AutoFormatHintText(childAltarText, { QM_GREEN, QM_RED, QM_BLUE }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); - - //CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE})); - - //Adult Altar Text - adultAltarText = ::Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^"; - if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { - adultAltarText = adultAltarText + - //Medallion Areas - (/*StartingLightMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_LIGHT, RG_LIGHT_MEDALLION)) + - (/*StartingForestMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_FOREST, RG_FOREST_MEDALLION)) + - (/*StartingFireMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_FIRE, RG_FIRE_MEDALLION)) + - (/*StartingWaterMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_WATER, RG_WATER_MEDALLION)) + - (/*StartingSpiritMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_SPIRIT, RG_SPIRIT_MEDALLION)) + - (/*StartingShadowMedallion.Value()*/false ? Text{ "##", "##", "##" } - : BuildDungeonRewardText(ITEM_MEDALLION_SHADOW, RG_SHADOW_MEDALLION)); - } - adultAltarText = adultAltarText + - //Bridge requirement - BuildBridgeReqsText()+ - - //Ganons Boss Key requirement - BuildGanonBossKeyText()+ - - //End - ::Hint(RHT_ADULT_ALTAR_TEXT_END).GetText(); - //CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED})); - ctx->AddHint(RH_ALTAR_ADULT, AutoFormatHintText(adultAltarText, { QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); -} - -void CreateMerchantsHints() { - auto ctx = Rando::Context::GetInstance(); - Text beanSalesmanItemText, medigoronItemText, grannyItemText, carpetSalesmanItemText, carpetSalesmanAfterItemText; - if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) { - RandomizerGet beanSalesmanItem = ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetPlacedRandomizerGet(); - beanSalesmanItemText = ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetPlacedItem().GetHint().GetText(); - if (beanSalesmanItem == RG_ICE_TRAP) { - beanSalesmanItemText = ctx->overrides[RC_ZR_MAGIC_BEAN_SALESMAN].GetTrickName(); - } - RandomizerGet medigoronItem = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedRandomizerGet(); - medigoronItemText = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedItem().GetHint().GetText(); - if (medigoronItem == RG_ICE_TRAP) { - medigoronItemText = ctx->overrides[RC_GC_MEDIGORON].GetTrickName(); - } - RandomizerGet grannyItem = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedRandomizerGet(); - grannyItemText = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText().Capitalize(); - if (grannyItem == RG_ICE_TRAP) { - grannyItemText = ctx->overrides[RC_KAK_GRANNYS_SHOP].GetTrickName(); - } - RandomizerGet carpetSalesmanItem = ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedRandomizerGet(); - carpetSalesmanItemText = - ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText(); - if (carpetSalesmanItem == RG_ICE_TRAP) { - carpetSalesmanItemText = ctx->overrides[RC_WASTELAND_BOMBCHU_SALESMAN].GetTrickName(); - } - carpetSalesmanAfterItemText = ::Hint(RHT_CARPET_SALESMAN_DIALOG_HINTED).GetText(); - } else { - medigoronItemText = grannyItemText = carpetSalesmanItemText = hintTable[RHT_HINT_MYSTERIOUS].GetTextCopy(); - carpetSalesmanAfterItemText = ::Hint(RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS).GetText(); - beanSalesmanItemText = Text{ "mysterious item", "objet mystérieux", "objeto misterioso", "mysteriöser gegenstand" }; - } - - Text medigoronText = - ::Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + ::Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText(); - Text grannyText = Text{"#"} + grannyItemText + "#" + ::Hint(RHT_GRANNY_DIALOG).GetText(); - Text carpetSalesmanTextOne = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText + - carpetSalesmanAfterItemText; - Text carpetSalesmanTextTwo = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FINAL).GetText(); - medigoronText = AutoFormatHintText(medigoronText, {QM_GREEN, QM_YELLOW, QM_GREEN }); - grannyText = AutoFormatHintText(grannyText, { QM_GREEN, QM_YELLOW, QM_GREEN }); - carpetSalesmanTextOne = AutoFormatHintText(carpetSalesmanTextOne, { QM_GREEN, QM_RED, QM_YELLOW, QM_GREEN }); - - if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) { - Text beanSalesmanText = ::Hint(RHT_BEAN_SALESMAN_FIRST).GetText() + beanSalesmanItemText + ::Hint(RHT_BEAN_SALESMAN_SECOND).GetText(); - ctx->AddHint(RH_BEAN_SALESMAN, AutoFormatHintText(beanSalesmanText, { QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN }), RC_ZR_MAGIC_BEAN_SALESMAN, HINT_TYPE_STATIC, "Static", RA_ZORAS_RIVER); - } - - ctx->AddHint(RH_MEDIGORON, medigoronText, RC_GC_MEDIGORON, HINT_TYPE_STATIC, "Static", RA_GORON_CITY); - ctx->AddHint(RH_GRANNYS_SHOP, grannyText, RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, "Static", RA_KAKARIKO_VILLAGE); - ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, carpetSalesmanTextOne, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, "Static", RA_HAUNTED_WASTELAND); - // Technically not a hint but this is probably the best place we have to store it for now. - ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST, carpetSalesmanTextTwo, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, "Static", RA_HAUNTED_WASTELAND); -} - -//RANDOTODO add Better Links Pocket and starting item handling once more starting items are added -void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, bool condition, bool yourpocket = false) { - auto ctx = Rando::Context::GetInstance(); - if(condition){ - RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) { - return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item; - })[0]; - - if (IsReachableWithout(hints,location,true)){ - ctx->GetItemLocation(location)->SetAsHinted(); - } - - RandomizerArea area = ctx->GetItemLocation(location)->GetArea(); - ctx->AddHint(hintKey, AutoFormatHintText(::Hint(text1).GetText() + ::Hint(area).GetText() + ::Hint(text2).GetText()), - location, HINT_TYPE_STATIC, "Static", area); - } -} - void CreateWarpSongTexts() { auto ctx = Rando::Context::GetInstance(); - - auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); - for (auto entrance : warpSongEntrances) { - auto destination = entrance->GetConnectedRegion()->GetArea(); - Text resolvedHint = ::Hint(destination).GetText(); - // If no Hint Area, use Region text - if (destination == RA_NONE) { - resolvedHint = Text{"","",""} + entrance->GetConnectedRegion()->regionName; + if (ctx->GetOption(RSK_WARP_SONG_HINTS)){ + auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); + for (auto entrance : warpSongEntrances) { + auto destination = entrance->GetConnectedRegion()->GetArea();//KNOWN ISSUE: says links pocket sometimes, putting off as this will need rewriting when entrance hits are added anyway + switch (entrance->GetIndex()) { + case 0x0600: // minuet RANDOTODO make into entrance hints when they are added + ctx->AddHint(RH_MINUET_WARP_LOC, Hint(RH_MINUET_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + case 0x04F6: // bolero + ctx->AddHint(RH_BOLERO_WARP_LOC, Hint(RH_BOLERO_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + case 0x0604: // serenade + ctx->AddHint(RH_SERENADE_WARP_LOC, Hint(RH_SERENADE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + case 0x01F1: // requiem + ctx->AddHint(RH_REQUIEM_WARP_LOC, Hint(RH_REQUIEM_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + case 0x0568: // nocturne + ctx->AddHint(RH_NOCTURNE_WARP_LOC, Hint(RH_NOCTURNE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + case 0x05F4: // prelude + ctx->AddHint(RH_PRELUDE_WARP_LOC, Hint(RH_PRELUDE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); + break; + default: + break; + } } - resolvedHint = ::Hint(RHT_WARP_TO).GetText() + resolvedHint + ::Hint(RHT_WARP_CHOICE).GetText(); - RandomizerHintKey hintKey = RH_NONE; - switch (entrance->GetIndex()) { - case 0x0600: // minuet - hintKey = RH_MINUET_WARP_LOC; - break; - case 0x04F6: // bolero - hintKey = RH_BOLERO_WARP_LOC; - break; - case 0x0604: // serenade - hintKey = RH_SERENADE_WARP_LOC; - break; - case 0x01F1: // requiem - hintKey = RH_REQUIEM_WARP_LOC; - break; - case 0x0568: // nocturne - hintKey = RH_NOCTURNE_WARP_LOC; - break; - case 0x05F4: // prelude - hintKey = RH_PRELUDE_WARP_LOC; - break; - default: - break; - } - ctx->AddHint(hintKey, AutoFormatHintText(resolvedHint, { QM_RED, QM_GREEN }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination); } } @@ -973,8 +554,7 @@ static void DistributeHints(std::vector& selected, size_t stoneCount, s selected[distribution] += 1; stoneCount -= distTable[distribution].copies; break; - } - else { + } else { totalWeight -= distTable[distribution].weight; distTable[distribution].weight = 0; break; @@ -1002,10 +582,7 @@ uint8_t PlaceHints(std::vector& selectedHints, std::vector hintTypePool = FilterHintability(ctx->allLocations, distribution.filter); for (uint8_t numHint = 0; numHint < selectedHints[curSlot]; numHint++){ - SPDLOG_DEBUG("Attempting to make hint of type: "); - SPDLOG_DEBUG(hintTypeNames[static_cast(distribution.type)]); - SPDLOG_DEBUG("\n"); - + SPDLOG_DEBUG("Attempting to make hint of type: " + StaticData::hintTypeNames[distribution.type].GetEnglish(MF_CLEAN) + "\n"); RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK; hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name); @@ -1035,40 +612,44 @@ void CreateStoneHints() { const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Value()]; std::vector distTable = hintSetting.distTable; - // Apply Static hint exclusions with no in-game requirements - for (int c = 0; c < staticHintLocations.size(); c++){ - if(ctx->GetOption(staticHintLocations[c].second)){ - ctx->GetItemLocation(staticHintLocations[c].first)->SetAsHinted(); - } + // Apply impa's song exclusions when zelda is skipped + if(ctx->GetOption(RSK_SKIP_CHILD_ZELDA)){ + ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetHintAccesible(); } // Add 'always' location hints + std::vector alwaysHintLocations = {}; if (hintSetting.alwaysCopies > 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(ctx->allLocations, [ctx](const RandomizerCheck loc) { - return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) || - // If we have Rainbow Bridge set to Greg, add a hint for where Greg is - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && - ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) && - ctx->GetItemLocation(loc)->IsHintable() && - !(ctx->GetOption(RSK_GREG_HINT) && (IsReachableWithout({RC_GREG_HINT}, loc, true))); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)){ + // If we have Rainbow Bridge set to Greg and the greg hint isn't useful, add a hint for where Greg is + // Do we really need this with the greg hint? + auto gregLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { + return ( + (ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) && + ctx->GetItemLocation(loc)->IsHintable() && + !(ctx->GetOption(RSK_GREG_HINT) && (IsReachableWithout({RC_GREG_HINT}, loc, true))); }); - - for (auto& hint : conditionalAlwaysHints) { - RandomizerCheck loc = hint.first; - if (hint.second() && ctx->GetItemLocation(loc)->IsHintable()) { - alwaysHintLocations.push_back(loc); - } + if (gregLocations.size() > 0){ + alwaysHintLocations.push_back(gregLocations[0]); } + } + + for (auto& hint : conditionalAlwaysHints) { + RandomizerCheck loc = hint.first; + if (hint.second() && ctx->GetItemLocation(loc)->IsHintable()) { + alwaysHintLocations.push_back(loc); + } + } for (RandomizerCheck location : alwaysHintLocations) { - CreateHint(location, hintSetting.alwaysCopies, HINT_TYPE_ITEM_LOCATION, "Always"); + CreateHint(location, hintSetting.alwaysCopies, HINT_TYPE_ITEM, "Always"); } } //Add 'trial' location hints - CreateTrialHints(hintSetting.trialCopies); + if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP)) { + CreateTrialHints(hintSetting.trialCopies); + } size_t totalStones = GetEmptyGossipStones().size(); std::vector selectedHints = {}; @@ -1077,7 +658,7 @@ void CreateStoneHints() { } selectedHints.push_back(0); DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight); - + while(totalStones != 0){ totalStones = PlaceHints(selectedHints, distTable); while (totalStones != 0){ @@ -1092,34 +673,114 @@ void CreateStoneHints() { GetAccessibleLocations({}); } -void CreateFrogsHint() { - const auto ctx = Rando::Context::GetInstance(); - Rando::ItemLocation* itemLoc = ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME); - Text itemText = itemLoc->GetPlacedItem().GetHint().GetText(); - if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) { - itemText = ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].GetTrickName(); +std::vector FindItemsAndMarkHinted(std::vector items, std::vector hintChecks){ + std::vector locations = {}; + auto ctx = Rando::Context::GetInstance(); + for (uint8_t c = 0; c < items.size(); c++){ + std::vector found = FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) { + return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];}); + if (found.size() > 0){ + locations.push_back(found[0]); + } + //RANDOTODO make the called functions of this always return true if empty hintChecks are provided + if (hintChecks.size() == 0 || (!ctx->GetItemLocation(found[0])->IsAHintAccessible() && IsReachableWithout(hintChecks,found[0],true))){ + ctx->GetItemLocation(found[0])->SetHintAccesible(); + } + } + return locations; +} + +void CreateChildAltarHint() { + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()){ + std::vector stoneLocs = {}; + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + //force marking the rewards as hinted if they are at the end of dungeons as they can be inffered + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ + stoneLocs = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {}); + } else { + stoneLocs = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {RC_ALTAR_HINT_CHILD}); + } + } + ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs)); + } +} + +void CreateAdultAltarHint() { + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()){ + std::vector medallionLocs = {}; + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + //force marking the rewards as hinted if they are at the end of dungeons as they can be inffered + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ + medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, + {}); + } else { + medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, + {RC_ALTAR_HINT_ADULT}); + } + } + ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs)); + } +} + +void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){ + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetHint(hint)->IsEnabled()){ + Option option = ctx->GetOption(staticData.setting); + if ((std::holds_alternative(staticData.condition) && option.Is(std::get(staticData.condition))) || + (std::holds_alternative(staticData.condition) && option.Is(std::get(staticData.condition)))){ + std::vector locations = {}; + if (staticData.targetItems.size() > 0){ + locations = FindItemsAndMarkHinted(staticData.targetItems, staticData.hintChecks); + } + //hintKeys are defaulted to in the hint object and do not need to be specified + ctx->AddHint(hint, Hint(hint, staticData.type, {}, locations, {}, {}, staticData.yourPocket, staticData.num)); + } + } +} + +void CreateStaticItemHint(RandomizerHint hintKey, std::vector hintTextKeys, + std::vector items, std::vector hintChecks, bool yourPocket = false) { + auto ctx = Rando::Context::GetInstance(); + std::vector locations = FindItemsAndMarkHinted(items, hintChecks); + ctx->AddHint(hintKey, Hint(hintKey, HINT_TYPE_AREA, hintTextKeys, locations, {}, {}, yourPocket)); +} + +void CreateGanondorfJoke(){ + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetHint(RH_GANONDORF_JOKE)->IsEnabled()){ + ctx->AddHint(RH_GANONDORF_JOKE, Hint(RH_GANONDORF_JOKE, HINT_TYPE_HINT_KEY, {GetRandomGanonJoke()})); + } +} + +void CreateGanondorfHint(){ + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_GANONDORF_HINT) && !ctx->GetHint(RH_GANONDORF_HINT)->IsEnabled()){ + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { + CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY, RHT_GANONDORF_HINT_MS_ONLY, RHT_GANONDORF_HINT_LA_AND_MS}, + {RG_LIGHT_ARROWS, RG_MASTER_SWORD}, {RC_GANONDORF_HINT}, true); + } else { + CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY}, {RG_LIGHT_ARROWS}, {RC_GANONDORF_HINT}, true); + } + } +} + +void CreateStaticHints(){ + CreateChildAltarHint(); + CreateAdultAltarHint(); + CreateGanondorfJoke(); + CreateGanondorfHint(); + for (auto[hint, staticData] : StaticData::staticHintInfoMap){ + CreateStaticHintFromData(hint, staticData); } - Text hintText = ::Hint(RHT_FROGS_HINT01).GetText() + itemText + ::Hint(RHT_FROGS_HINT02).GetText(); - RandomizerArea area = itemLoc->GetArea(); - itemLoc->SetAsHinted(); - ctx->AddHint(RH_FROGS, AutoFormatHintText(hintText, { QM_GREEN }), RC_ZR_FROGS_OCARINA_GAME, HINT_TYPE_STATIC, "Static", area); } void CreateAllHints(){ auto ctx = Rando::Context::GetInstance(); - CreateGanonAndSheikText(); - CreateAltarText(); - CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT)); - CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, (bool)ctx->GetOption(RSK_GREG_HINT)); - CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, (bool)ctx->GetOption(RSK_SARIA_HINT)); - CreateSpecialItemHint(RG_FISHING_POLE, RH_FISHING_POLE, {RC_FISHING_POLE_HINT}, RHT_FISHING_POLE_HINT01, RHT_FISHING_POLE_HINT02, (bool)ctx->GetOption(RSK_FISHING_POLE_HINT)); - if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) { - CreateMerchantsHints(); - } - if (ctx->GetOption(RSK_FROGS_HINT)) { - CreateFrogsHint(); - } + CreateStaticHints(); + if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) { SPDLOG_INFO("Creating Hints..."); CreateStoneHints(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index ed23c1e9a..d111c78ca 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -1,12 +1,15 @@ #pragma once -#include #include #include +#include #include "text.hpp" #include "random.hpp" #include +#include "../randomizerTypes.h" +#include "../../custom-message/CustomMessageManager.h" + struct HintDistributionSetting { std::string name; HintType type; @@ -16,21 +19,8 @@ struct HintDistributionSetting { std::function filter; uint8_t dungeonLimit; - HintDistributionSetting(std::string _name, - HintType _type, - uint32_t _weight, - uint8_t _fixed, - uint8_t _copies, - std::function _filter, - uint8_t _dungeonLimit = 40){ - name = _name; - type = _type; - weight = _weight; - fixed = _fixed; - copies = _copies; - filter = _filter; - dungeonLimit = _dungeonLimit; - } + HintDistributionSetting(std::string _name, HintType _type, uint32_t _weight, uint8_t _fixed, uint8_t _copies, + std::function _filter, uint8_t _dungeonLimit = 40); }; struct HintSetting { @@ -40,185 +30,45 @@ struct HintSetting { std::vector distTable; }; -enum class HintCategory { - Item, - Always, - Sometimes, - Exclude, - Entrance, - Region, - Junk, - DungeonName, - Boss, - Bridge, - GanonsBossKey, - LACS, - Altar, - Validation, - OtherHint, - MasterSword, - GanonLine, - SheikLine, - MerchantsDialogs, -}; - class HintText { public: HintText() = default; - HintText(std::vector obscureText_, std::vector ambiguousText_, Text clearText_, HintCategory type_) - : obscureText(std::move(obscureText_)), - ambiguousText(std::move(ambiguousText_)), - clearText(std::move(clearText_)), - type(type_) { - } - - static auto Item(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Item}; - } - - static auto Always(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Always}; - } - - static auto Sometimes(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Sometimes}; - } - - static auto Exclude(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Exclude}; - } - - static auto Entrance(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Entrance}; - } - - static auto Region(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Region}; - } - - static auto Junk(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Junk}; - } - - static auto DungeonName(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::DungeonName}; - } - - static auto Boss(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Boss}; - } - - static auto Bridge(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Bridge}; - } - - static auto GanonsBossKey(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonsBossKey}; - } - - static auto LACS(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LACS}; - } - - static auto Altar(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Altar}; - } - - static auto Validation(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Validation}; - } - - static auto OtherHint(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::OtherHint}; - } - - static auto MasterSword(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::MasterSword}; - } - - static auto GanonLine(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonLine}; - } - - static auto SheikLine(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { - return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::SheikLine}; - } - - static auto MerchantsDialogs(std::vector&& obscureText, std::vector&& 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; - - const Text GetTextCopy() const; - - 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); - } + HintText(CustomMessage clearText_, std::vector ambiguousText_ = {}, std::vector obscureText_ = {}); + const CustomMessage& GetClear() const; + const CustomMessage& GetObscure() const; + const CustomMessage& GetObscure(uint8_t selection) const; + const CustomMessage& GetAmbiguous() const; + const CustomMessage& GetAmbiguous(uint8_t selection) const; + uint8_t GetAmbiguousSize() const; + uint8_t GetObscureSize() const; + const CustomMessage& GetHintMessage(uint8_t selection = 0) const; + const CustomMessage GetMessageCopy() const; + bool operator==(const HintText& right) const; + bool operator!=(const HintText& right) const; private: - std::vector obscureText = {}; - std::vector ambiguousText = {}; - Text clearText; - HintCategory type; + CustomMessage clearText; + std::vector ambiguousText = {}; + std::vector obscureText = {}; }; -using ConditionalAlwaysHint = std::pair>; +struct StaticHintInfo{ + HintType type; + std::vector hintKeys; + RandomizerSettingKey setting; + std::variant condition; + std::vector targetChecks; + std::vector targetItems; + std::vector hintChecks; + bool yourPocket; + int num; -typedef enum { - DUNGEON_NEITHER, - DUNGEON_BARREN, - DUNGEON_WOTH, -} DungeonHintInfo; - -//10 dungeons as GTG and GC are excluded -extern std::array dungeonInfoData; - -extern std::array conditionalAlwaysHints; + StaticHintInfo() = default; + StaticHintInfo(HintType _type, std::vector _hintKeys, RandomizerSettingKey _setting, std::variant _condition, + std::vector _targetChecks, std::vector _targetItems = {}, + std::vector _hintChecks = {}, bool _yourPocket = false, int _num = 0); +}; extern void CreateAllHints(); extern void CreateWarpSongTexts(); - -void SetGanonText(Text text); - -std::string GetMasterSwordHintLoc(); -std::string GetLightArrowHintLoc(); - +void CreateStaticHints(); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 09fc5209e..82b3817bf 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -4,7 +4,6 @@ #include #include -#include "hint_list.hpp" #include "fill.hpp" #include "../randomizerTypes.h" #include "../context.h" diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index 874cc76c1..dacd8127e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -38,10 +38,10 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairyWithoutSuns;}}), }, { //Locations - LocationAccess(RC_TOT_LEFT_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_TOT_LEFTMOST_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_TOT_LEFT_CENTER_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_TOT_RIGHT_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_TOT_RIGHTMOST_GOSSIP_STONE, {[]{return true;}}), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp index e91513b79..baa3cb0fc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp @@ -32,12 +32,12 @@ void AreaTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, {[]{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}}), - Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) && - (logic->FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) && - (logic->WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) && - (logic->ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) && - (logic->SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) && - (logic->LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}), + Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || randoCtx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) && + (logic->FireTrialClear || randoCtx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) && + (logic->WaterTrialClear || randoCtx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) && + (logic->ShadowTrialClear || randoCtx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) && + (logic->SpiritTrialClear || randoCtx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) && + (logic->LightTrialClear || randoCtx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}}), Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH);}}), }); @@ -134,12 +134,12 @@ void AreaTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL, {[]{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}}), - Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) && - (logic->FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) && - (logic->WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) && - (logic->ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) && - (logic->SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) && - (logic->LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}), + Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || randoCtx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) && + (logic->FireTrialClear || randoCtx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) && + (logic->WaterTrialClear || randoCtx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) && + (logic->ShadowTrialClear || randoCtx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) && + (logic->SpiritTrialClear || randoCtx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) && + (logic->LightTrialClear || randoCtx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}}), Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}}), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp index 777154bab..8c3d6a5b1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp @@ -34,7 +34,7 @@ void AreaTable_Init_HyruleField() { //Locations LocationAccess(RC_HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}), LocationAccess(RC_HF_SOUTHEAST_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_HF_SOUTHEAST_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), LocationAccess(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), }, { @@ -77,7 +77,7 @@ void AreaTable_Init_HyruleField() { //Locations LocationAccess(RC_HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}), LocationAccess(RC_HF_NEAR_MARKET_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_HF_NEAR_MARKET_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), LocationAccess(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp index 809a439f8..b33cc9381 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp @@ -281,7 +281,7 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairyWithoutSuns;}}), }, { //Locations - LocationAccess(RC_GY_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_GRAVEYARD_GOSSIP_STONE, {[]{return true;}}), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp index 6dc417727..c7214d6ca 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp @@ -98,7 +98,7 @@ void AreaTable_Init_LostWoods() { //Locations LocationAccess(RC_KF_STORMS_GROTTO_CHEST, {[]{return true;}}), LocationAccess(RC_KF_STORMS_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_KF_STORMS_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), LocationAccess(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), }, { @@ -168,7 +168,7 @@ void AreaTable_Init_LostWoods() { //Locations LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}), LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}), LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index c20667c47..dddad29a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -158,8 +158,8 @@ void AreaTable_Init_ZorasDomain() { LocationAccess(RC_ZF_GS_TREE, {[]{return logic->IsChild;}}), LocationAccess(RC_ZF_GS_ABOVE_THE_LOG, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), LocationAccess(RC_ZF_GS_HIDDEN_CAVE, {[]{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBlastOrSmash && logic->HookshotOrBoomerang && logic->IsAdult && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_FAIRY_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_JABU_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_ZF_FAIRY_GOSSIP_STONE, {[]{return true;}}), + LocationAccess(RC_ZF_JABU_GOSSIP_STONE, {[]{return true;}}), }, { //Exits Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 349995177..e3c757ba5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -1,5 +1,4 @@ #include "menu.hpp" -#include "hint_list.hpp" #include "../static_data.h" #include "../item_location.h" #include "location_access.hpp" @@ -12,7 +11,6 @@ void RandoMain::GenerateRando(std::set excludedLocations, std::set enabledTricks, std::string seedString) { - HintTable_Init(); // std::string settingsFileName = "./randomizer/latest_settings.json"; // CVarSetString("gLoadedPreset", settingsFileName.c_str()); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 3fdf56b60..1835dfe03 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -38,7 +38,6 @@ using namespace Rando; json jsonData; std::map hintedLocations; -extern std::array hintTypeNames; extern std::array hintCategoryNames; extern Area* GetHintRegion(uint32_t); @@ -499,16 +498,7 @@ static void WriteRequiredTrials() { auto ctx = Rando::Context::GetInstance(); for (const auto& trial : ctx->GetTrials()->GetTrialList()) { if (trial->IsRequired()) { - std::string trialName; - switch (gSaveContext.language) { - case LANGUAGE_FRA: - trialName = trial->GetName().GetFrench(); - break; - case LANGUAGE_ENG: - default: - trialName = trial->GetName().GetEnglish(); - break; - } + std::string trialName = trial->GetName().GetForCurrentLanguage(MF_CLEAN); jsonData["requiredTrials"].push_back(RemoveLineBreaks(trialName)); } } @@ -553,117 +543,13 @@ Rando::ItemLocation* GetItemLocation(RandomizerGet item) { })[0]); } -// Writes the hints to the spoiler log, if they are enabled. -static void WriteHints() { - auto ctx = Rando::Context::GetInstance(); - - uint8_t language = ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex(); - - if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) { - jsonData["warpMinuetText"] = ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetForLanguage(language); - jsonData["warpBoleroText"] = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetForLanguage(language); - jsonData["warpSerenadeText"] = ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetForLanguage(language); - jsonData["warpRequiemText"] = ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetForLanguage(language); - jsonData["warpNocturneText"] = ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetForLanguage(language); - jsonData["warpPreludeText"] = ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetForLanguage(language); - } - jsonData["childAltar"]["hintText"] = ctx->GetHint(RH_ALTAR_CHILD)->GetText().GetForLanguage(language); - jsonData["adultAltar"]["hintText"] = ctx->GetHint(RH_ALTAR_ADULT)->GetText().GetForLanguage(language); - - Rando::ItemLocation* emeraldLoc = GetItemLocation(RG_KOKIRI_EMERALD); - Rando::ItemLocation* rubyLoc = GetItemLocation(RG_GORON_RUBY); - Rando::ItemLocation* sapphireLoc = GetItemLocation(RG_ZORA_SAPPHIRE); - std::string emeraldArea; - std::string erubyArea; - std::string sapphireArea; - - jsonData["childAltar"]["rewards"]["emeraldLoc"] = Rando::StaticData::GetLocation(emeraldLoc->GetRandomizerCheck())->GetName(); - jsonData["childAltar"]["rewards"]["rubyLoc"] = Rando::StaticData::GetLocation(rubyLoc->GetRandomizerCheck())->GetName(); - jsonData["childAltar"]["rewards"]["sapphireLoc"] = - Rando::StaticData::GetLocation(sapphireLoc->GetRandomizerCheck())->GetName(); - - Rando::ItemLocation* forestMedallionLoc = GetItemLocation(RG_FOREST_MEDALLION); - Rando::ItemLocation* fireMedallionLoc = GetItemLocation(RG_FIRE_MEDALLION); - Rando::ItemLocation* waterMedallionLoc = GetItemLocation(RG_WATER_MEDALLION); - Rando::ItemLocation* shadowMedallionLoc = GetItemLocation(RG_SHADOW_MEDALLION); - Rando::ItemLocation* spiritMedallionLoc = GetItemLocation(RG_SPIRIT_MEDALLION); - Rando::ItemLocation* lightMedallionLoc = GetItemLocation(RG_LIGHT_MEDALLION); - - jsonData["adultAltar"]["rewards"]["forestMedallionLoc"] = - Rando::StaticData::GetLocation(forestMedallionLoc->GetRandomizerCheck())->GetName(); - jsonData["adultAltar"]["rewards"]["fireMedallionLoc"] = - Rando::StaticData::GetLocation(fireMedallionLoc->GetRandomizerCheck())->GetName(); - jsonData["adultAltar"]["rewards"]["waterMedallionLoc"] = - Rando::StaticData::GetLocation(waterMedallionLoc->GetRandomizerCheck())->GetName(); - jsonData["adultAltar"]["rewards"]["shadowMedallionLoc"] = - Rando::StaticData::GetLocation(shadowMedallionLoc->GetRandomizerCheck())->GetName(); - jsonData["adultAltar"]["rewards"]["spiritMedallionLoc"] = - Rando::StaticData::GetLocation(spiritMedallionLoc->GetRandomizerCheck())->GetName(); - jsonData["adultAltar"]["rewards"]["lightMedallionLoc"] = - Rando::StaticData::GetLocation(lightMedallionLoc->GetRandomizerCheck())->GetName(); - - jsonData["ganonText"] = ctx->GetHint(RH_GANONDORF_NOHINT)->GetText().GetForLanguage(language); - if (ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){ - jsonData["ganonHintText"] = ctx->GetHint(RH_GANONDORF_HINT)->GetText().GetForLanguage(language); - jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc(); - jsonData["lightArrowArea"] = ::Hint(ctx->GetHint(RH_GANONDORF_HINT)->GetHintedArea()).GetText().GetEnglish(); - jsonData["masterSwordHintLoc"] = GetMasterSwordHintLoc(); - if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { - jsonData["sheikText"] = ctx->GetHint(RH_SHEIK_LIGHT_ARROWS)->GetText().GetForLanguage(language); - } - } - if (ctx->GetOption(RSK_DAMPES_DIARY_HINT)){ - jsonData["dampeText"] = ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetForLanguage(language); - jsonData["dampeHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_DAMPES_DIARY)->GetHintedLocation())->GetName(); - jsonData["dampeRegion"] = ::Hint(ctx->GetHint(RH_DAMPES_DIARY)->GetHintedArea()).GetText().GetEnglish(); - } - if (ctx->GetOption(RSK_GREG_HINT)){ - jsonData["gregText"] = ctx->GetHint(RH_GREG_RUPEE)->GetText().GetForLanguage(language); - jsonData["gregLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_GREG_RUPEE)->GetHintedLocation())->GetName(); - jsonData["gregRegion"] = ::Hint(ctx->GetHint(RH_GREG_RUPEE)->GetHintedArea()).GetText().GetEnglish(); - } - if (ctx->GetOption(RSK_SARIA_HINT)){ - jsonData["sariaText"] = ctx->GetHint(RH_SARIA)->GetText().GetForLanguage(language); - jsonData["sariaHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_SARIA)->GetHintedLocation())->GetName(); - jsonData["sariaRegion"] = ::Hint(ctx->GetHint(RH_SARIA)->GetHintedArea()).GetText().GetEnglish(); - } - if (ctx->GetOption(RSK_FISHING_POLE_HINT)) { - jsonData["fishingPoleText"] = ctx->GetHint(RH_FISHING_POLE)->GetText().GetForLanguage(language); - jsonData["fishingPoleHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_FISHING_POLE)->GetHintedLocation())->GetName(); - jsonData["fishingPoleRegion"] = ::Hint(ctx->GetHint(RH_FISHING_POLE)->GetHintedArea()).GetText().GetEnglish(); - } - - if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NONE)) { - return; - } - for (const RandomizerCheck key : Rando::StaticData::gossipStoneLocations) { //RANDOTODO should be merged with static hints, iterate over hint keys - Rando::Hint* hint = ctx->GetHint((RandomizerHintKey)(key - RC_COLOSSUS_GOSSIP_STONE + 1)); - Rando::ItemLocation* hintedLocation = ctx->GetItemLocation(hint->GetHintedLocation()); - std::string hintTextString = hint->GetText().GetForLanguage(language); - HintType hintType = hint->GetHintType(); - - std::string textStr = hintTextString; - std::string name = Rando::StaticData::GetLocation(key)->GetName(); - jsonData["hints"][name]["hint"] = textStr; - jsonData["hints"][name]["distribution"] = hint->GetDistribution(); - jsonData["hints"][name]["type"] = hintTypeNames[(int)hintType]; - if (hintType == HINT_TYPE_ITEM_LOCATION || hintType == HINT_TYPE_ITEM_AREA || hintType == HINT_TYPE_WOTH) { - jsonData["hints"][name]["item"] = hintedLocation->GetPlacedItemName().GetEnglish(); - jsonData["hints"][name]["location"] = Rando::StaticData::GetLocation(hintedLocation->GetRandomizerCheck())->GetName(); - } - if (hintType != HINT_TYPE_TRIAL && hintType != HINT_TYPE_JUNK) { - jsonData["hints"][name]["area"] = ::Hint(hint->GetHintedArea()).GetText().Capitalize().GetEnglish(); - } - } -} - static void WriteAllLocations() { auto ctx = Rando::Context::GetInstance(); for (const RandomizerCheck key : ctx->allLocations) { Rando::ItemLocation* location = ctx->GetItemLocation(key); std::string placedItemName; - switch (ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex()) { + switch (gSaveContext.language) { case 0: default: placedItemName = location->GetPlacedItemName().english; @@ -689,12 +575,12 @@ static void WriteAllLocations() { jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["price"] = location->GetPrice(); } - if (location->IsHintedAt()) { + if (location->IsAHintAccessible()) { hintedLocations.emplace(Rando::StaticData::GetLocation(key)->GetHintKey(), location); } if (location->GetPlacedRandomizerGet() == RG_ICE_TRAP) { - switch (ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex()) { + switch (gSaveContext.language) { case 0: default: jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["model"] = @@ -737,7 +623,7 @@ const char* SpoilerLog_Write() { WriteSettings(); WriteExcludedLocations(); WriteStartingInventory(); - WriteEnabledTricks(spoilerLog); + WriteEnabledTricks(spoilerLog); //RANDOTODO clean up spoilerLog refernces //if (Settings::Logic.Is(LOGIC_GLITCHED)) { // WriteEnabledGlitches(spoilerLog); //} @@ -748,7 +634,7 @@ const char* SpoilerLog_Write() { ctx->playthroughLocations.clear(); ctx->playthroughBeatable = false; - WriteHints(); + ctx->WriteHintJson(jsonData); WriteShuffledEntrances(); WriteAllLocations(); diff --git a/soh/soh/Enhancements/randomizer/3drando/text.hpp b/soh/soh/Enhancements/randomizer/3drando/text.hpp index 49e598f63..46c0196bb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/text.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/text.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "z64.h" +#include #define PLURAL 0 #define SINGULAR 1 @@ -54,11 +54,11 @@ public: const std::string& GetForLanguage(uint8_t language) const { switch (language) { - case LANGUAGE_ENG: + case 0: //LANGUAGE_ENG: changed to resolve #include loops return GetEnglish(); - case LANGUAGE_FRA: + case 2: //LANGUAGE_FRA: return GetFrench(); - case LANGUAGE_GER: + case 1: //LANGUAGE_GER: return GetGerman(); default: return GetEnglish(); @@ -97,6 +97,29 @@ public: } } + void Replace(std::string oldStr, Text newText) { + size_t position = english.find(oldStr); + while (position != std::string::npos) { + english.replace(position, oldStr.length(), newText.GetEnglish()); + position = english.find(oldStr); + } + position = french.find(oldStr); + while (position != std::string::npos) { + french.replace(position, oldStr.length(), newText.GetFrench()); + position = french.find(oldStr); + } + position = spanish.find(oldStr); + while (position != std::string::npos) { + spanish.replace(position, oldStr.length(), newText.GetSpanish()); + position = spanish.find(oldStr); + } + position = german.find(oldStr); + while (position != std::string::npos) { + german.replace(position, oldStr.length(), newText.GetGerman()); + position = german.find(oldStr); + } + } + // Convert first char to upper case Text Capitalize(void) const { Text cap = *this + ""; diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 3f5e09db3..35c856d60 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -5,11 +5,11 @@ #include "3drando/shops.hpp" #include "dungeon.h" #include "logic.h" -#include "trial.h" #include "entrance.h" #include "settings.h" #include "rando_hash.h" #include "fishsanity.h" +#include "3drando/hints.hpp" #include #include @@ -20,56 +20,6 @@ namespace Rando { std::weak_ptr Context::mContext; Context::Context() { - mSpoilerfileHintTypeNameToEnum = { - { "Static", HINT_TYPE_STATIC }, - { "Trial", HINT_TYPE_TRIAL }, - { "WotH", HINT_TYPE_WOTH }, - { "Barren", HINT_TYPE_BARREN }, - { "Entrance", HINT_TYPE_ENTRANCE }, - { "Item Area", HINT_TYPE_ITEM_AREA }, - { "Item Location", HINT_TYPE_ITEM_LOCATION }, - { "Junk", HINT_TYPE_JUNK }, - }; - - mSpoilerfileAreaNameToEnum = { - {"No Hint", RA_NONE}, - {"Link's Pocket", RA_LINKS_POCKET}, - {"Kokiri Forest", RA_KOKIRI_FOREST}, - {"The Lost Woods", RA_THE_LOST_WOODS}, - {"Sacred Forest Meadow", RA_SACRED_FOREST_MEADOW}, - {"Hyrule Field", RA_HYRULE_FIELD}, - {"Lake Hylia", RA_LAKE_HYLIA}, - {"Gerudo Valley", RA_GERUDO_VALLEY}, - {"Gerudo Fortress", RA_GERUDO_FORTRESS}, - {"Haunted Wasteland", RA_HAUNTED_WASTELAND}, - {"Desert Colossus", RA_DESERT_COLOSSUS}, - {"The Market", RA_THE_MARKET}, - {"Temple of Time", RA_TEMPLE_OF_TIME}, - {"Hyrule Castle", RA_HYRULE_CASTLE}, - {"Outside Ganon's Castle", RA_OUTSIDE_GANONS_CASTLE}, - {"Castle Grounds", RA_CASTLE_GROUNDS}, - {"Kakariko Village", RA_KAKARIKO_VILLAGE}, - {"the Graveyard", RA_THE_GRAVEYARD}, - {"Death Mountain Trail", RA_DEATH_MOUNTAIN_TRAIL}, - {"Goron City", RA_GORON_CITY}, - {"Death Mountain Crater", RA_DEATH_MOUNTAIN_CRATER}, - {"Zora's River", RA_ZORAS_RIVER}, - {"Zora's Domain", RA_ZORAS_DOMAIN}, - {"Zora's Fountain", RA_ZORAS_FOUNTAIN}, - {"Lon Lon Ranch", RA_LON_LON_RANCH}, - {"Deku Tree", RA_DEKU_TREE}, - {"Dodongo's Cavern", RA_DODONGOS_CAVERN}, - {"Jabu-Jabu's Belly", RA_JABU_JABUS_BELLY}, - {"Forest Temple", RA_FOREST_TEMPLE}, - {"Fire Temple", RA_FIRE_TEMPLE}, - {"Water Temple", RA_WATER_TEMPLE}, - {"Spirit Temple", RA_SPIRIT_TEMPLE}, - {"Shadow Temple", RA_SHADOW_TEMPLE}, - {"Bottom of the Well", RA_BOTTOM_OF_THE_WELL}, - {"Ice Cavern", RA_ICE_CAVERN}, - {"Gerudo training Grounds", RA_GERUDO_TRAINING_GROUND}, - {"Inside Ganon's Castle", RA_GANONS_CASTLE}, - }; for (int i = 0; i < RC_MAX; i++) { itemLocationTable[i] = ItemLocation(static_cast(i)); @@ -83,11 +33,15 @@ Context::Context() { } RandomizerArea Context::GetAreaFromString(std::string str) { - return mSpoilerfileAreaNameToEnum[str]; + return (RandomizerArea)StaticData::areaNameToEnum[str]; } void Context::InitStaticData() { - StaticData::InitItemTable(); + StaticData::HintTable_Init(); + StaticData::trialNameToEnum = StaticData::PopulateTranslationMap(StaticData::trialData); + StaticData::hintNameToEnum = StaticData::PopulateTranslationMap(StaticData::hintNames); + StaticData::hintTypeNameToEnum = StaticData::PopulateTranslationMap(StaticData::hintTypeNames); + StaticData::areaNameToEnum = StaticData::PopulateTranslationMap(StaticData::areaNames); StaticData::InitLocationTable(); } @@ -104,14 +58,12 @@ std::shared_ptr Context::GetInstance() { return mContext.lock(); } -Hint* Context::GetHint(const RandomizerHintKey hintKey) { +Hint* Context::GetHint(const RandomizerHint hintKey) { return &hintTable[hintKey]; } -void Context::AddHint(const RandomizerHintKey hintId, const Text& text, const RandomizerCheck hintedLocation, const HintType hintType, - std::string distributionName, RandomizerArea hintedArea) { - hintTable[hintId] = Hint(text, hintedLocation, hintType, distributionName, hintedArea); - GetItemLocation(hintedLocation)->AddHintedBy(hintId); +void Context::AddHint(const RandomizerHint hintId, const Hint hint) { + hintTable[hintId] = hint; //RANDOTODO this should probably be an rvalue } ItemLocation* Context::GetItemLocation(const RandomizerCheck locKey) { @@ -222,7 +174,7 @@ std::vector Context::GetLocations(const std::vector(i))->ResetVariables(); } } @@ -250,7 +202,7 @@ void Context::LocationReset() { GetItemLocation(il)->RemoveFromPool(); } - for (const RandomizerCheck il : StaticData::otherHintLocations) { + for (const RandomizerCheck il : StaticData::staticHintLocations) { GetItemLocation(il)->RemoveFromPool(); } } @@ -258,7 +210,9 @@ void Context::LocationReset() { void Context::HintReset() { for (const RandomizerCheck il : StaticData::gossipStoneLocations) { GetItemLocation(il)->ResetVariables(); - GetHint(static_cast(il - RC_COLOSSUS_GOSSIP_STONE + 1))->ResetVariables(); + } + for (Hint& hint : hintTable){ + hint.ResetVariables(); } } @@ -393,126 +347,52 @@ void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) { void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) { nlohmann::json locationsJson = spoilerFileJson["locations"]; for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) { - RandomizerCheck rc = StaticData::SpoilerfileCheckNameToEnum[it.key()]; + RandomizerCheck rc = StaticData::locationNameToEnum[it.key()]; if (it->is_structured()) { nlohmann::json itemJson = *it; for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) { if (itemit.key() == "item") { - itemLocationTable[rc].SetPlacedItem(StaticData::SpoilerfileItemNameToEnum[itemit.value().get()]); + itemLocationTable[rc].SetPlacedItem(StaticData::itemNameToEnum[itemit.value().get()]); } else if (itemit.key() == "price") { itemLocationTable[rc].SetCustomPrice(itemit.value().get()); } else if (itemit.key() == "model") { - overrides[rc] = ItemOverride(rc, StaticData::SpoilerfileItemNameToEnum[itemit.value().get()]); + overrides[rc] = ItemOverride(rc, StaticData::itemNameToEnum[itemit.value().get()]); } else if (itemit.key() == "trickName") { overrides[rc].SetTrickName(Text(itemit.value().get())); } } } else { - itemLocationTable[rc].SetPlacedItem(StaticData::SpoilerfileItemNameToEnum[it.value().get()]); + itemLocationTable[rc].SetPlacedItem(StaticData::itemNameToEnum[it.value().get()]); } } } +void Context::WriteHintJson(nlohmann::ordered_json& spoilerFileJson){ + for (Hint hint: hintTable){ + hint.logHint(spoilerFileJson); + } +} + +nlohmann::json getValueForMessage(std::unordered_map map, CustomMessage message){ + std::vector strings = message.GetAllMessages(); + for (uint8_t language = 0; language < LANGUAGE_MAX; language++){ + if (map.contains(strings[language])){ + return strings[language]; + } + } + return {}; +} + void Context::ParseHintJson(nlohmann::json spoilerFileJson) { - // Child Altar - std::string childAltarText = spoilerFileJson["childAltar"]["hintText"].get(); - AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE); - mEmeraldLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]]; - mRubyLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]]; - mSapphireLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]]; - - // Adult Altar - std::string adultAltarText = spoilerFileJson["adultAltar"]["hintText"].get(); - AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE); - mForestMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"].get()]; - mFireMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"].get()]; - mWaterMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"].get()]; - mShadowMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"].get()]; - mSpiritMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"].get()]; - mLightMedallionLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"].get()]; - - // Ganondorf and Sheik Light Arrow Hints - std::string ganonHintText = spoilerFileJson["ganonHintText"].get(); - RandomizerCheck lightArrowLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"].get()]; - std::string lightArrowRegion = spoilerFileJson["lightArrowArea"].get(); - AddHint(RH_GANONDORF_HINT, Text(ganonHintText), lightArrowLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[lightArrowRegion]); - if (spoilerFileJson.contains("sheikText")) { - std::string sheikText = spoilerFileJson["sheikText"].get(); - AddHint(RH_SHEIK_LIGHT_ARROWS, Text(sheikText), lightArrowLoc, HINT_TYPE_STATIC, lightArrowRegion); + for (auto hintData : spoilerFileJson["Gossip Stone Hints"].items()){ + RandomizerHint hint = (RandomizerHint)StaticData::hintNameToEnum[hintData.key()]; + AddHint(hint, Hint(hint, hintData.value())); } - std::string ganonText = spoilerFileJson["ganonText"].get(); - AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_JUNK, "Static", RA_GANONS_CASTLE); - - // Dampe Hookshot Hint - if (spoilerFileJson.contains("dampeText")) { - std::string dampeText = spoilerFileJson["dampeText"].get(); - std::string dampeRegion = spoilerFileJson["dampeRegion"].get(); - RandomizerCheck dampeHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"].get()]; - AddHint(RH_DAMPES_DIARY, Text(dampeText), dampeHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[dampeRegion]); - } - - // Greg Hint - if (spoilerFileJson.contains("gregText")) { - std::string gregText = spoilerFileJson["gregText"].get(); - std::string gregRegion = spoilerFileJson["gregRegion"].get(); - RandomizerCheck gregLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"].get()]; - AddHint(RH_GREG_RUPEE, Text(gregText), gregLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[gregRegion]); - } - - // Saria Magic Hint - if (spoilerFileJson.contains("sariaText")) { - std::string sariaText = spoilerFileJson["sariaText"].get(); - std::string sariaRegion = spoilerFileJson["sariaRegion"].get(); - RandomizerCheck sariaHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"].get()]; - AddHint(RH_SARIA, Text(sariaText), sariaHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[sariaRegion]); - } - - // Fishing Pole Hint - if(spoilerFileJson.contains("fishingPoleText")) { - std::string fishingPoleText = spoilerFileJson["fishingPoleText"].get(); - std::string fishingPoleRegion = spoilerFileJson["fishingPoleRegion"].get(); - RandomizerCheck fishingPoleHintLoc = StaticData::SpoilerfileCheckNameToEnum[spoilerFileJson["fishingPoleHintLoc"].get()]; - AddHint(RH_FISHING_POLE, Text(fishingPoleText), fishingPoleHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[fishingPoleRegion]); - } - - // Warp Songs - if (spoilerFileJson.contains("warpMinuetText")) { - std::string warpMinuetText = spoilerFileJson["warpMinuetText"].get(); //RANDOTODO fall back for if location is used - AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpMinuetText]); - } - if (spoilerFileJson.contains("warpBoleroText")) { - std::string warpBoleroText = spoilerFileJson["warpBoleroText"].get(); - AddHint(RH_BOLERO_WARP_LOC, Text(warpBoleroText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpBoleroText]); - } - if (spoilerFileJson.contains("warpSerenadeText")) { - std::string warpSerenadeText = spoilerFileJson["warpSerenadeText"].get(); - AddHint(RH_SERENADE_WARP_LOC, Text(warpSerenadeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpSerenadeText]); - } - if (spoilerFileJson.contains("warpRequiemText")) { - std::string warpRequiemText = spoilerFileJson["warpRequiemText"].get(); - AddHint(RH_REQUIEM_WARP_LOC, Text(warpRequiemText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpRequiemText]); - } - if (spoilerFileJson.contains("warpNocturneText")) { - std::string warpNocturneText = spoilerFileJson["warpNocturneText"].get(); - AddHint(RH_NOCTURNE_WARP_LOC, Text(warpNocturneText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpNocturneText]); - } - if (spoilerFileJson.contains("warpPreludeText")) { - std::string warpPreludeText = spoilerFileJson["warpPreludeText"].get(); - AddHint(RH_PRELUDE_WARP_LOC, Text(warpPreludeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpPreludeText]); - } - - // Gossip Stones - nlohmann::json hintsJson = spoilerFileJson["hints"]; - for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) { - RandomizerCheck gossipStoneLoc = StaticData::SpoilerfileCheckNameToEnum[it.key()]; - nlohmann::json hintInfo = it.value(); - std::string hintText = hintInfo["hint"].get(); - HintType hintType = mSpoilerfileHintTypeNameToEnum[hintInfo["type"].get()]; - RandomizerCheck hintedLocation = hintInfo.contains("location") ? StaticData::SpoilerfileCheckNameToEnum[hintInfo["location"]] : RC_UNKNOWN_CHECK; - RandomizerArea hintedArea = hintInfo.contains("area") ? mSpoilerfileAreaNameToEnum[hintInfo["area"].get()] : RA_NONE; - std::string distribution = hintInfo["distribution"].get(); - AddHint(static_cast(gossipStoneLoc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), hintedLocation, hintType, distribution, hintedArea); + for (auto hintData : spoilerFileJson["Static Hints"].items()){ + RandomizerHint hint = (RandomizerHint)StaticData::hintNameToEnum[hintData.key()]; + AddHint(hint, Hint(hint, hintData.value())); } + CreateStaticHints(); } std::shared_ptr Context::GetSettings() { @@ -554,6 +434,10 @@ TrialInfo* Context::GetTrial(size_t key) const { return mTrials->GetTrial(static_cast(key)); } +TrialInfo* Context::GetTrial(TrialKey key) const { + return mTrials->GetTrial(key); +} + Sprite* Context::GetSeedTexture(const uint8_t index) { return &gSeedTextures[index]; } diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h index 06dd44628..2deb4e365 100644 --- a/soh/soh/Enhancements/randomizer/context.h +++ b/soh/soh/Enhancements/randomizer/context.h @@ -7,6 +7,7 @@ #include "3drando/text.hpp" #include "hint.h" #include "fishsanity.h" +#include "trial.h" #include #include @@ -36,9 +37,8 @@ class Context { static std::shared_ptr CreateInstance(); static std::shared_ptr GetInstance(); void InitStaticData(); - Hint* GetHint(RandomizerHintKey hintKey); - void AddHint(RandomizerHintKey hintId, const Text& text, RandomizerCheck hintedLocation, HintType hintType, std::string distributionName, - RandomizerArea hintedArea = RA_NONE); + Hint* GetHint(RandomizerHint hintKey); + void AddHint(const RandomizerHint hintId, const Hint hint); ItemLocation* GetItemLocation(RandomizerCheck locKey); ItemLocation* GetItemLocation(size_t locKey); ItemOverride& GetItemOverride(RandomizerCheck locKey); @@ -73,6 +73,7 @@ class Context { void ResetLogic(); std::shared_ptr GetTrials(); TrialInfo* GetTrial(size_t key) const; + TrialInfo* GetTrial(TrialKey key) const; static Sprite* GetSeedTexture(uint8_t index); Option& GetOption(RandomizerSettingKey key) const; TrickOption& GetTrickOption(RandomizerTrick key) const; @@ -80,6 +81,7 @@ class Context { void ParseSpoiler(const char* spoilerFileName, bool plandoMode); void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson); void ParseItemLocationsJson(nlohmann::json spoilerFileJson); + void WriteHintJson(nlohmann::ordered_json& spoilerFileJson); void ParseHintJson(nlohmann::json spoilerFileJson); std::map overrides = {}; std::vector> playthroughLocations = {}; @@ -93,18 +95,7 @@ class Context { private: static std::weak_ptr mContext; - std::unordered_map mSpoilerfileHintTypeNameToEnum; - std::unordered_map mSpoilerfileAreaNameToEnum; std::array hintTable = {}; - RandomizerCheck mEmeraldLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mRubyLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mSapphireLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mForestMedallionLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mFireMedallionLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mWaterMedallionLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mShadowMedallionLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mSpiritMedallionLoc = RC_UNKNOWN_CHECK; - RandomizerCheck mLightMedallionLoc = RC_UNKNOWN_CHECK; std::array itemLocationTable = {}; std::shared_ptr mSettings; std::shared_ptr mEntranceShuffler; diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index ff9dfdf81..7d62d29c7 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -1,56 +1,729 @@ #include "hint.h" +#include "map" +#include "string" +#include "context.h" +#include +#include "static_data.h" namespace Rando { -Hint::Hint() : text(std::move(Text())) {} -Hint::Hint(Text text_): text(std::move(text_)) {} -Hint::Hint(Text text_, RandomizerCheck hintedLocation_, HintType hintType_, std::string distributionName_, RandomizerArea hintedArea_) - : text(std::move(text_)), hintedLocation(hintedLocation_), hintType(hintType_), - hintedArea(hintedArea_), distribution(std::move(distributionName_)) { +Hint::Hint(){} + +Hint::Hint(RandomizerHint ownKey_, + HintType hintType_, + std::string distribution_, + std::vector hintKeys_, + std::vector locations_, + std::vector areas_, + std::vector trials_) + : ownKey(ownKey_), hintType(hintType_), distribution(std::move(distribution_)), hintKeys(hintKeys_), locations(locations_), areas(areas_), trials(trials_) { + FillGapsInData(); + SetLocationsAsHinted(); + NamesChosen(); + enabled = true; } -const Text& Hint::GetText() const { - return text; +Hint::Hint(RandomizerHint ownKey_, + HintType hintType_, + std::vector hintKeys_, + std::vector locations_, + std::vector areas_, + std::vector trials_, + bool yourPocket_, + int num_) + : ownKey(ownKey_), hintType(hintType_), hintKeys(hintKeys_), locations(locations_), areas(areas_), trials(trials_), yourPocket(yourPocket_), num(num_) { + FillGapsInData(); + SetLocationsAsHinted(); + NamesChosen(); + enabled = true; } -void Hint::SetHintedLocation(RandomizerCheck location) { - hintedLocation = location; +Hint::Hint(RandomizerHint ownKey_, std::vector messages_) +: ownKey(ownKey_), messages(messages_){ + hintType = HINT_TYPE_MESSAGE; + enabled = true; } -RandomizerCheck Hint::GetHintedLocation() { - return hintedLocation; +Hint::Hint(RandomizerHint ownKey_, nlohmann::json json_){ + ownKey = ownKey_; + if (json_.contains("enabled") && !json_["enabled"].get()){ + return; + } + enabled = true; + + if (json_.contains("type")){ + hintType = (HintType)StaticData::hintTypeNameToEnum[json_["type"].get()]; + } + + if (hintType == HINT_TYPE_MESSAGE){ + if (json_.contains("messages")){ + for (auto message: json_["messages"]){ + messages.push_back(CustomMessage(message.get())); + } + } else if (json_.contains("message")){ + messages.push_back(CustomMessage(json_["message"].get())); + } + } + + if (json_.contains("distribution")){ + distribution = json_["distribution"].get(); + } + + if (json_.contains("locations")){ + for (auto loc: json_["locations"]){ + locations.push_back(StaticData::locationNameToEnum[loc.get()]); + } + } else if (json_.contains("location")){ + locations.push_back(StaticData::locationNameToEnum[json_["location"].get()]); + } + + if (json_.contains("itemNamesChosen")){ + for (auto name: json_["itemNamesChosen"]){ + itemNamesChosen.push_back(name.get()); + } + } else if (json_.contains("itemNameChosen")){ + itemNamesChosen.push_back(json_["itemNameChosen"].get()); + } + + if (json_.contains("areas")){ + for (auto area: json_["areas"]){ + areas.push_back((RandomizerArea)Rando::StaticData::areaNameToEnum[area]); + } + } else if (json_.contains("area")){ + areas.push_back((RandomizerArea)Rando::StaticData::areaNameToEnum[json_["area"]]); + } + + if (json_.contains("areaNamesChosen")){ + for (auto name: json_["areaNamesChosen"]){ + areaNamesChosen.push_back(name.get()); + } + } else if (json_.contains("areaNameChosen")){ + areaNamesChosen.push_back(json_["areaNameChosen"].get()); + } + + if (json_.contains("trials")){ + for (auto trial: json_["trials"]){ + trials.push_back((TrialKey)Rando::StaticData::trialNameToEnum[trial]); + } + } else if (json_.contains("trial")){ + trials.push_back((TrialKey)Rando::StaticData::trialNameToEnum[json_["trial"]]); + } + + if (json_.contains("hintKeys")){ + for (auto hintKey: json_["hintKeys"]){ + hintKeys.push_back((RandomizerHintTextKey)hintKey.get()); + } + } else if (json_.contains("hintKey")){ + hintKeys.push_back((RandomizerHintTextKey)json_["hintKey"].get()); + } + + if (json_.contains("hintTextsChosen")){ + for (auto name: json_["hintTextsChosen"]){ + hintTextsChosen.push_back(name.get()); + } + } else if (json_.contains("hintTextChosen")){ + hintTextsChosen.push_back(json_["hintTextChosen"].get()); + } + + if (json_.contains("num")){ + num = json_["num"].get(); + } + + FillGapsInData(); + SetLocationsAsHinted(); +} + +void Hint::FillGapsInData(){ + auto ctx = Rando::Context::GetInstance(); + if (locations.size() == 0 && StaticData::staticHintInfoMap.contains(ownKey)){ + locations = StaticData::staticHintInfoMap[ownKey].targetChecks; + } + bool fillAreas = true; + bool fillItems = true; + if (areas.size() > 0){ + fillAreas = false; + } + if (items.size() > 0){ + fillItems = false; + } + for(uint8_t c = 0; c < locations.size(); c++){ + if (fillAreas){ + areas.push_back(ctx->GetItemLocation(locations[c])->GetArea()); + } + if (fillItems){ + items.push_back(ctx->GetItemLocation(locations[c])->GetPlacedRandomizerGet()); + } + } +} + +void Hint::SetLocationsAsHinted() const { + auto ctx = Rando::Context::GetInstance(); + for (uint8_t count = 0; count < locations.size(); count++){ + ctx->GetItemLocation(locations[count])->AddHintedBy(ownKey); + } +} + +uint8_t GetRandomHintTextEntry(const HintText hintText){ + auto ctx = Rando::Context::GetInstance(); + uint8_t size = 0; + if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)){ + size = hintText.GetAmbiguousSize(); + } else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)){ + size = hintText.GetObscureSize(); + } + if (size > 0){ + return Random(0, size); + } + return 0; +} + +void Hint::NamesChosen(){ + auto ctx = Rando::Context::GetInstance(); + std::vector namesTemp = {}; + bool saveNames = false; + uint8_t numMessages = GetNumberOfMessages(); + for (uint8_t c = 0; c < numMessages; c++){ + uint8_t selection = GetRandomHintTextEntry(GetHintText(c)); + if (selection > 0){ + saveNames = true; + } + namesTemp.push_back(selection); + } + if (saveNames) { + hintTextsChosen = namesTemp; + } + + if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_ITEM_AREA || hintType == HINT_TYPE_MERCHANT){ + bool mysterious = hintType == HINT_TYPE_MERCHANT && ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_NO_HINT); + for(uint8_t c = 0; c < locations.size(); c++){ + namesTemp = {}; + saveNames = false; + uint8_t selection = GetRandomHintTextEntry(GetItemHintText(c, mysterious)); + if (selection > 0){ + saveNames = true; + } + namesTemp.push_back(selection); + } + if (saveNames) { + itemNamesChosen = namesTemp; + } + } + + if (hintType == HINT_TYPE_FOOLISH || hintType == HINT_TYPE_ITEM_AREA || hintType == HINT_TYPE_WOTH || + hintType == HINT_TYPE_ALTAR_CHILD || hintType == HINT_TYPE_ALTAR_ADULT){ + namesTemp = {}; + saveNames = false; + for(uint8_t c = 0; c < areas.size(); c++){ + uint8_t selection = GetRandomHintTextEntry(GetAreaHintText(c)); + if (selection > 0){ + saveNames = true; + } + namesTemp.push_back(selection); + } + if (saveNames) { + areaNamesChosen = namesTemp; + } + } +} + +uint8_t Hint::GetNumberOfMessages() const { + size_t numMessages = std::max(messages.size(), hintKeys.size()); + if (StaticData::staticHintInfoMap.contains(ownKey)){ + numMessages = std::max(StaticData::staticHintInfoMap[ownKey].hintKeys.size(), numMessages); + } + if (numMessages == 0){ + numMessages = 1; //RANDOTODO make std::max actually fucking work for 3 arguments + } + return numMessages; +} + +const std::vector Hint::GetAllMessageStrings(MessageFormat format) const { + std::vector hintMessages = {}; + uint8_t numMessages = GetNumberOfMessages(); + for (int c = 0; c < numMessages; c++){ + hintMessages.push_back(GetHintMessage(format, c).GetForCurrentLanguage(format)); + } + return hintMessages; +} + +const HintText Hint::GetHintText(uint8_t id) const { + auto ctx = Rando::Context::GetInstance(); + if (hintKeys.size() > id){ + return StaticData::hintTextTable[hintKeys[id]]; + } +// If a static hint, load default from staticHintInfoMap + if (StaticData::staticHintInfoMap.contains(ownKey) && StaticData::staticHintInfoMap[ownKey].hintKeys.size() > id){ + return StaticData::hintTextTable[StaticData::staticHintInfoMap[ownKey].hintKeys[id]]; + } + + switch (hintType){ + case HINT_TYPE_HINT_KEY: + return StaticData::hintTextTable[0]; + break; + case HINT_TYPE_TRIAL: + if (ctx->GetTrial(trials[0])->IsRequired()) { + return StaticData::hintTextTable[RHT_TRIAL_ON]; + } else { + return StaticData::hintTextTable[RHT_TRIAL_OFF]; + } + case HINT_TYPE_WOTH: + return StaticData::hintTextTable[RHT_WAY_OF_THE_HERO]; + case HINT_TYPE_FOOLISH: + return StaticData::hintTextTable[RHT_FOOLISH]; + case HINT_TYPE_ITEM: + if (locations.size() > 0) { + return *StaticData::GetLocation(locations[0])->GetHint(); + } else { + return CustomMessage("ERROR: ITEM HINT WITH NO LOCATIONS OR HINT KEY"); + } + case HINT_TYPE_ITEM_AREA: + if (locations.size() > 0) { + if (StaticData::GetLocation(locations[0])->IsDungeon()) { + return StaticData::hintTextTable[RHT_HOARDS]; + } else { + return StaticData::hintTextTable[RHT_CAN_BE_FOUND_AT]; + } + } else { + return CustomMessage("ERROR: ITEM AREA HINT WITH NO LOCATION"); //RANDOTODO get isDungeon from area? + } + default: + return CustomMessage("ERROR: NO HINTKEY PROVIDED AND HINT TYPE HAS NO DEFAULT"); + } +} + +const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const { + auto ctx = Rando::Context::GetInstance(); + CustomMessage hintText = CustomMessage(""); + + uint8_t chosenMessage = 0; + if (hintTextsChosen.size() > id){ + chosenMessage = id; + } + + if (hintType == HINT_TYPE_MESSAGE){ + if (id < messages.size()){ + hintText = messages[id]; + } + } else if (hintType == HINT_TYPE_ALTAR_CHILD){ + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)){ + hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage(); + } + if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { + hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage()); + } else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY)) { + hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY].GetHintMessage()); + } else { + hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED].GetHintMessage()); + } + } else if (hintType == HINT_TYPE_ALTAR_ADULT){ + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)){ + hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage(); + } + hintText += GetBridgeReqsText() + GetGanonBossKeyText() + StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage(); + } else { + hintText = GetHintText(id).GetHintMessage(chosenMessage); + } + + std::vector toInsert = {}; + + switch (hintType){ + case HINT_TYPE_ITEM:{ + //if we write items + for(uint8_t b = 0; b < locations.size(); b++){ + toInsert.push_back(GetItemName(b)); + } + break;} + case HINT_TYPE_MERCHANT:{ + //if we write items, but need to adjust for merchants + bool mysterious = hintType == HINT_TYPE_MERCHANT && ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_NO_HINT); + for(uint8_t b = 0; b < locations.size(); b++){ + toInsert.push_back(GetItemName(b, mysterious)); + } + break;} + case HINT_TYPE_TRIAL:{ + //If we write trials + for(uint8_t b = 0; b < trials.size(); b++){ + toInsert.push_back(ctx->GetTrial(trials[b])->GetName()); + } + break;} + case HINT_TYPE_ITEM_AREA:{ + //If we write items and areas + for(uint8_t b = 0; b < items.size(); b++){ + toInsert.push_back(GetItemName(b)); + toInsert.push_back(GetAreaName(b)); + } + break;} + case HINT_TYPE_ALTAR_CHILD: + case HINT_TYPE_ALTAR_ADULT: + case HINT_TYPE_AREA: + case HINT_TYPE_WOTH: + case HINT_TYPE_FOOLISH:{ + //If we write areas + for(uint8_t b = 0; b < areas.size(); b++){ + toInsert.push_back(GetAreaName(b)); + } + break;} + default: + break; + } + + hintText.InsertNames(toInsert); + + if (num != 0){ + hintText.InsertNumber(num); + } + + if (format == MF_FORMATTED){ + hintText.Format(); + } else if (format == MF_AUTO_FORMAT){ + hintText.AutoFormat(); + } else if (format == MF_CLEAN){ + hintText.Clean(); + } + + return hintText; +} + +oJson Hint::toJSON() { + auto ctx = Rando::Context::GetInstance(); + nlohmann::ordered_json log = {}; + if (enabled){ + log["type"] = StaticData::hintTypeNames[hintType].GetForCurrentLanguage(MF_CLEAN); + + std::vector hintMessages = GetAllMessageStrings(MF_CLEAN); + if (hintMessages.size() == 1){ + log["message"] = hintMessages[0]; + } else if (hintMessages.size() > 1){ + log["messages"] = hintMessages; + } + + if (distribution != ""){ + log["distribution"] = distribution; + } + + if (hintType != HINT_TYPE_FOOLISH){ + if (!(StaticData::staticHintInfoMap.contains(ownKey) && + StaticData::staticHintInfoMap[ownKey].targetChecks.size() > 0)){ + if (locations.size() == 1){ + log["location"] = StaticData::GetLocation(locations[0])->GetName();//RANDOTODO change to CustomMessage when VB is done; + } else if (locations.size() > 1){ + //If we have defaults, no need to write more + std::vector locStrings = {}; + for (size_t c = 0; c < locations.size(); c++){ + locStrings.push_back(StaticData::GetLocation(locations[c])->GetName());//RANDOTODO change to CustomMessage when VB is done + } + log["locations"] = locStrings; + } + } + + if (!(StaticData::staticHintInfoMap.contains(ownKey) && + StaticData::staticHintInfoMap[ownKey].targetItems.size() > 0)){ + if (items.size() == 1){ + log["item"] = StaticData::GetItemTable()[items[0]].GetName().GetEnglish();//RANDOTODO change to CustomMessage; + } else if (items.size() > 1){ + std::vector itemStrings = {}; + for (size_t c = 0; c < items.size(); c++){ + itemStrings.push_back(StaticData::GetItemTable()[items[c]].GetName().GetEnglish());//RANDOTODO change to CustomMessage + } + log["items"] = itemStrings; + } + } + + if (itemNamesChosen.size() == 1){ + log["itemNameChosen"] = itemNamesChosen[0]; + } else if (itemNamesChosen.size() > 1){ + std::vector nameNums = {}; + for (size_t c = 0; c < itemNamesChosen.size(); c++){ + nameNums.push_back(itemNamesChosen[c]); + } + log["itemNamesChosen"] = nameNums; + } + } + if (areas.size() == 1){ + log["area"] = StaticData::hintTextTable[StaticData::areaNames[areas[0]]].GetClear().GetForCurrentLanguage(MF_CLEAN); + } else if (areas.size() > 0 && + !(StaticData::staticHintInfoMap.contains(ownKey) && StaticData::staticHintInfoMap[ownKey].targetChecks.size() > 0)){ + // If we got locations from defaults, areas are derived from them and don't need logging + std::vector areaStrings = {}; + for (size_t c = 0; c < areas.size(); c++){ + areaStrings.push_back(StaticData::hintTextTable[StaticData::areaNames[areas[c]]].GetClear().GetForCurrentLanguage(MF_CLEAN)); + } + log["areas"] = areaStrings; + } + + if (areaNamesChosen.size() == 1){ + log["areaNameChosen"] = areaNamesChosen[0]; + } else if (areaNamesChosen.size() > 1){ + std::vector nameNums = {}; + for (size_t c = 0; c < areaNamesChosen.size(); c++){ + nameNums.push_back(areaNamesChosen[c]); + } + log["areaNamesChosen"] = nameNums; + } + + if (trials.size() == 1){ + log["trial"] = ctx->GetTrial(trials[0])->GetName().GetForCurrentLanguage(MF_CLEAN); + } else if (trials.size() > 0){ + std::vector trialStrings = {}; + for (size_t c = 0; c < trials.size(); c++){ + trialStrings.push_back(ctx->GetTrial(trials[c])->GetName().GetForCurrentLanguage(MF_CLEAN)); + } + log["trials"] = trialStrings; + } + + if (hintKeys.size() == 1){ + log["hintKey"] = hintKeys[0]; + } else if (hintKeys.size() > 1){ + std::vector hintKeyNums = {}; + for (size_t c = 0; c < hintKeys.size(); c++){ + hintKeyNums.push_back(hintKeys[c]); + } + log["hintKeys"] = hintKeyNums; + } + + if (hintTextsChosen.size() == 1){ + log["hintTextChosen"] = hintTextsChosen[0]; + } else if (hintTextsChosen.size() > 1){ + std::vector nameNums = {}; + for (size_t c = 0; c < hintTextsChosen.size(); c++){ + nameNums.push_back(hintTextsChosen[c]); + } + log["hintTextsChosen"] = nameNums; + } + + if (num != 0){ + log["num"] = num; + } + + } + return log; +} + +void Hint::logHint(oJson& jsonData){ + auto ctx = Rando::Context::GetInstance(); + std::string logMap = "Static Hints"; + bool staticHint = true; + if (ownKey < RH_GANONDORF_HINT){ + logMap = "Gossip Stone Hints"; + staticHint = false; + } + if (enabled && + (!(staticHint && (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_MERCHANT) && ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_CLEAR)))){ + //skip if not enabled or if a static hint with no possible variance + jsonData[logMap][Rando::StaticData::hintNames[ownKey].GetForCurrentLanguage(MF_CLEAN)] = toJSON(); + } +} + +const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const { + //RANDOTODO make unreliant on locations, or make Hint accept ItemLocation + auto ctx = Rando::Context::GetInstance(); + RandomizerCheck hintedCheck = locations[slot]; + RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet(); + if (mysterious){ + return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM]; + } else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) && targetRG == RG_ICE_TRAP) { //RANDOTODO store in item hint instead of item + return HintText(CustomMessage({ctx->overrides[hintedCheck].GetTrickName()})); + } else { + return ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetHint(); + } +} + +const HintText Hint::GetAreaHintText(uint8_t slot) const { + CustomMessage areaText; + if (yourPocket && (areas[slot] == RA_LINKS_POCKET || areas[slot] == RA_NONE)){ + return StaticData::hintTextTable[RHT_YOUR_POCKET]; + } else { + return StaticData::hintTextTable[Rando::StaticData::areaNames[areas[slot]]]; + } +} + + +const CustomMessage Hint::GetItemName(uint8_t slot, bool mysterious) const { + uint8_t nameNum = 0; + if (itemNamesChosen.size() > slot){ + nameNum = itemNamesChosen[slot]; + } + return GetItemHintText(slot, mysterious).GetHintMessage(nameNum); +} + +const CustomMessage Hint::GetAreaName(uint8_t slot) const { + uint8_t nameNum = 0; + if (areaNamesChosen.size() > slot){ + nameNum = areaNamesChosen[slot]; + } + return GetAreaHintText(slot).GetHintMessage(nameNum); +} + + +CustomMessage Hint::GetBridgeReqsText() { + auto ctx = Rando::Context::GetInstance(); + CustomMessage bridgeMessage; + + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN)) { + return StaticData::hintTextTable[RHT_BRIDGE_OPEN_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA)) { + return StaticData::hintTextTable[RHT_BRIDGE_VANILLA_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { + bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_STONES_HINT].GetHintMessage(); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value()); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { + bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT].GetHintMessage(); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value()); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_REWARDS_HINT].GetHintMessage(); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value()); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) { + bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_DUNGEONS_HINT].GetHintMessage(); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value()); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { + bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_TOKENS_HINT].GetHintMessage(); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value()); + } + else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) { + return StaticData::hintTextTable[RHT_BRIDGE_GREG_HINT].GetHintMessage(); + } + return bridgeMessage; +} + +CustomMessage Hint::GetGanonBossKeyText() { + auto ctx = Rando::Context::GetInstance(); + CustomMessage ganonBossKeyMessage; + + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) { + return StaticData::hintTextTable[RHT_GANON_BK_START_WITH_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { + return StaticData::hintTextTable[RHT_GANON_BK_VANILLA_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) { + return StaticData::hintTextTable[RHT_GANON_BK_OWN_DUNGEON_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { + return StaticData::hintTextTable[RHT_GANON_BK_ANY_DUNGEON_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { + return StaticData::hintTextTable[RHT_GANON_BK_OVERWORLD_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE)) { + return StaticData::hintTextTable[RHT_GANON_BK_ANYWHERE_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { + return StaticData::hintTextTable[RHT_GANON_BK_SKULLTULA_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_VANILLA)) { + return StaticData::hintTextTable[RHT_LACS_VANILLA_HINT].GetHintMessage(); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_STONES_HINT].GetHintMessage(); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).Value()); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { + ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_MEDALLIONS_HINT].GetHintMessage(); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value()); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { + ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_REWARDS_HINT].GetHintMessage(); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value()); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { + ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_DUNGEONS_HINT].GetHintMessage(); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value()); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { + ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage(); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value()); + } + else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { + return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage(); + } + return ganonBossKeyMessage; +} + + +void Hint::AddHintedLocation(RandomizerCheck location) { + locations.push_back(location); +} + +std::vector Hint::GetHintedLocations() const { + return locations; } void Hint::SetHintType(HintType type) { hintType = type; } -HintType Hint::GetHintType() { +HintType Hint::GetHintType() const { return hintType; } -void Hint::SetHintedArea(RandomizerArea area) { - hintedArea = area; +void Hint::AddHintedArea(RandomizerArea area) { + areas.push_back(area); } -RandomizerArea Hint::GetHintedArea() { - return hintedArea; +std::vector Hint::GetHintedAreas() const { + return areas; } void Hint::SetDistribution(std::string distributionName) { distribution = distributionName; } -const std::string& Hint::GetDistribution() { +const std::string& Hint::GetDistribution() const { return distribution; } +bool Hint::IsEnabled() const{ + return enabled; +} + +std::vector Hint::GetHintTextKeys() const{ + return hintKeys; +} + +std::vector Hint::GetHintedItems() const{ + return items; +} + +std::vector Hint::GetItemNamesChosen() const{ + return itemNamesChosen; +} + +std::vector Hint::GetHintTextsChosen() const{ + return hintTextsChosen; +} +std::vector Hint::GetAreaTextsChosen() const{ + return areaNamesChosen; +} + +std::vector Hint::GetHintedTrials() const{ + return trials; +} + +int Hint::GetNum(){ + return num; +} void Hint::ResetVariables() { - hintedLocation = RC_UNKNOWN_CHECK; - text = Text{}; - distribution = ""; - hintedArea = RA_NONE; - hintType = HINT_TYPE_STATIC; - addedToPool = false; + ownKey = RH_NONE; + num = 0; + yourPocket = false; + messages = {}; + hintKeys = {}; + locations = {}; + items = {}; + trials = {}; + hintType = HINT_TYPE_HINT_KEY; + areas = {}; + distribution = ""; + enabled = false; + itemNamesChosen = {}; + hintTextsChosen = {}; + areaNamesChosen = {}; } + } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/hint.h b/soh/soh/Enhancements/randomizer/hint.h index 4b76cd691..dc626ebf9 100644 --- a/soh/soh/Enhancements/randomizer/hint.h +++ b/soh/soh/Enhancements/randomizer/hint.h @@ -1,33 +1,82 @@ #pragma once #include "3drando/text.hpp" +#include "3drando/hints.hpp" +#include "../custom-message/CustomMessageManager.h" #include "randomizerTypes.h" +#include +#include "nlohmann/json.hpp" +using oJson = nlohmann::ordered_json; namespace Rando { class Hint { - public: - Hint(); - Hint(Text text_); - Hint(Text text_, RandomizerCheck hintedLocation_, HintType hintType_, std::string distributionName_, RandomizerArea hintedArea_); - const Text& GetText() const; - RandomizerCheck GetHintedLocation(); - void SetHintedLocation (RandomizerCheck location); - HintType GetHintType(); - void SetHintType (HintType type); - RandomizerArea GetHintedArea(); - void SetHintedArea (RandomizerArea area); - const std::string& GetDistribution(); - void SetDistribution (std::string distribution); - void ResetVariables(); - bool IsAddedToPool(); - void AddToPool(); + public: + Hint(); + Hint(RandomizerHint ownKey_, + HintType hintType_, + std::string distributionName_, + std::vector hintKeys_, + std::vector locations_, + std::vector areas_ = {}, + std::vector trials_ = {}); + Hint(RandomizerHint ownKey_, + HintType hintType_, + std::vector hintKeys_, + std::vector locations_ = {}, + std::vector areas_ = {}, + std::vector trials_ = {}, + bool yourPocket_ = false, + int num_ = 0); + Hint(RandomizerHint ownKey_, std::vector messages_); + Hint(RandomizerHint ownKey_, nlohmann::json json_); + void FillGapsInData(); + void SetLocationsAsHinted() const; + void NamesChosen(); + uint8_t GetNumberOfMessages() const; + const std::vector GetAllMessageStrings(MessageFormat format = MF_AUTO_FORMAT) const ; + const CustomMessage GetHintMessage(MessageFormat format = MF_AUTO_FORMAT, uint8_t id = 0) const ; + const HintText GetHintText(uint8_t id = 0) const; + oJson toJSON(); + void logHint(oJson& jsonData); + const HintText GetItemHintText(uint8_t slot, bool mysterious) const; + const HintText GetAreaHintText(uint8_t slot) const; + const CustomMessage GetItemName(uint8_t slot, bool mysterious = false) const; + const CustomMessage GetAreaName(uint8_t slot) const; + static CustomMessage GetBridgeReqsText(); + static CustomMessage GetGanonBossKeyText(); + void AddHintedLocation (RandomizerCheck location); + std::vector GetHintedLocations() const; + void SetHintType (HintType type); + HintType GetHintType() const; + void AddHintedArea (RandomizerArea area); + std::vector GetHintedAreas() const; + void SetDistribution (std::string distribution); + const std::string& GetDistribution() const; + bool IsEnabled() const; + std::vector GetHintTextKeys() const; + std::vector GetHintedItems() const; + std::vector GetItemNamesChosen() const; + std::vector GetHintTextsChosen() const; + std::vector GetAreaTextsChosen() const; + std::vector GetHintedTrials() const; + int GetNum(); + void ResetVariables(); - private: - Text text = Text(); - RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK; - HintType hintType = HINT_TYPE_STATIC; - RandomizerArea hintedArea = RA_NONE; - std::string distribution = ""; - bool addedToPool = false; + private: + RandomizerHint ownKey = RH_NONE; + HintType hintType = HINT_TYPE_HINT_KEY; + std::string distribution = ""; + std::vector hintKeys = {}; + std::vector locations = {}; + std::vector areas = {}; + std::vector trials = {}; + bool yourPocket = false; + int num = 0; + std::vector messages = {}; + std::vector items = {}; + bool enabled = false; + std::vector itemNamesChosen = {}; + std::vector hintTextsChosen = {}; + std::vector areaNamesChosen = {}; }; } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 970d7a347..16396c072 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -378,7 +378,7 @@ RandomizerHintTextKey Item::GetHintKey() const { } const HintText& Item::GetHint() const { - return ::Hint(hintKey); + return StaticData::hintTextTable[hintKey]; } bool Item::operator==(const Item& right) const { diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index d1610a7bc..8986d1146 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -5,9 +5,9 @@ #include #include "3drando/text.hpp" -#include "3drando/hint_list.hpp" #include "randomizerTypes.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h" +#include "3drando/hints.hpp" enum ItemType { ITEMTYPE_ITEM, diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 4541550e8..2b6c42d34 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -8,7 +8,7 @@ using namespace Rando; std::array Rando::StaticData::itemTable; -std::unordered_map Rando::StaticData::SpoilerfileItemNameToEnum; +std::unordered_map Rando::StaticData::itemNameToEnum; void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); @@ -322,15 +322,15 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, &logic->TriforcePieces, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - // Init SpoilerfileItemNameToEnum + // Init itemNameToEnum for (auto& item : itemTable) { // Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE // entry if (item.GetName().english.empty()) { continue; } - SpoilerfileItemNameToEnum[item.GetName().english] = item.GetRandomizerGet(); - SpoilerfileItemNameToEnum[item.GetName().french] = item.GetRandomizerGet(); + itemNameToEnum[item.GetName().english] = item.GetRandomizerGet(); + itemNameToEnum[item.GetName().french] = item.GetRandomizerGet(); } } diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 736778786..59bceb8d5 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -109,19 +109,19 @@ void ItemLocation::SetAsHintable() { isHintable = true; } -bool ItemLocation::IsHintedAt() const { - return hintedAt; +bool ItemLocation::IsAHintAccessible() const { + return hintAccesible; } -void ItemLocation::SetAsHinted() { - hintedAt = true; +void ItemLocation::SetHintAccesible() { + hintAccesible = true; } -const std::vector& ItemLocation::GetHintedBy() const { +const std::vector& ItemLocation::GetHintedBy() const { return hintedBy; } -void ItemLocation::AddHintedBy(const RandomizerHintKey hintKey) { +void ItemLocation::AddHintedBy(const RandomizerHint hintKey) { hintedBy.push_back(hintKey); } @@ -193,7 +193,7 @@ void ItemLocation::ResetVariables() { placedItem = RG_NONE; delayedItem = RG_NONE; isHintable = false; - hintedAt = false; + hintAccesible = false; hintedBy = {}; price = 0; hasCustomPrice = false; diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h index a4b60a5d3..dd5ec8a00 100644 --- a/soh/soh/Enhancements/randomizer/item_location.h +++ b/soh/soh/Enhancements/randomizer/item_location.h @@ -33,10 +33,10 @@ class ItemLocation { void SetCustomPrice(uint16_t price_); bool IsHintable() const; void SetAsHintable(); - bool IsHintedAt() const; - void SetAsHinted(); - const std::vector& GetHintedBy() const; - void AddHintedBy(RandomizerHintKey hintKey); + bool IsAHintAccessible() const; + void SetHintAccesible(); + const std::vector& GetHintedBy() const; + void AddHintedBy(RandomizerHint hintKey); bool IsHidden() const; bool IsExcluded() const; void AddExcludeOption(); @@ -52,8 +52,8 @@ class ItemLocation { private: RandomizerCheck rc; - std::vector hintedBy = {}; - bool hintedAt = false; + std::vector hintedBy = {}; + bool hintAccesible = false; bool isHintable = false; bool addedToPool = false; RandomizerGet placedItem = RG_NONE; diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index a0783f4ad..24d6ac9cb 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -1,5 +1,5 @@ #include "location.h" -#include "3drando/hint_list.hpp" +#include "static_data.h" #include RandomizerCheck Rando::Location::GetRandomizerCheck() const { @@ -47,7 +47,7 @@ RandomizerHintTextKey Rando::Location::GetHintKey() const { } HintText* Rando::Location::GetHint() { - return &hintTable[hintKey]; + return &StaticData::hintTextTable[hintKey]; } const std::string& Rando::Location::GetName() const { @@ -90,7 +90,7 @@ uint32_t Rando::Location::Getuint32_t() const { } const HintText& Rando::Location::GetHint() const { - return Hint(hintKey); + return StaticData::hintTextTable[hintKey]; } RandomizerGet Rando::Location::GetVanillaItem() const { diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index c5418dda2..f990bb1fb 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -3,7 +3,6 @@ #define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) std::array Rando::StaticData::locationTable; -std::unordered_map Rando::StaticData::SpoilerfileCheckNameToEnum; std::multimap, RandomizerCheck> Rando::StaticData::CheckFromActorMultimap; std::vector KF_ShopLocations = { @@ -501,49 +500,49 @@ std::vector Rando::StaticData::overworldLocations = { }; std::vector Rando::StaticData::gossipStoneLocations = { - RC_COLOSSUS_GOSSIP_STONE, - RC_DMC_GOSSIP_STONE, - RC_DMC_UPPER_GROTTO_GOSSIP_STONE, - RC_DMT_GOSSIP_STONE, - RC_DMT_STORMS_GROTTO_GOSSIP_STONE, - RC_DODONGOS_CAVERN_GOSSIP_STONE, - RC_FAIRY_GOSSIP_STONE, - RC_GC_MAZE_GOSSIP_STONE, - RC_GC_MEDIGORON_GOSSIP_STONE, - RC_GV_GOSSIP_STONE, - RC_GY_GOSSIP_STONE, - RC_HC_MALON_GOSSIP_STONE, - RC_HC_ROCK_WALL_GOSSIP_STONE, - RC_HC_STORMS_GROTTO_GOSSIP_STONE, - RC_HF_COW_GROTTO_GOSSIP_STONE, - RC_HF_NEAR_MARKET_GOSSIP_STONE, - RC_HF_OPEN_GROTTO_GOSSIP_STONE, - RC_HF_SOUTHEAST_GOSSIP_STONE, - RC_JABU_GOSSIP_STONE, RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RC_KF_GOSSIP_STONE, - RC_KF_STORMS_GOSSIP_STONE, - RC_KAK_OPEN_GROTTO_GOSSIP_STONE, - RC_LH_LAB_GOSSIP_STONE, - RC_LH_SOUTHEAST_GOSSIP_STONE, - RC_LH_SOUTHWEST_GOSSIP_STONE, + RC_KF_STORMS_GROTTO_GOSSIP_STONE, RC_LW_GOSSIP_STONE, - RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, + RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RC_SFM_MAZE_LOWER_GOSSIP_STONE, RC_SFM_MAZE_UPPER_GOSSIP_STONE, RC_SFM_SARIA_GOSSIP_STONE, + RC_HF_COW_GROTTO_GOSSIP_STONE, + RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, + RC_HF_OPEN_GROTTO_GOSSIP_STONE, + RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RC_TOT_LEFT_CENTER_GOSSIP_STONE, - RC_TOT_LEFT_GOSSIP_STONE, + RC_TOT_LEFTMOST_GOSSIP_STONE, RC_TOT_RIGHT_CENTER_GOSSIP_STONE, - RC_TOT_RIGHT_GOSSIP_STONE, - RC_ZD_GOSSIP_STONE, + RC_TOT_RIGHTMOST_GOSSIP_STONE, + RC_HC_MALON_GOSSIP_STONE, + RC_HC_ROCK_WALL_GOSSIP_STONE, + RC_HC_STORMS_GROTTO_GOSSIP_STONE, + RC_KAK_OPEN_GROTTO_GOSSIP_STONE, + RC_GRAVEYARD_GOSSIP_STONE, + RC_DMT_GOSSIP_STONE, + RC_DMT_STORMS_GROTTO_GOSSIP_STONE, + RC_GC_MAZE_GOSSIP_STONE, + RC_GC_MEDIGORON_GOSSIP_STONE, + RC_DMC_GOSSIP_STONE, + RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RC_ZR_OPEN_GROTTO_GOSSIP_STONE, + RC_ZD_GOSSIP_STONE, + RC_ZF_JABU_GOSSIP_STONE, + RC_ZF_FAIRY_GOSSIP_STONE, + RC_LH_LAB_GOSSIP_STONE, + RC_LH_SOUTHEAST_GOSSIP_STONE, + RC_LH_SOUTHWEST_GOSSIP_STONE, + RC_GV_GOSSIP_STONE, + RC_COLOSSUS_GOSSIP_STONE, + RC_DODONGOS_CAVERN_GOSSIP_STONE, }; -std::vector Rando::StaticData::otherHintLocations = { +std::vector Rando::StaticData::staticHintLocations = { RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC, @@ -1515,48 +1514,48 @@ void Rando::StaticData::InitLocationTable() { locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - // Gossip Stones - // RandomizerCheck Randomizer Check Quest Area Scene Params Flag Short Name Spoiler name Categories - locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); - locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); - locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); - locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); - locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); - locationTable[RC_GY_GOSSIP_STONE] = Location::HintStone(RC_GY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); - locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); - locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); - locationTable[RC_KF_STORMS_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); - locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); - locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); - locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); - locationTable[RC_TOT_LEFT_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); - locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); - locationTable[RC_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); - locationTable[RC_JABU_GOSSIP_STONE] = Location::HintStone(RC_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); - locationTable[RC_HF_NEAR_MARKET_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); - locationTable[RC_HF_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); - locationTable[RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); + // Gossip Stones RANDOTODO work towards removing and replacing with event access + // RandomizerCheck Randomizer Check Quest Area Scene Params Flag Short Name Spoiler name Categories + locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); + locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); + locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); + locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); + locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); + locationTable[RC_GRAVEYARD_GOSSIP_STONE] = Location::HintStone(RC_GRAVEYARD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); + locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); + locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); + locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); + locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); + locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); + locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); + locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); + locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); + locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); + locationTable[RC_ZF_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_ZF_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); + locationTable[RC_ZF_JABU_GOSSIP_STONE] = Location::HintStone(RC_ZF_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); + locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); + locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); // Other Hints locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); @@ -1572,12 +1571,12 @@ void Rando::StaticData::InitLocationTable() { locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on - // Init SpoilerfileCheckNameToEnum - SpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK; - SpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET; + // Init locationNameToEnum + locationNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK; + locationNameToEnum["Link's Pocket"] = RC_LINKS_POCKET; for (auto& location : locationTable) { - SpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck(); + locationNameToEnum[location.GetName()] = location.GetRandomizerCheck(); CheckFromActorMultimap.emplace(std::make_tuple((int16_t)location.GetActorID(), (int16_t)location.GetScene(), location.GetActorParams()), location.GetRandomizerCheck()); } } diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index e50846005..d3f1fa8e4 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -503,10 +503,13 @@ void Settings::CreateOptionDescriptions() { "Reading the Temple of Time altar as child will tell you the locations of the Spiritual Stones.\n" "Reading the Temple of Time altar as adult will tell you the locations of the Medallions, as well as the " "conditions for building the Rainbow Bridge and getting the Boss Key for Ganon's Castle."; - mOptionDescriptions[RSK_LIGHT_ARROWS_HINT] = - "Talking to Ganondorf in his boss room or Sheik inside Ganon's Castle (when trials are enabled) will tell you " - "the location of the Light Arrows." - "If this option is enabled and Ganondorf is reachable without Light Arrows, Gossip Stones will never hint the " + mOptionDescriptions[RSK_GANONDORF_HINT] = + "Talking to Ganondorf in his boss room will tell you the location of the Light Arrows and Master Sword." + "If this option is enabled and Ganondorf is reachable without these items, Gossip Stones will never hint the " + "appropriote items.";//RANDOTODO make this hint text about no dupe hints a global hint for static hints. Add to navi? + mOptionDescriptions[RSK_SHEIK_LA_HINT] = + "Talking to Sheik inside Ganon's Castle will tell you the location of the Light Arrows." + "If this option is enabled and Sheik is reachable without Light Arrows, Gossip Stones will never hint the " "Light Arrows."; mOptionDescriptions[RSK_DAMPES_DIARY_HINT] = "Reading the diary of Dampé the gravekeeper as adult will tell you the location of one of the Hookshots."; @@ -546,7 +549,7 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_BLUE_FIRE_ARROWS] = "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress."; - mOptionDescriptions[RSK_LIGHT_ARROWS_HINT] = + mOptionDescriptions[RSK_SUNLIGHT_ARROWS] = "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress."; mOptionDescriptions[RSK_LOGIC_RULES] = diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 99d8961a5..868a9dea3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -10,6 +10,7 @@ #include #include "3drando/rando_main.hpp" #include "3drando/random.hpp" +#include "3drando/custom_messages.hpp" #include "../../UIWidgets.hpp" #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS @@ -37,12 +38,12 @@ #include "settings.h" #include "soh/util.h" #include "fishsanity.h" +#include "randomizerTypes.h" extern "C" uint32_t ResourceMgr_IsGameMasterQuest(); extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); extern std::map rcAreaNames; -extern std::array hintTypeNames; using json = nlohmann::json; using namespace std::literals::string_literals; @@ -136,8 +137,8 @@ Randomizer::Randomizer() { SpoilerfileAreaNameToEnum["the Graveyard"] = RCAREA_GRAVEYARD; SpoilerfileAreaNameToEnum["Haunted Wasteland"] = RCAREA_WASTELAND; SpoilerfileAreaNameToEnum["outside Ganon's Castle"] = RCAREA_HYRULE_CASTLE; - for (int c = 0; c < hintTypeNames.size(); c++) { - SpoilerfileHintTypeNameToEnum[hintTypeNames[c]] = (HintType)c; + for (int c = 0; c < Rando::StaticData::hintTypeNames.size(); c++) { + SpoilerfileHintTypeNameToEnum[Rando::StaticData::hintTypeNames[(HintType)c].GetEnglish(MF_CLEAN)] = (HintType)c; } } @@ -240,187 +241,10 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD, - CustomMessage(ctx->GetHint(RH_ALTAR_CHILD)->GetText(), TEXTBOX_TYPE_BLUE)); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT, - CustomMessage(ctx->GetHint(RH_ALTAR_ADULT)->GetText(), TEXTBOX_TYPE_BLUE)); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_GANONDORF, - CustomMessage(ctx->GetHint(RH_GANONDORF_HINT)->GetText())); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT, - CustomMessage(ctx->GetHint(RH_GANONDORF_NOHINT)->GetText())); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_SHEIK_NEED_HOOK, - CustomMessage("{{message}}", "{{message}}", "{{message}}")); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_SHEIK_HAVE_HOOK, - CustomMessage("{{message}}", "{{message}}", "{{message}}")); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE, - CustomMessage(ctx->GetHint(RH_SARIA)->GetText(), TEXTBOX_TYPE_BLUE)); - - for (int i : Rando::StaticData::gossipStoneLocations) { - RandomizerHintKey rhk = RandomizerHintKey(i - RC_COLOSSUS_GOSSIP_STONE + 1); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, i, CustomMessage(ctx->GetHint(rhk)->GetText())); - } - //Extra Hints CustomMessageManager::Instance->ClearMessageTable(Randomizer::randoMiscHintsTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::randoMiscHintsTableID); - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_SKULLTULA_PEOPLE_IM_CURSED, - CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying&%r{{params}} Spiders of the Curse%w&and I will give you my&%g{{item1}}%w!", - "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du %r{{params}} Skulltulas&%wzerstörst und ich werde dir dafür&%g{{item1}} %wgeben!", - "Yeaaarrgh! Je suis maudit!^Détruit encore %r{{params}} Araignées de&la Malédiction%w et j'aurai quelque&chose à te donner!&%g({{item1}})") - ); - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY, - CustomMessage(ctx->GetHint(RH_DAMPES_DIARY)->GetText()) - ); - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED, - CustomMessage(ctx->GetHint(RH_GREG_RUPEE)->GetText()) - ); - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER, - CustomMessage(ctx->GetHint(RH_FROGS)->GetText().GetEnglish(), - ctx->GetHint(RH_FROGS)->GetText().GetGerman(), - ctx->GetHint(RH_FROGS)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE) - ); - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_MINUET_OF_FOREST, - CustomMessage(ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetFrench())); - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_BOLERO_OF_FIRE, - CustomMessage(ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetFrench())); - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_SERENADE_OF_WATER, - CustomMessage(ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetFrench())); - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_REQUIEM_OF_SPIRIT, - CustomMessage(ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetFrench())); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_SARIAS_SONG_FOREST_SOUNDS, - CustomMessage("{{message}}", "{{message}}", "{{message}}", TEXTBOX_TYPE_BLUE) - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_BIGGORON_BETTER_AT_SMITHING, - CustomMessage("Arrrrrre you here to claim my finest&%g{{item1}}%w?&Shoooooow me your %rClaim Check.%w", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_GHOST_SHOP_CARD_HAS_POINTS, - CustomMessage("You have %g\x1E\x01%r Poe Points%w!&Reach 1000 and you'll get a&%g{{item1}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, - CustomMessage("You! Please!&Bring my Cucco's back to my pen!&I'll give you my %g{{item1}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_OBSTICLE_COURSE, - CustomMessage("How about trying the %rObsticle Course?%w&If you beat my time I'll let you keep&my favourite cow Elsie and&her toy %g{{item1}}%w!^" - "Challenge the %rObsticle Course?&\x1B&%gLet's go&No thanks%w", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_HOW_IS_EPONA_DOING, - CustomMessage("@! You should come back &with Epona and try to beat my time&on the %rObsticle Course%w!^If you beat my time, I'll give you&my favourite %rcow%w Elsie and&her toy %g{{item1}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_EVERYONE_TURNING_EVIL, - CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an &%rObsticle Course%w, and whoever gets&the best time would win a %rcow%w!^Elsie loves sharing her %g{{item1}}%w&with new people, It'll be fun!^...But Ingo won't let me...", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, - CustomMessage("@! You should come back in&the morning and try to beat my time&on the %rObsticle Course%w!^If you beat my time, I'll give you&my favourite %rcow%w Elsie and&her toy %g{{item1}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_HBA_NOT_ON_HORSE, - CustomMessage("Hey, rookie!&Come back on your %rhorse%w&and take on the&%rHorseback Archery%w challenge!^Impress me with a high score of 1000&to win a %g{{item1}}%w&or score 1500 for my&%g{{item2}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_HBA_INITIAL_EXPLAINATION, - CustomMessage("Hey, rookie!&Want to take on the&%rHorseback Archery%w challenge?^Impress me with a high score of 1000&to win a %g{{item1}}%w&or score 1500 for my&%g{{item2}}%w!\x0B", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_HBA_ALREADY_HAVE_1000, - CustomMessage("Hey, newcomer!&Want to take on the&%rHorseback Archery%w challenge?^Prove yourself to be a horsemaster&by scoring 1500 points to win &my %g{{item1}}%w!\x0B", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_GF_HBA_SIGN, - CustomMessage("%rHorseback Archery%w Range Prizes:&1000: %g{{item1}}%w&1500: %g{{item2}}%w^@'s Record: %g\x1E\x00%w", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_OBSTICLE_COURSE, - CustomMessage("How about trying your skill on the %rObsticle Course?%w& If you beat my time I'll let you keep my favourite cow Elsie and& her toy %g{{item1}}%w!&x1B&%gLet's go&No thanks%w", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_EVERYONE_TURNING_EVIL, - CustomMessage("@? Is that you? &If I ran the ranch, I'd build an %rObsticle Course%w, and whoever gets the best time would win a cow!& Elsie loves sharing her %g{{item1}}%w&with new people, It'll be fun!&...But Ingo won't let me...", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, - CustomMessage("@! You should come back in the morning and try to beat my time on the %rObsticle Course%w!&If you beat my time, I'll let you keep Elsie and& her toy %g{{item1}}%w!", - "", - "") - ); - - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_NOCTURNE_OF_SHADOW, - CustomMessage(ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetFrench())); - CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_PRELUDE_OF_LIGHT, - CustomMessage(ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetEnglish(), - ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetGerman(), - ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetFrench())); // Bow Shooting Gallery reminder CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, @@ -428,19 +252,12 @@ void Randomizer::LoadHintMessages() { "Komm wieder sobald du deinen eigenen&Bogen hast, um einen %rspeziellen Preis%w zu&erhalten!", "J'aurai %rune autre récompense%w pour toi&lorsque tu auras ton propre arc.")); - // Fishing pond pole hint - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START, - CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(), - ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(), - ctx->GetHint(RH_FISHING_POLE)->GetText().GetFrench()) - ); - CustomMessageManager::Instance->CreateMessage( - Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START_MET, - CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(), - ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(), - ctx->GetHint(RH_FISHING_POLE)->GetText().GetFrench()) - ); + // Warp Song Mysterious text + CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST, + CustomMessage("Warp to&#a mysterious place?#&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", + "Zu&#ein mysteriöser Ort#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", + "Se téléporter vers&#un endroit mystérieux#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK!&Non#", + {QM_RED, QM_GREEN})); // Lake Hylia water level system CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, @@ -493,67 +310,38 @@ void Randomizer::LoadMerchantMessages() { // Prices have a chance of being 0, and the "sell" message below doesn't really make sense for a free item, so adding a "free" variation here CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE, - CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will give you a&%g{{item}}%w!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen &%g{{item}}%w geben!\x07\x10\xA3", - "\x12\x38\x82" "J'me rends! Laisse-moi partir et en&échange, je te donne un &%g{{item}}%w! Vas-y prends le!\x07\x10\xA3")); + CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will give you a&%g[[item]]%w!&Please, take it!\x07\x10\xA3", + "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen &%g[[item]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" "J'me rends! Laisse-moi partir et en&échange, je te donne un &%g[[item]]%w! Vas-y prends le!\x07\x10\xA3")); CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM, - CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will sell you a&%g{{item}}%w!&%r{{price}} Rupees%w it is!\x07\x10\xA3", - "\x12\x38\x82" "Aufgeben! Ich verkaufe dir einen&%g{{item}}%w&für %r{{price}} Rubine%w!\x07\x10\xA3", - "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter&un %g{{item}}%w?&Ça fera %r{{price}} Rubis%w!\x07\x10\xA3")); + CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will sell you a&%g[[item]]%w!&%r[[price]] Rupees%w it is!\x07\x10\xA3", + "\x12\x38\x82" "Aufgeben! Ich verkaufe dir einen&%g[[item]]%w&für %r[[price]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter&un %g[[item]]%w?&Ça fera %r[[price]] Rubis%w!\x07\x10\xA3")); + + //Carpet Salesman CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10, - CustomMessage(ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetEnglish(), - ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetGerman(), - ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetFrench())); + Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2, + CustomMessage("Finally! Now I can go back to being &an %rarms dealer%w!", + /*german*/"Endlich! Schon bald kann ich wieder &%rKrabbelminen-Händler%w sein!", + /*french*/ "Squalala! Je vais enfin pouvoir &%rprendre des vacances%w!")); + + // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are + // prompted buy/don't buy + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM, + CustomMessage("\x08%r[[item]] [[price]] Rupees&%wSpecial deal! ONE LEFT!&Get it while it lasts!\x0A\x02", + "\x08%r[[item]] [[price]] Rubine&%wSonderangebot! NUR NOCH EINES VERFÜGBAR!&Beeilen Sie sich!\x0A\x02", + "\x08%r[[item]] [[price]] Rubis&%wOffre spéciale! DERNIER EN STOCK!&Faites vite!\x0A\x02")); + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM_CONFIRM, + CustomMessage("\x08[[item]] [[price]] Rupees\x09&&\x1B%gBuy&Don't buy%w\x09\x02", + "\x08[[item]] [[price]] Rubine\x09&&\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08[[item]] [[price]] Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w\x09\x02")); CustomMessageManager::Instance->CreateMessage( Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, CustomMessage("I never thought I'd say this, but I'm &selling the last %rMagic Bean%w. %r99%w Rupees...\x1B&%gYes&No%w", - "\x1B&%gJa&Nein%w", - "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); - - - //Setup for merchant text boxes - //Medigoron - //RANDOTODO: Implement obscure/ambiguous hints - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_MEDIGORON, - CustomMessage(ctx->GetHint(RH_MEDIGORON)->GetText().GetEnglish(), - ctx->GetHint(RH_MEDIGORON)->GetText().GetGerman(), - ctx->GetHint(RH_MEDIGORON)->GetText().GetFrench())); - - //Granny Shop - //RANDOTODO: Implement obscure/ambiguous hints - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP, - CustomMessage(ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetEnglish(), - ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetGerman(), - ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetFrench())); - - //Carpet Salesman - //RANDOTODO: Implement obscure/ambiguous hints - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1, - CustomMessage(ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetEnglish(), - ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetGerman(), - ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetFrench())); - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2, - CustomMessage(ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetEnglish(), - ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetGerman(), - ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetFrench())); - - // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are - // prompted buy/don't buy - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM, - CustomMessage("\x08%r{{item}} {{price}} Rupees&%wSpecial deal! ONE LEFT!&Get it while it lasts!\x0A\x02", - "\x08%r{{item}} {{price}} Rubine&%wSonderangebot! NUR NOCH EINES VERFÜGBAR!&Beeilen Sie sich!\x0A\x02", - "\x08%r{{item}} {{price}} Rubis&%wOffre spéciale! DERNIER EN STOCK!&Faites vite!\x0A\x02")); - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM_CONFIRM, - CustomMessage("\x08{{item}} {{price}} Rupees\x09&&\x1B%gBuy&Don't buy%w\x09\x02", - "\x08{{item}} {{price}} Rubine\x09&&\x1B%gKaufen&Nicht kaufen%w\x09\x02", - "\x08{{item}} {{price}} Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w\x09\x02")); + "\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); } bool Randomizer::IsTrialRequired(RandomizerInf trial) { @@ -1654,7 +1442,7 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, case SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS: switch (actorParams) { case 14342: - specialRc = RC_TOT_LEFT_GOSSIP_STONE; + specialRc = RC_TOT_LEFTMOST_GOSSIP_STONE; break; case 14599: specialRc = RC_TOT_LEFT_CENTER_GOSSIP_STONE; @@ -1663,7 +1451,7 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, specialRc = RC_TOT_RIGHT_CENTER_GOSSIP_STONE; break; case 15120: - specialRc = RC_TOT_RIGHT_GOSSIP_STONE; + specialRc = RC_TOT_RIGHTMOST_GOSSIP_STONE; break; } break; @@ -1702,11 +1490,11 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, switch (actorParams) { case 15362: case 14594: - specialRc = RC_JABU_GOSSIP_STONE; + specialRc = RC_ZF_JABU_GOSSIP_STONE; break; case 14849: case 14337: - specialRc = RC_FAIRY_GOSSIP_STONE; + specialRc = RC_ZF_FAIRY_GOSSIP_STONE; break; } break; @@ -2601,109 +2389,51 @@ void RandomizerSettingsWindow::UpdateElement() { } } -CustomMessage Randomizer::ReplaceWithItemName(CustomMessage message, std::string&& toReplace, RandomizerCheck hintedCheck){ - auto ctx = Rando::Context::GetInstance(); - RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet(); - std::array itemName; - if (targetRG == RG_ICE_TRAP) { - targetRG = ctx->overrides[hintedCheck].LooksLike(); - itemName = { - ctx->overrides[hintedCheck].GetTrickName().english, - ctx->overrides[hintedCheck].GetTrickName().french, - ctx->overrides[hintedCheck].GetTrickName().english - }; - } else { - itemName = { - Rando::StaticData::RetrieveItem(targetRG).GetName().english, - Rando::StaticData::RetrieveItem(targetRG).GetName().french, - Rando::StaticData::RetrieveItem(targetRG).GetName().english, - }; - } - message.Replace(std::move(toReplace), std::move(itemName[0]), std::move(itemName[1]), std::move(itemName[2])); - return message; -} - - -CustomMessage Randomizer::GetMiscHintMessage(TextIDs textToGet, RandomizerCheck hintedCheck, RandomizerCheck otherCheck) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textToGet); - messageEntry = ReplaceWithItemName(messageEntry, "{{item1}}", hintedCheck); - if (otherCheck != RC_UNKNOWN_CHECK){ - messageEntry = ReplaceWithItemName(messageEntry, "{{item2}}", otherCheck); - } - return messageEntry; -} - -CustomMessage Randomizer::GetCursedSkullMessage(s16 params, RandomizerCheck hintedCheck) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry = GetMiscHintMessage(TEXT_SKULLTULA_PEOPLE_IM_CURSED, hintedCheck); - messageEntry.Replace("{{params}}", std::to_string(params*10)); - return messageEntry; -} - CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, originalTextId); + CustomMessage messageEntry; switch (scene) { case SCENE_TEMPLE_OF_TIME: - if (originalTextId == TEXT_SHEIK_NEED_HOOK) { - messageEntry.Replace("{{message}}", + if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { + messageEntry = CustomMessage( "@,&meet me at %gGanon's Castle%w&once you obtain the %rkey to his lair%w.", "@, wir treffen uns bei %gGanons Schloß%w,&sobald Du den %rSchlüssel zu&seinem Verließ%w hast.", "Retrouve-moi au %gChâteau de Ganon%w une&fois que tu auras obtenu la&Mrclé de son repaire%w."); } else { - messageEntry.Replace("{{message}}", + messageEntry = CustomMessage( "The time has come. Prepare yourself.", "Die Zeit ist gekommen.&Mach Dich bereit.", "Le moment est venu @.&Tu ferais bien de te préparer."); } break; case SCENE_INSIDE_GANONS_CASTLE: - if (originalTextId == TEXT_SHEIK_NEED_HOOK) { - //If MS shuffle is on, Sheik will hint both MS and LA as long as Link doesn't have both, to prevent hint lockout. - //Otherwise, she'll only give LA hint so only LA is required to move on. - bool needRequirements = GetRandoSettingValue(RSK_SHUFFLE_MASTER_SWORD) ? - (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) || INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) : - (INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT); - if (needRequirements) { - messageEntry.Replace("{{message}}", ctx->GetHint(RH_SHEIK_LIGHT_ARROWS)->GetText().GetEnglish().c_str(), ctx->GetHint(RH_SHEIK_LIGHT_ARROWS)->GetText().GetEnglish().c_str(), ctx->GetHint(RH_SHEIK_LIGHT_ARROWS)->GetText().GetFrench().c_str()); - } else { - messageEntry.Replace("{{message}}", "You are still ill-equipped to&face %rGanondorf%w." + if (ctx->GetOption(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { + messageEntry = ctx->GetHint(RH_SHEIK_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && + CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { + messageEntry = CustomMessage("You are still ill-equipped to&face %rGanondorf%w." "^Seek out the %cMaster Sword%w,&%rsomething to hold your arrows%w,&and %gmagic%w to summon the %ylight%w.", "Du bist noch nicht gewappnet um Dich&%rGanondorf%w stellen zu können.^" "Begib Dich auf die Suche nach dem&%cMaster-Schwert%w, %retwas um deine Pfeilen&einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w&herauf beschwören zu können.", "@, tu n'es toujours pas prêt à affronter&%rGanondorf%w.^" "Cherche l'%cÉpée de Légende%w,&%rquelque chose pour ranger tes flèches%w&et de la %gmagie%w pour invoquer la&%ylumière%w."); - } - } else { - if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER)) { - messageEntry.Replace("{{message}}", + } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER)){ + messageEntry = CustomMessage( "You may have what you need to defeat&%rthe Evil King%w, but the %cbarrier%w still&stands.^Complete the remaining %gtrials%w&to destroy it." - ); - - } else { - messageEntry.Replace("{{message}}", + ); + } else { + messageEntry = CustomMessage( "If you're ready, then proceed.^Good luck.", "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", "Si tu es prêt, tu peux y aller.^Bonne chance."); - } } break; } return messageEntry; } -CustomMessage Randomizer::GetSariaMessage(u16 originalTextId) { - if (originalTextId == TEXT_SARIA_SFM || (originalTextId >= TEXT_SARIAS_SONG_FACE_TO_FACE && originalTextId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE); - CustomMessage messageEntry2 = messageEntry; - std::string code = originalTextId == TEXT_SARIA_SFM ? "" : "\x0B"; - messageEntry2.Replace("$C", std::move(code)); - return messageEntry2; - } -} - CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { - CustomMessage hintMessageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START); + auto ctx = Rando::Context::GetInstance(); CustomMessage messageEntry = CustomMessage( "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", "", @@ -2711,7 +2441,7 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { ); if (Rando::Context::GetInstance()->GetOption(RSK_FISHING_POLE_HINT)) { - messageEntry = messageEntry + hintMessageEntry; + messageEntry = messageEntry + CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetHintMessage()); } // if the fishing pond guy doesnt remember me i will cry :( @@ -2723,61 +2453,38 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { ) + messageEntry; } - messageEntry.Format(); + messageEntry.Format(); //RANDOTODO why is this needed when it's not elsewhere.... return messageEntry; } CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious) { - auto ctx = Rando::Context::GetInstance(); + auto ctx = Rando::Context::GetInstance(); //RANDOTODO If scrubs are allowed to have ambiguous hints, they need to be RandomiserHint objects for logging CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId); RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf); RandomizerGet shopItemGet = ctx->GetItemLocation(rc)->GetPlacedRandomizerGet(); - std::array shopItemName; + CustomMessage shopItemName; if (mysterious) { - shopItemName = { - "mysterious item", - "mysteriösen Gegenstand", - "objet mystérieux" - }; + shopItemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM].GetHintMessage(); // TODO: This should eventually be replaced with a full fledged trick model & trick name system } else if (shopItemGet == RG_ICE_TRAP) { shopItemGet = ctx->overrides[rc].LooksLike(); - shopItemName = { - std::string(ctx->overrides[rc].GetTrickName().english), - std::string(ctx->overrides[rc].GetTrickName().french), - std::string(ctx->overrides[rc].GetTrickName().english) - }; + shopItemName = CustomMessage(ctx->overrides[rc].GetTrickName()); } else { auto shopItem = Rando::StaticData::RetrieveItem(shopItemGet); - shopItemName = { - shopItem.GetName().english, - shopItem.GetName().french, - shopItem.GetName().english, - }; + shopItemName = {shopItem.GetName()}; } u16 shopItemPrice = ctx->GetItemLocation(rc)->GetPrice(); if (textId == TEXT_SCRUB_RANDOM && shopItemPrice == 0) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE); - } else if (textId == TEXT_GRANNYS_SHOP) { - // Capitalize the first letter for the item in Granny's text as the item is the first word presented - for (auto &itemName : shopItemName) { - itemName[0] = std::toupper(itemName[0]); - } } - messageEntry.Replace("{{item}}", std::move(shopItemName[0]), std::move(shopItemName[1]), std::move(shopItemName[2])); - messageEntry.Replace("{{price}}", std::to_string(shopItemPrice)); + messageEntry.Replace("[[item]]", shopItemName); + messageEntry.Replace("[[price]]", std::to_string(shopItemPrice)); return messageEntry; } -static const char* mapGetItemHints[3][2] = { - { " It's ordinary.", " It's masterful!" }, - { "&Sieht aus wie immer.", " &Man kann darauf die Worte&%r\"Master Quest\"%w entziffern..." }, - { "&Elle vous semble %rordinaire%w.", "&Étrange... les mots %r\"Master&Quest\"%w sont gravés dessus." }, -}; - CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) { CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, itemEntry.getItemId); int sceneNum; @@ -2818,11 +2525,11 @@ CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) { (GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER && GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12) ) { - messageEntry.Replace("{{typeHint}}", ""); + messageEntry.Replace("[[typeHint]]", ""); } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { - messageEntry.Replace("{{typeHint}}", mapGetItemHints[0][1], mapGetItemHints[1][1], mapGetItemHints[2][1]); + messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); } else { - messageEntry.Replace("{{typeHint}}", mapGetItemHints[0][0], mapGetItemHints[1][0], mapGetItemHints[2][0]); + messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); } return messageEntry; @@ -2848,16 +2555,16 @@ void CreateRupeeMessages() { for (u8 rupee : rupees) { switch (rupee) { case TEXT_BLUE_RUPEE: - rupeeText = "\x05\x03 5 {{rupee}}\x05\x00"; + rupeeText = "\x05\x03 5 [[rupee]]\x05\x00"; break; case TEXT_RED_RUPEE: - rupeeText = "\x05\x01 20 {{rupee}}\x05\x00"; + rupeeText = "\x05\x01 20 [[rupee]]\x05\x00"; break; case TEXT_PURPLE_RUPEE: - rupeeText = "\x05\x05 50 {{rupee}}\x05\x00"; + rupeeText = "\x05\x05 50 [[rupee]]\x05\x00"; break; case TEXT_HUGE_RUPEE: - rupeeText = "\x05\x06 200 {{rupee}}\x05\x00"; + rupeeText = "\x05\x06 200 [[rupee]]\x05\x00"; break; } customMessageManager->CreateMessage( @@ -2869,37 +2576,38 @@ void CreateRupeeMessages() { CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::rupeeMessageTableID, rupeeTextId); - messageEntry.Replace("{{rupee}}", RandomElement(englishRupeeNames), - RandomElement(germanRupeeNames), RandomElement(frenchRupeeNames)); + messageEntry.Replace("[[rupee]]", CustomMessage(RandomElement(englishRupeeNames), + RandomElement(germanRupeeNames), + RandomElement(frenchRupeeNames))); return messageEntry; } void CreateTriforcePieceMessages() { CustomMessage TriforcePieceMessages[NUM_TRIFORCE_PIECE_MESSAGES] = { - { "You found a %yTriforce Piece%w!&%g{{current}}%w down, %c{{remaining}}%w to go. It's a start!", - "Ein %yTriforce-Splitter%w! Du hast&%g{{current}}%w von %c{{required}}%w gefunden. Es ist ein&Anfang!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g{{current}}%w, il en&reste %c{{remaining}}%w à trouver. C'est un début!" }, + { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }, - { "You found a %yTriforce Piece%w!&%g{{current}}%w down, %c{{remaining}}%w to go. Progress!", - "Ein %yTriforce-Splitter%w! Du hast&%g{{current}}%w von %c{{required}}%w gefunden. Es geht voran!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g{{current}}%w, il en&reste %c{{remaining}}%w à trouver. Ça avance!" }, + { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }, - { "You found a %yTriforce Piece%w!&%g{{current}}%w down, %c{{remaining}}%w to go. Over half-way&there!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g{{current}}%w von %c{{required}}%w gefunden. Schon&über die Hälfte!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g{{current}}%w, il en&reste %c{{remaining}}%w à trouver. Il en reste un&peu moins que la moitié!" }, + { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }, - { "You found a %yTriforce Piece%w!&%g{{current}}%w down, %c{{remaining}}%w to go. Almost done!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g{{current}}%w von %c{{required}}%w gefunden. Fast&geschafft!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g{{current}}%w, il en&reste %c{{remaining}}%w à trouver. C'est presque&terminé!" }, + { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }, { "You completed the %yTriforce of&Courage%w! %gGG%w!", "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }, - { "You found a spare %yTriforce Piece%w!&You only needed %c{{required}}%w, but you have %g{{current}}%w!", - "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g{{current}}%w von %c{{required}}%w nötigen gefunden.", - "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c{{required}}%w, mais vous en avez %g{{current}}%w en&tout!" }, + { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", + "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", + "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }, }; CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::triforcePieceMessageTableID); @@ -2932,9 +2640,9 @@ CustomMessage Randomizer::GetTriforcePieceMessage() { CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::triforcePieceMessageTableID, messageIndex); - messageEntry.Replace("{{current}}", std::to_string(current), std::to_string(current), std::to_string(current)); - messageEntry.Replace("{{remaining}}", std::to_string(remaining), std::to_string(remaining), std::to_string(remaining)); - messageEntry.Replace("{{required}}", std::to_string(required), std::to_string(required), std::to_string(required)); + messageEntry.Replace("[[current]]", std::to_string(current)); + messageEntry.Replace("[[remaining]]", std::to_string(remaining)); + messageEntry.Replace("[[required]]", std::to_string(required)); return messageEntry; } @@ -3156,11 +2864,11 @@ void CreateFireTempleGoronMessages() { "je&ressemble à n'importe quel Goron?", }, { - "How long has it been, do you know?^%r{{days}}%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " + "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " "cake!!", - "Weißt du zufällig, wie viele Tage&vergangen sind?^%r{{days}}%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " + "Weißt du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " "Ich&muss dringend nach meinem Kuchen&sehen!!!", - "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r{{days}}%w " + "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", }, { @@ -3182,11 +2890,11 @@ void CreateFireTempleGoronMessages() { "aller.&A plus tard.", }, { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " - "pressed it %b{{a_btn}}%w times.^Wow.", + "pressed it %b[[a_btn]]%w times.^Wow.", "Weißt du über %b\x9f%w bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " - "erschienen sind...^Es scheint, dass du sie schon&%b{{a_btn}}%w mal betätigt hast.^Faszinierend...", + "erschienen sind...^Es scheint, dass du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " - "dernièrement...^Apparemment, tu as appuyé dessus&%b{{a_btn}}%w fois.^Wow..." }, + "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." }, { "\x13\x1A" "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " @@ -3223,8 +2931,8 @@ void CreateFireTempleGoronMessages() { CustomMessage Randomizer::GetGoronMessage(u16 index) { CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, goronIDs[index]); - messageEntry.Replace("{{days}}", std::to_string(gSaveContext.totalDays)); - messageEntry.Replace("{{a_btn}}", std::to_string(gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A])); + messageEntry.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); + messageEntry.Replace("[[a_btn]]", std::to_string(gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A])); return messageEntry; } @@ -3377,45 +3085,45 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"), GIMESSAGE(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, - "You found the %gDeku Tree &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%gDeku-Baum%w!{{typeHint}}", - "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w!{{typeHint}}"), + "You found the %gDeku Tree &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%gDeku-Baum%w![[typeHint]]", + "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w![[typeHint]]"), GIMESSAGE(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, - "You found the %rDodongo's Cavern &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für&%rDodongos Höhle%w!{{typeHint}}", - "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w!{{typeHint}}"), + "You found the %rDodongo's Cavern &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für&%rDodongos Höhle%w![[typeHint]]", + "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w![[typeHint]]"), GIMESSAGE(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, - "You found the %bJabu Jabu's Belly &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für&%bJabu-Jabus Bauch%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w!{{typeHint}}"), + "You found the %bJabu Jabu's Belly &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für&%bJabu-Jabus Bauch%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w![[typeHint]]"), GIMESSAGE(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %gForest Temple &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%gWaldtempel%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w!{{typeHint}}"), + "You found the %gForest Temple &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%gWaldtempel%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w![[typeHint]]"), GIMESSAGE(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %rFire Temple &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%rFeuertempel%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%rTemple du Feu%w!{{typeHint}}"), + "You found the %rFire Temple &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%rFeuertempel%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%rTemple du Feu%w![[typeHint]]"), GIMESSAGE(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %bWater Temple &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%bWassertempel%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w!{{typeHint}}"), + "You found the %bWater Temple &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%bWassertempel%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w![[typeHint]]"), GIMESSAGE(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %ySpirit Temple &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%yGeistertempel%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w!{{typeHint}}"), + "You found the %ySpirit Temple &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%yGeistertempel%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w![[typeHint]]"), GIMESSAGE(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %pShadow Temple &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%pSchattentempel%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w!{{typeHint}}"), + "You found the %pShadow Temple &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%pSchattentempel%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w![[typeHint]]"), GIMESSAGE(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, - "You found the %pBottom of the &Well %wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für den&%pGrund des Brunnens%w!{{typeHint}}", - "Vous obtenez la %rCarte %wdu &%pPuits%w!{{typeHint}}"), + "You found the %pBottom of the &Well %wMap![[typeHint]]", + "Du erhältst die %rKarte%w für den&%pGrund des Brunnens%w![[typeHint]]", + "Vous obtenez la %rCarte %wdu &%pPuits%w![[typeHint]]"), GIMESSAGE(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, - "You found the %cIce Cavern &%wMap!{{typeHint}}", - "Du erhältst die %rKarte%w für die&%cEishöhle%w!{{typeHint}}", - "Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w!{{typeHint}}"), + "You found the %cIce Cavern &%wMap![[typeHint]]", + "Du erhältst die %rKarte%w für die&%cEishöhle%w![[typeHint]]", + "Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w![[typeHint]]"), GIMESSAGE(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!", diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 5f567cd54..866f4cd7f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -59,13 +59,9 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); - CustomMessage ReplaceWithItemName(CustomMessage message, std::string&& toReplace, RandomizerCheck hintedCheck); - CustomMessage GetMiscHintMessage(TextIDs textToGet, RandomizerCheck hintedCheck, RandomizerCheck otherCheck = RC_UNKNOWN_CHECK); - CustomMessage GetSariaMessage(u16 originalTextId); CustomMessage GetFishingPondOwnerMessage(u16 originalTextId); CustomMessage GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); - CustomMessage GetCursedSkullMessage(s16 params, RandomizerCheck hintedCheck); CustomMessage GetGoronMessage(u16 index); CustomMessage GetMapGetItemMessageWithHint(GetItemEntry itemEntry); static void CreateCustomMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 91906d127..5e651e807 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -38,14 +38,18 @@ typedef enum { } RandomizerCheckStatus; typedef enum { - HINT_TYPE_STATIC, + HINT_TYPE_HINT_KEY, + HINT_TYPE_AREA, + HINT_TYPE_ITEM, HINT_TYPE_TRIAL, - HINT_TYPE_WOTH, // Way of the Hero - HINT_TYPE_BARREN, HINT_TYPE_ENTRANCE, HINT_TYPE_ITEM_AREA, - HINT_TYPE_ITEM_LOCATION, - HINT_TYPE_JUNK, + HINT_TYPE_MERCHANT, + HINT_TYPE_ALTAR_CHILD, + HINT_TYPE_ALTAR_ADULT, + HINT_TYPE_WOTH, // Way of the Hero + HINT_TYPE_FOOLISH, + HINT_TYPE_MESSAGE, HINT_TYPE_MAX } HintType; @@ -90,24 +94,34 @@ typedef enum { RA_MAX } RandomizerArea; +typedef enum { + TK_LIGHT_TRIAL, + TK_FOREST_TRIAL, + TK_FIRE_TRIAL, + TK_WATER_TRIAL, + TK_SPIRIT_TRIAL, + TK_SHADOW_TRIAL, + TK_MAX +} TrialKey; + // Check types based on main settings typedef enum { - RCTYPE_STANDARD, // Base set of rando checks - RCTYPE_SKULL_TOKEN, // Gold Skulltulas - RCTYPE_COW, // Cows - RCTYPE_ADULT_TRADE, // Adult trade quest checks - RCTYPE_FROG_SONG, // Frog song purple rupee checks - RCTYPE_MAP_COMPASS, // Maps/Compasses - RCTYPE_SMALL_KEY, // Small Keys - RCTYPE_GF_KEY, // Gerudo Fortress Keys - RCTYPE_BOSS_KEY, // Boss Keys - RCTYPE_GANON_BOSS_KEY, // Ganon's boss key - RCTYPE_SHOP, // shops - RCTYPE_SCRUB, // scrubs - RCTYPE_MERCHANT, // merchants - RCTYPE_CHEST_GAME, // todo replace this once we implement it, just using it to exclude for now - RCTYPE_LINKS_POCKET, // todo this feels hacky - RCTYPE_GOSSIP_STONE, + RCTYPE_STANDARD, // Base set of rando checks + RCTYPE_SKULL_TOKEN, // Gold Skulltulas + RCTYPE_COW, // Cows + RCTYPE_ADULT_TRADE, // Adult trade quest checks + RCTYPE_FROG_SONG, // Frog song purple rupee checks + RCTYPE_MAP_COMPASS, // Maps/Compasses + RCTYPE_SMALL_KEY, // Small Keys + RCTYPE_GF_KEY, // Gerudo Fortress Keys + RCTYPE_BOSS_KEY, // Boss Keys + RCTYPE_GANON_BOSS_KEY, // Ganon's boss key + RCTYPE_SHOP, // shops + RCTYPE_SCRUB, // scrubs + RCTYPE_MERCHANT, // merchants + RCTYPE_CHEST_GAME, // RANDOTODO replace this once we implement it, just using it to exclude for now + RCTYPE_LINKS_POCKET, // RANDOTODO this feels hacky, replace with better starting items + RCTYPE_GOSSIP_STONE, // RANDOTODO make these into event access RCTYPE_SONG_LOCATION, // Song locations RCTYPE_BOSS_HEART_OR_OTHER_REWARD, // Boss heart container or lesser dungeon rewards (lens, ice arrow) RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) @@ -1388,46 +1402,46 @@ typedef enum { RC_PIERRE, RC_DELIVER_RUTOS_LETTER, RC_MASTER_SWORD_PEDESTAL, - RC_COLOSSUS_GOSSIP_STONE, - RC_DMC_GOSSIP_STONE, - RC_DMC_UPPER_GROTTO_GOSSIP_STONE, - RC_DMT_GOSSIP_STONE, - RC_DMT_STORMS_GROTTO_GOSSIP_STONE, - RC_DODONGOS_CAVERN_GOSSIP_STONE, - RC_FAIRY_GOSSIP_STONE, - RC_GC_MAZE_GOSSIP_STONE, - RC_GC_MEDIGORON_GOSSIP_STONE, - RC_GV_GOSSIP_STONE, - RC_GY_GOSSIP_STONE, - RC_HC_MALON_GOSSIP_STONE, - RC_HC_ROCK_WALL_GOSSIP_STONE, - RC_HC_STORMS_GROTTO_GOSSIP_STONE, - RC_HF_COW_GROTTO_GOSSIP_STONE, - RC_HF_NEAR_MARKET_GOSSIP_STONE, - RC_HF_OPEN_GROTTO_GOSSIP_STONE, - RC_HF_SOUTHEAST_GOSSIP_STONE, - RC_JABU_GOSSIP_STONE, RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RC_KF_GOSSIP_STONE, - RC_KF_STORMS_GOSSIP_STONE, - RC_KAK_OPEN_GROTTO_GOSSIP_STONE, - RC_LH_LAB_GOSSIP_STONE, - RC_LH_SOUTHEAST_GOSSIP_STONE, - RC_LH_SOUTHWEST_GOSSIP_STONE, + RC_KF_STORMS_GROTTO_GOSSIP_STONE, RC_LW_GOSSIP_STONE, - RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, + RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RC_SFM_MAZE_LOWER_GOSSIP_STONE, RC_SFM_MAZE_UPPER_GOSSIP_STONE, RC_SFM_SARIA_GOSSIP_STONE, + RC_HF_COW_GROTTO_GOSSIP_STONE, + RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, + RC_HF_OPEN_GROTTO_GOSSIP_STONE, + RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RC_TOT_LEFT_CENTER_GOSSIP_STONE, - RC_TOT_LEFT_GOSSIP_STONE, + RC_TOT_LEFTMOST_GOSSIP_STONE, RC_TOT_RIGHT_CENTER_GOSSIP_STONE, - RC_TOT_RIGHT_GOSSIP_STONE, - RC_ZD_GOSSIP_STONE, + RC_TOT_RIGHTMOST_GOSSIP_STONE, + RC_HC_MALON_GOSSIP_STONE, + RC_HC_ROCK_WALL_GOSSIP_STONE, + RC_HC_STORMS_GROTTO_GOSSIP_STONE, + RC_KAK_OPEN_GROTTO_GOSSIP_STONE, + RC_GRAVEYARD_GOSSIP_STONE, + RC_DMT_GOSSIP_STONE, + RC_DMT_STORMS_GROTTO_GOSSIP_STONE, + RC_GC_MAZE_GOSSIP_STONE, + RC_GC_MEDIGORON_GOSSIP_STONE, + RC_DMC_GOSSIP_STONE, + RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RC_ZR_OPEN_GROTTO_GOSSIP_STONE, + RC_ZD_GOSSIP_STONE, + RC_ZF_JABU_GOSSIP_STONE, + RC_ZF_FAIRY_GOSSIP_STONE, + RC_LH_LAB_GOSSIP_STONE, + RC_LH_SOUTHEAST_GOSSIP_STONE, + RC_LH_SOUTHWEST_GOSSIP_STONE, + RC_GV_GOSSIP_STONE, + RC_COLOSSUS_GOSSIP_STONE, + RC_DODONGOS_CAVERN_GOSSIP_STONE, RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, @@ -1996,75 +2010,83 @@ typedef enum { typedef enum { RH_NONE, - RH_COLOSSUS_GOSSIP_STONE, - RH_DMC_GOSSIP_STONE, - RH_DMC_UPPER_GROTTO_GOSSIP_STONE, - RH_DMT_GOSSIP_STONE, - RH_DMT_STORMS_GROTTO_GOSSIP_STONE, - RH_DODONGOS_CAVERN_GOSSIP_STONE, - RH_ZF_FAIRY_GOSSIP_STONE, - RH_GC_MAZE_GOSSIP_STONE, - RH_GC_MEDIGORON_GOSSIP_STONE, - RH_GV_GOSSIP_STONE, - RH_GRAVEYARD_GOSSIP_STONE, - RH_HC_MALON_GOSSIP_STONE, - RH_HC_ROCK_WALL_GOSSIP_STONE, - RH_HC_STORMS_GROTTO_GOSSIP_STONE, + RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE, + RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, + RH_KF_GOSSIP_STONE, + RH_KF_STORMS_GROTTO_GOSSIP_STONE, + RH_LW_GOSSIP_STONE, + RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, + RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE, + RH_SFM_MAZE_CENTER_GOSSIP_STONE, + RH_SFM_SARIA_GOSSIP_STONE, RH_HF_COW_GROTTO_GOSSIP_STONE, RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RH_HF_OPEN_GROTTO_GOSSIP_STONE, RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, - RH_ZF_JABU_GOSSIP_STONE, - RH_KF_DEKU_TREE_GOSSIP_STONE_LEFT, - RH_KF_DEKU_TREE_GOSSIP_STONE_RIGHT, - RH_KF_GOSSIP_STONE, - RH_KF_STORMS_GROTTO_GOSSIP_STONE, + RH_TOT_LEFT_CENTER_GOSSIP_STONE, + RH_TOT_LEFTMOST_GOSSIP_STONE, + RH_TOT_RIGHT_CENTER_GOSSIP_STONE, + RH_TOT_RIGHTMOST_GOSSIP_STONE, + RH_HC_MALON_GOSSIP_STONE, + RH_HC_ROCK_WALL_GOSSIP_STONE, + RH_HC_STORMS_GROTTO_GOSSIP_STONE, RH_KAK_OPEN_GROTTO_GOSSIP_STONE, - RH_LH_LAB_GOSSIP_STONE, - RH_LH_SOUTHEAST_GOSSIP_STONE, - RH_LH_SOUTHWEST_GOSSIP_STONE, - RH_LW_GOSSIP_STONE, - RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, - RH_SFM_MAZE_GOSSIP_STONE_LOWER, - RH_SFM_MAZE_GOSSIP_STONE_UPPER, - RH_SFM_SARIA_GOSSIP_STONE, - RH_TOT_GOSSIP_STONE_LEFT_CENTER, - RH_TOT_GOSSIP_STONE_LEFT, - RH_TOT_GOSSIP_STONE_RIGHT_CENTER, - RH_TOT_GOSSIP_STONE_RIGHT, - RH_ZD_GOSSIP_STONE, + RH_GRAVEYARD_GOSSIP_STONE, + RH_DMT_GOSSIP_STONE, + RH_DMT_STORMS_GROTTO_GOSSIP_STONE, + RH_GC_MAZE_GOSSIP_STONE, + RH_GC_MEDIGORON_GOSSIP_STONE, + RH_DMC_GOSSIP_STONE, + RH_DMC_UPPER_GROTTO_GOSSIP_STONE, RH_ZR_NEAR_DOMAIN_GOSSIP_STONE, RH_ZR_NEAR_GROTTOS_GOSSIP_STONE, RH_ZR_OPEN_GROTTO_GOSSIP_STONE, + RH_ZD_GOSSIP_STONE, + RH_ZF_JABU_GOSSIP_STONE, + RH_ZF_FAIRY_GOSSIP_STONE, + RH_LH_LAB_GOSSIP_STONE, + RH_LH_SOUTHEAST_GOSSIP_STONE, + RH_LH_SOUTHWEST_GOSSIP_STONE, + RH_GV_GOSSIP_STONE, + RH_COLOSSUS_GOSSIP_STONE, + RH_DODONGOS_CAVERN_GOSSIP_STONE, RH_GANONDORF_HINT, - RH_GANONDORF_NOHINT, + RH_GANONDORF_JOKE, + RH_SHEIK_HINT, RH_DAMPES_DIARY, RH_GREG_RUPEE, - RH_BEAN_SALESMAN, - RH_MEDIGORON, - RH_GRANNYS_SHOP, - RH_WASTELAND_BOMBCHU_SALESMAN, - RH_WASTELAND_BOMBCHU_SALESMAN_POST, RH_ALTAR_CHILD, RH_ALTAR_ADULT, - RH_SARIA, + RH_SARIA_HINT, RH_FISHING_POLE, - RH_SHEIK_LIGHT_ARROWS, RH_MINUET_WARP_LOC, RH_BOLERO_WARP_LOC, RH_SERENADE_WARP_LOC, RH_REQUIEM_WARP_LOC, RH_NOCTURNE_WARP_LOC, RH_PRELUDE_WARP_LOC, - RH_FROGS, + RH_MEDIGORON, + RH_CARPET_SALESMAN, + RH_BEAN_SALESMAN, + RH_GRANNY, + RH_HBA_HINT, + RH_MALON_HINT, + RH_CHICKENS_HINT, + RH_BIG_POES_HINT, + RH_BIGGORON_HINT, + RH_FROGS_HINT, + RH_KAK_10_SKULLS_HINT, + RH_KAK_20_SKULLS_HINT, + RH_KAK_30_SKULLS_HINT, + RH_KAK_40_SKULLS_HINT, + RH_KAK_50_SKULLS_HINT, + RH_KAK_100_SKULLS_HINT, RH_MAX, -} RandomizerHintKey; +} RandomizerHint; typedef enum { RHT_NONE, - RHT_PREFIX, RHT_WAY_OF_THE_HERO, - RHT_PLUNDERING, RHT_FOOLISH, RHT_CAN_BE_FOUND_AT, RHT_HOARDS, @@ -3163,7 +3185,6 @@ typedef enum { RHT_BUY_RED_POTION_50, RHT_TRIFORCE, RHT_HINT, - RHT_HINT_MYSTERIOUS, RHT_TYCOON_WALLET, RHT_CHILD_WALLET, RHT_HOOKSHOT, @@ -3208,6 +3229,8 @@ typedef enum { RHT_BRONZE_SCALE, RHT_FISHING_POLE, RHT_EPONA, + RHT_HINT_MYSTERIOUS, + RHT_MYSTERIOUS_ITEM, // Entrances RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO, RHT_GV_GROTTO_LEDGE_TO_GV_OCTOROK_GROTTO, @@ -3367,60 +3390,69 @@ typedef enum { // Trials RHT_SIX_TRIALS, RHT_ZERO_TRIALS, - RHT_FOUR_TO_FIVE_TRIALS, - RHT_ONE_TO_THREE_TRIALS, + RHT_TRIAL_OFF, + RHT_TRIAL_ON, + RHT_LIGHT_TRIAL, + RHT_FOREST_TRIAL, + RHT_FIRE_TRIAL, + RHT_WATER_TRIAL, + RHT_SPIRIT_TRIAL, + RHT_SHADOW_TRIAL, // Altar - RHT_SPIRITUAL_STONE_TEXT_START, + RHT_CHILD_ALTAR_STONES, RHT_CHILD_ALTAR_TEXT_END_DOTOPEN, RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY, RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED, - RHT_ADULT_ALTAR_TEXT_START, + RHT_ADULT_ALTAR_MEDALLIONS, RHT_ADULT_ALTAR_TEXT_END, - // Validation Line - RHT_VALIDATION_LINE, - // Light Arrow Location - RHT_LIGHT_ARROW_LOCATION_HINT, - RHT_SHEIK_LIGHT_ARROW_HINT, - // Master Sword Location - RHT_MASTER_SWORD_LOCATION_HINT, - RHT_SHEIK_MASTER_SWORD_LOCATION_HINT, - // Your Pocket - RHT_YOUR_POCKET, - // Other Hints - RHT_DAMPE_DIARY01, - RHT_DAMPE_DIARY02, - RHT_GREG_HINT01, - RHT_GREG_HINT02, - RHT_SARIA_TEXT01, - RHT_SARIA_TEXT02, - RHT_WARP_TO, - RHT_WARP_CHOICE, - RHT_FROGS_HINT01, - RHT_FROGS_HINT02, - RHT_FISHING_POLE_HINT01, - RHT_FISHING_POLE_HINT02, - // Ganon Line - RHT_GANON_LINE01, - RHT_GANON_LINE02, - RHT_GANON_LINE03, - RHT_GANON_LINE04, - RHT_GANON_LINE05, - RHT_GANON_LINE06, - RHT_GANON_LINE07, - RHT_GANON_LINE08, - RHT_GANON_LINE09, - RHT_GANON_LINE10, - RHT_GANON_LINE11, - // Merchants - RHT_BEAN_SALESMAN_FIRST, - RHT_BEAN_SALESMAN_SECOND, - RHT_MEDIGORON_DIALOG_FIRST, - RHT_MEDIGORON_DIALOG_SECOND, + // Static Item Hints + RHT_GANONDORF_HINT_LA_ONLY, + RHT_GANONDORF_HINT_MS_ONLY, + RHT_GANONDORF_HINT_LA_AND_MS, + RHT_SHEIK_HINT_LA_ONLY, + RHT_DAMPE_DIARY, + RHT_GREG_HINT, + RHT_SARIA_TALK_HINT, + RHT_SARIA_SONG_HINT, + RHT_FISHING_POLE_HINT, + // Static Entrance Hints + RHT_WARP_SONG, + // Static Location Hints + RHT_MEDIGORON_HINT, RHT_CARPET_SALESMAN_DIALOG_FIRST, RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS, RHT_CARPET_SALESMAN_DIALOG_HINTED, - RHT_CARPET_SALESMAN_DIALOG_FINAL, - RHT_GRANNY_DIALOG, + RHT_BEAN_SALESMAN_HINT, + RHT_GRANNY_HINT, + RHT_HBA_HINT_SIGN, + RHT_HBA_HINT_NOT_ON_HORSE, + RHT_HBA_HINT_INITIAL, + RHT_HBA_HINT_HAVE_1000, + RHT_MALON_HINT_HOW_IS_EPONA, + RHT_MALON_HINT_OBSTICLE_COURSE, + RHT_MALON_HINT_TURNING_EVIL, + RHT_MALON_HINT_INGO_TEMPTED, + RHT_CHICKENS_HINT, + RHT_BIG_POES_HINT, + RHT_BIGGORON_HINT, + RHT_FROGS_HINT, + RHT_SKULLS_HINT, + // Ganon Line + RHT_GANON_JOKE01, + RHT_GANON_JOKE02, + RHT_GANON_JOKE03, + RHT_GANON_JOKE04, + RHT_GANON_JOKE05, + RHT_GANON_JOKE06, + RHT_GANON_JOKE07, + RHT_GANON_JOKE08, + RHT_GANON_JOKE09, + RHT_GANON_JOKE10, + RHT_GANON_JOKE11, + // Misc utilities + RHT_YOUR_POCKET, + RHT_DUNGEON_ORDINARY, + RHT_DUNGEON_MASTERFUL, RHT_MAX } RandomizerHintTextKey; @@ -3553,7 +3585,8 @@ typedef enum { RSK_ICE_TRAPS, RSK_GOSSIP_STONE_HINTS, RSK_TOT_ALTAR_HINT, - RSK_LIGHT_ARROWS_HINT, + RSK_GANONDORF_HINT, + RSK_SHEIK_LA_HINT, RSK_DAMPES_DIARY_HINT, RSK_GREG_HINT, RSK_SARIA_HINT, @@ -3583,7 +3616,6 @@ typedef enum { RSK_SKIP_CHILD_ZELDA, RSK_STARTING_CONSUMABLES, RSK_FULL_WALLETS, - RSK_LANGUAGE, RSK_SHUFFLE_CHEST_MINIGAME, RSK_CUCCO_COUNT, RSK_BIG_POE_COUNT, @@ -4095,3 +4127,5 @@ typedef enum { TH_MESSAGE_FINISHED, TH_MESSAGE_SURPLUS, } TriforceHuntMessages; + + diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index b664b0898..f00179ef7 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -158,7 +158,8 @@ void Settings::CreateOptions() { mOptions[RSK_HINT_CLARITY] = Option::U8("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, "gRandomizeHintClarity", mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT); mOptions[RSK_HINT_DISTRIBUTION] = Option::U8("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, "gRandomizeHintDistribution", mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT); mOptions[RSK_TOT_ALTAR_HINT] = Option::Bool("ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeAltarHint", mOptionDescriptions[RSK_TOT_ALTAR_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_INDENT); - mOptions[RSK_LIGHT_ARROWS_HINT] = Option::Bool("Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeLAHint", mOptionDescriptions[RSK_LIGHT_ARROWS_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); + mOptions[RSK_GANONDORF_HINT] = Option::Bool("Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeGanondorfHint", mOptionDescriptions[RSK_GANONDORF_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); + mOptions[RSK_SHEIK_LA_HINT] = Option::Bool("Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeSheikLAHint", mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", "gRandomizeDampeHint", mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE); mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", "gRandomizeGregHint", mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", "gRandomizeSariaHint", mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); @@ -208,8 +209,6 @@ void Settings::CreateOptions() { mOptions[RSK_ALL_LOCATIONS_REACHABLE] = Option::Bool("All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, "gRandomizeAllLocationsReachable", mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON); mOptions[RSK_SKULLS_SUNS_SONG] = Option::Bool("Night Skulltula's Expect Sun's Song", "gRandomizeGsExpectSunsSong", mOptionDescriptions[RSK_SKULLS_SUNS_SONG]); mOptions[RSK_DAMAGE_MULTIPLIER] = Option::U8("Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WidgetType::Slider, RO_DAMAGE_MULTIPLIER_DEFAULT); - - mOptions[RSK_LANGUAGE] = Option::U8("Language", {"English", "German", "French"}, OptionCategory::Setting, "gLanguages", "", WidgetType::Combobox, LANGUAGE_ENG); // clang-format on mExcludeLocationsOptionsGroups.reserve(SPOILER_COLLECTION_GROUP_COUNT); @@ -729,7 +728,8 @@ void Settings::CreateOptions() { }, false, WidgetContainerType::SECTION); mOptionGroups[RSG_EXTRA_HINTS_IMGUI] = OptionGroup::SubGroup("Extra Hints", { &mOptions[RSK_TOT_ALTAR_HINT], - &mOptions[RSK_LIGHT_ARROWS_HINT], + &mOptions[RSK_GANONDORF_HINT], + &mOptions[RSK_SHEIK_LA_HINT], &mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT], &mOptions[RSK_SARIA_HINT], @@ -956,7 +956,8 @@ void Settings::CreateOptions() { &mOptions[RSK_HINT_CLARITY], &mOptions[RSK_HINT_DISTRIBUTION], &mOptions[RSK_TOT_ALTAR_HINT], - &mOptions[RSK_LIGHT_ARROWS_HINT], + &mOptions[RSK_GANONDORF_HINT], + &mOptions[RSK_SHEIK_LA_HINT], &mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT], &mOptions[RSK_SARIA_HINT], @@ -1173,7 +1174,8 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Miscellaneous Settings:Hint Clarity", RSK_HINT_CLARITY }, { "Miscellaneous Settings:ToT Altar Hint", RSK_TOT_ALTAR_HINT }, - { "Miscellaneous Settings:Light Arrow Hint", RSK_LIGHT_ARROWS_HINT }, + { "Miscellaneous Settings:Ganondorf Hint", RSK_GANONDORF_HINT }, + { "Miscellaneous Settings:Sheik Light Arrow Hint", RSK_SHEIK_LA_HINT }, { "Miscellaneous Settings:Dampe's Diary Hint", RSK_DAMPES_DIARY_HINT }, { "Miscellaneous Settings:Greg the Rupee Hint", RSK_GREG_HINT }, { "Miscellaneous Settings:Saria's Hint", RSK_SARIA_HINT }, @@ -2280,7 +2282,8 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SUNLIGHT_ARROWS: case RSK_BOMBCHUS_IN_LOGIC: case RSK_TOT_ALTAR_HINT: - case RSK_LIGHT_ARROWS_HINT: + case RSK_GANONDORF_HINT: + case RSK_SHEIK_LA_HINT: case RSK_DAMPES_DIARY_HINT: case RSK_GREG_HINT: case RSK_SARIA_HINT: @@ -2644,7 +2647,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { ctx->AddExcludedOptions(); for (auto it = jsonExcludedLocations.begin(); it != jsonExcludedLocations.end(); ++it) { - const RandomizerCheck rc = StaticData::SpoilerfileCheckNameToEnum[it.value()]; + const RandomizerCheck rc = Rando::StaticData::locationNameToEnum[it.value()]; ctx->GetItemLocation(rc)->GetExcludedOption()->SetSelectedIndex(RO_GENERIC_ON); } diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp new file mode 100644 index 000000000..524ab4700 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -0,0 +1,307 @@ +#include +#include "static_data.h" +#include + +namespace Rando { + +std::unordered_map StaticData::hintTypeNames = { + {HINT_TYPE_HINT_KEY, CustomMessage("Message")}, + {HINT_TYPE_AREA, CustomMessage("Area")}, + {HINT_TYPE_ITEM, CustomMessage("Item")}, + {HINT_TYPE_TRIAL, CustomMessage("Trial")}, + {HINT_TYPE_ENTRANCE, CustomMessage("Entrance")}, + {HINT_TYPE_ITEM_AREA, CustomMessage("Item Area")}, + {HINT_TYPE_MERCHANT, CustomMessage("Merchant")}, + {HINT_TYPE_ALTAR_CHILD, CustomMessage("Child Altar")}, + {HINT_TYPE_ALTAR_ADULT, CustomMessage("Adult Altar")}, + {HINT_TYPE_WOTH, CustomMessage("Way of the Hero")}, + {HINT_TYPE_FOOLISH, CustomMessage("Foolish")}, + {HINT_TYPE_MESSAGE, CustomMessage("Hardcoded Message")} +}; + +//RANDOTODO When dynamic grotto check names are done, apply it to these hints +//RANDOTODO Translations +std::unordered_map StaticData::hintNames = { + {RH_NONE, CustomMessage("ERROR HINT")}, + {RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE, CustomMessage("KF Left Near Deku Gossip Stone")}, //RANDOTODO find cardinal direction + {RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, CustomMessage("KF Right Near Deku Gossip Stone")}, + {RH_KF_GOSSIP_STONE, CustomMessage("KF Gossip Stone")}, + {RH_KF_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("KF Storms Grotto Gossip Stone")}, + {RH_LW_GOSSIP_STONE, CustomMessage("LW Gossip Stone")}, + {RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, CustomMessage("LW Near Shortcuts Grotto Gossip Stone")}, + {RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE, CustomMessage("SFM Near LW Gossip Stone")}, + {RH_SFM_MAZE_CENTER_GOSSIP_STONE, CustomMessage("SFM Center Gossip Stone")}, + {RH_SFM_SARIA_GOSSIP_STONE, CustomMessage("SFM Near Saria Gossip Stone")}, + {RH_HF_COW_GROTTO_GOSSIP_STONE, CustomMessage("HF Cow Grotto Gossip Stone")}, + {RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, CustomMessage("HF Near Market Grotto Gossip Stone")}, + {RH_HF_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("HF Open Grotto Gossip Stone")}, + {RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, CustomMessage("HF Southeast Grotto Gossip Stone")}, + {RH_TOT_LEFT_CENTER_GOSSIP_STONE, CustomMessage("Market Left Center Gossip Stone")}, + {RH_TOT_LEFTMOST_GOSSIP_STONE, CustomMessage("Market Leftmost Center Gossip Stone")}, + {RH_TOT_RIGHT_CENTER_GOSSIP_STONE, CustomMessage("Market Right Center Gossip Stone")}, + {RH_TOT_RIGHTMOST_GOSSIP_STONE, CustomMessage("Market Rightmost Gossip Stone")}, + {RH_HC_MALON_GOSSIP_STONE, CustomMessage("HC Near Malon Gossip Stone")}, + {RH_HC_ROCK_WALL_GOSSIP_STONE, CustomMessage("HC Rock Wall Gossip Stone")}, + {RH_HC_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("HC Storm Grotto Gossip Stone")}, + {RH_KAK_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("Kak Open Grotto Gossip Stone")}, + {RH_GRAVEYARD_GOSSIP_STONE, CustomMessage("Graveyard Gossip Stone")}, + {RH_DMT_GOSSIP_STONE, CustomMessage("DMT Gossip Stone")}, + {RH_DMT_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("DMT Storms Grotto Gossip Stone")}, + {RH_GC_MAZE_GOSSIP_STONE, CustomMessage("GC Maze Gossip Stone")}, + {RH_GC_MEDIGORON_GOSSIP_STONE, CustomMessage("GC Medigoron Gossip Stone")}, + {RH_DMC_GOSSIP_STONE, CustomMessage("DMC Gossip Stone")}, + {RH_DMC_UPPER_GROTTO_GOSSIP_STONE, CustomMessage("DMC Upper Grotto Gossip Stone")}, + {RH_ZR_NEAR_DOMAIN_GOSSIP_STONE, CustomMessage("ZR Near Domain Gossip Stone")}, + {RH_ZR_NEAR_GROTTOS_GOSSIP_STONE, CustomMessage("ZR Near Grottos Gossip Stone")}, + {RH_ZR_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("ZR Open Grotto Gossip Stone")}, + {RH_ZD_GOSSIP_STONE, CustomMessage("ZD Gossip Stone")}, + {RH_ZF_JABU_GOSSIP_STONE, CustomMessage("ZF Near Jabu Gossip Stone")}, + {RH_ZF_FAIRY_GOSSIP_STONE, CustomMessage("ZF Near Fairy Gossip Stone")}, + {RH_LH_LAB_GOSSIP_STONE, CustomMessage("LH Near Lab Gossip Stone")}, + {RH_LH_SOUTHEAST_GOSSIP_STONE, CustomMessage("LH Southeast Gossip Stone")}, + {RH_LH_SOUTHWEST_GOSSIP_STONE, CustomMessage("LH Southwest Gossip Stone")}, + {RH_GV_GOSSIP_STONE, CustomMessage("Gerudo Valley Gossip Stone")}, + {RH_COLOSSUS_GOSSIP_STONE, CustomMessage("Desert Collosus Gossip Stone")}, + {RH_DODONGOS_CAVERN_GOSSIP_STONE, CustomMessage("Dodongo's Cavern Gossip Stone")}, + {RH_GANONDORF_HINT, CustomMessage("Ganondorf Hint")}, + {RH_GANONDORF_JOKE, CustomMessage("Ganondorf Joke")}, + {RH_SHEIK_HINT, CustomMessage("Sheik in Ganons Castle Hint")}, + {RH_DAMPES_DIARY, CustomMessage("Dampe's Diary Hint")}, + {RH_GREG_RUPEE, CustomMessage("Treasure Chest Game Greg Hint")}, + {RH_ALTAR_CHILD, CustomMessage("ToT Altar as Child")}, + {RH_ALTAR_ADULT, CustomMessage("ToT Altar as Adult")}, + {RH_SARIA_HINT, CustomMessage("Saria's Magic Hint")}, + {RH_FISHING_POLE, CustomMessage("Fishing Pole Hint")}, + {RH_MINUET_WARP_LOC, CustomMessage("Minuet of Forest Destination")}, + {RH_BOLERO_WARP_LOC, CustomMessage("Bolero of Fire Destination")}, + {RH_SERENADE_WARP_LOC, CustomMessage("Serenade of Water Destination")}, + {RH_REQUIEM_WARP_LOC, CustomMessage("Requiem of Spirit Destination")}, + {RH_NOCTURNE_WARP_LOC, CustomMessage("Nocturne of Shadow Destination")}, + {RH_PRELUDE_WARP_LOC, CustomMessage("Prelude of Light Destination")}, + {RH_MEDIGORON, CustomMessage("Medigoron Hint")}, + {RH_CARPET_SALESMAN, CustomMessage("Carpet Salseman Hint")}, + {RH_BEAN_SALESMAN, CustomMessage("Bean Salseman Hint")}, + {RH_GRANNY, CustomMessage("Granny Hint")}, + {RH_HBA_HINT, CustomMessage("Horseback Archery Hint")}, + {RH_MALON_HINT, CustomMessage("Malon Hint")}, + {RH_CHICKENS_HINT, CustomMessage("Anju's Child Chickens Hint")}, + {RH_BIG_POES_HINT, CustomMessage("Big Poe Reward Hint")}, + {RH_BIGGORON_HINT, CustomMessage("Biggoron Claim Check Hint")}, + {RH_FROGS_HINT, CustomMessage("Final Frogs in River Hint")}, + {RH_KAK_10_SKULLS_HINT, CustomMessage("10 Skulls Hint")}, + {RH_KAK_20_SKULLS_HINT, CustomMessage("20 Skulls Hint")}, + {RH_KAK_30_SKULLS_HINT, CustomMessage("30 Skulls Hint")}, + {RH_KAK_40_SKULLS_HINT, CustomMessage("40 Skulls Hint")}, + {RH_KAK_50_SKULLS_HINT, CustomMessage("50 Skulls Hint")}, + {RH_KAK_100_SKULLS_HINT, CustomMessage("100 Skulls Hint")} +}; + +std::unordered_map StaticData::gossipStoneCheckToHint { + {RC_COLOSSUS_GOSSIP_STONE, RH_COLOSSUS_GOSSIP_STONE}, + {RC_DMC_GOSSIP_STONE, RH_DMC_GOSSIP_STONE}, + {RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RH_DMC_UPPER_GROTTO_GOSSIP_STONE}, + {RC_DMT_GOSSIP_STONE, RH_DMT_GOSSIP_STONE}, + {RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RH_DMT_STORMS_GROTTO_GOSSIP_STONE}, + {RC_DODONGOS_CAVERN_GOSSIP_STONE, RH_DODONGOS_CAVERN_GOSSIP_STONE}, + {RC_ZF_FAIRY_GOSSIP_STONE, RH_ZF_FAIRY_GOSSIP_STONE}, + {RC_GC_MAZE_GOSSIP_STONE, RH_GC_MAZE_GOSSIP_STONE}, + {RC_GC_MEDIGORON_GOSSIP_STONE, RH_GC_MEDIGORON_GOSSIP_STONE}, + {RC_GV_GOSSIP_STONE, RH_GV_GOSSIP_STONE}, + {RC_GRAVEYARD_GOSSIP_STONE, RH_GRAVEYARD_GOSSIP_STONE}, + {RC_HC_MALON_GOSSIP_STONE, RH_HC_MALON_GOSSIP_STONE}, + {RC_HC_ROCK_WALL_GOSSIP_STONE, RH_HC_ROCK_WALL_GOSSIP_STONE}, + {RC_HC_STORMS_GROTTO_GOSSIP_STONE, RH_HC_STORMS_GROTTO_GOSSIP_STONE}, + {RC_HF_COW_GROTTO_GOSSIP_STONE, RH_HF_COW_GROTTO_GOSSIP_STONE}, + {RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE}, + {RC_HF_OPEN_GROTTO_GOSSIP_STONE, RH_HF_OPEN_GROTTO_GOSSIP_STONE}, + {RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE}, + {RC_ZF_JABU_GOSSIP_STONE, RH_ZF_JABU_GOSSIP_STONE}, + {RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE}, + {RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE}, + {RC_KF_GOSSIP_STONE, RH_KF_GOSSIP_STONE}, + {RC_KF_STORMS_GROTTO_GOSSIP_STONE, RH_KF_STORMS_GROTTO_GOSSIP_STONE}, + {RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RH_KAK_OPEN_GROTTO_GOSSIP_STONE}, + {RC_LH_LAB_GOSSIP_STONE, RH_LH_LAB_GOSSIP_STONE}, + {RC_LH_SOUTHEAST_GOSSIP_STONE, RH_LH_SOUTHEAST_GOSSIP_STONE}, + {RC_LH_SOUTHWEST_GOSSIP_STONE, RH_LH_SOUTHWEST_GOSSIP_STONE}, + {RC_LW_GOSSIP_STONE, RH_LW_GOSSIP_STONE}, + {RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE}, + {RC_SFM_MAZE_LOWER_GOSSIP_STONE, RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE}, + {RC_SFM_MAZE_UPPER_GOSSIP_STONE, RH_SFM_MAZE_CENTER_GOSSIP_STONE}, + {RC_SFM_SARIA_GOSSIP_STONE, RH_SFM_SARIA_GOSSIP_STONE}, + {RC_TOT_LEFT_CENTER_GOSSIP_STONE, RH_TOT_LEFT_CENTER_GOSSIP_STONE}, + {RC_TOT_LEFTMOST_GOSSIP_STONE, RH_TOT_LEFTMOST_GOSSIP_STONE}, + {RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RH_TOT_RIGHT_CENTER_GOSSIP_STONE}, + {RC_TOT_RIGHTMOST_GOSSIP_STONE, RH_TOT_RIGHTMOST_GOSSIP_STONE}, + {RC_ZD_GOSSIP_STONE, RH_ZD_GOSSIP_STONE}, + {RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RH_ZR_NEAR_DOMAIN_GOSSIP_STONE}, + {RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RH_ZR_NEAR_GROTTOS_GOSSIP_STONE}, + {RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RH_ZR_OPEN_GROTTO_GOSSIP_STONE} +}; + +std::unordered_map StaticData::areaNames = { //RANDOTODO resolve None in area + {RA_NONE, RHT_LINKS_POCKET}, //explicit none in area hints usually means it's a starting item, so say Link's pocket + {RA_LINKS_POCKET, RHT_LINKS_POCKET}, + {RA_KOKIRI_FOREST, RHT_KOKIRI_FOREST}, + {RA_THE_LOST_WOODS, RHT_THE_LOST_WOODS}, + {RA_SACRED_FOREST_MEADOW, RHT_SACRED_FOREST_MEADOW}, + {RA_HYRULE_FIELD, RHT_HYRULE_FIELD}, + {RA_LAKE_HYLIA, RHT_LAKE_HYLIA}, + {RA_GERUDO_VALLEY, RHT_GERUDO_VALLEY}, + {RA_GERUDO_FORTRESS, RHT_GERUDO_FORTRESS}, + {RA_HAUNTED_WASTELAND, RHT_HAUNTED_WASTELAND}, + {RA_DESERT_COLOSSUS, RHT_DESERT_COLOSSUS}, + {RA_THE_MARKET, RHT_THE_MARKET}, + {RA_TEMPLE_OF_TIME, RHT_TEMPLE_OF_TIME}, + {RA_HYRULE_CASTLE, RHT_HYRULE_CASTLE}, + {RA_OUTSIDE_GANONS_CASTLE, RHT_OUTSIDE_GANONS_CASTLE}, + {RA_CASTLE_GROUNDS, RHT_CASTLE_GROUNDS}, + {RA_KAKARIKO_VILLAGE, RHT_KAKARIKO_VILLAGE}, + {RA_THE_GRAVEYARD, RHT_THE_GRAVEYARD}, + {RA_DEATH_MOUNTAIN_TRAIL, RHT_DEATH_MOUNTAIN_TRAIL}, + {RA_GORON_CITY, RHT_GORON_CITY}, + {RA_DEATH_MOUNTAIN_CRATER, RHT_DEATH_MOUNTAIN_CRATER}, + {RA_ZORAS_RIVER, RHT_ZORAS_RIVER}, + {RA_ZORAS_DOMAIN, RHT_ZORAS_DOMAIN}, + {RA_ZORAS_FOUNTAIN, RHT_ZORAS_FOUNTAIN}, + {RA_LON_LON_RANCH, RHT_LON_LON_RANCH}, + {RA_DEKU_TREE, RHT_DEKU_TREE}, + {RA_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN}, + {RA_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY}, + {RA_FOREST_TEMPLE, RHT_FOREST_TEMPLE}, + {RA_FIRE_TEMPLE, RHT_FIRE_TEMPLE}, + {RA_WATER_TEMPLE, RHT_WATER_TEMPLE}, + {RA_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE}, + {RA_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE}, + {RA_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL}, + {RA_ICE_CAVERN, RHT_ICE_CAVERN}, + {RA_GERUDO_TRAINING_GROUND, RHT_GERUDO_TRAINING_GROUND}, + {RA_GANONS_CASTLE, RHT_GANONS_CASTLE} +}; + +std::unordered_map StaticData::trialData = { + {TK_LIGHT_TRIAL, RHT_LIGHT_TRIAL}, + {TK_FOREST_TRIAL, RHT_FOREST_TRIAL}, + {TK_FIRE_TRIAL, RHT_FIRE_TRIAL}, + {TK_WATER_TRIAL, RHT_WATER_TRIAL}, + {TK_SHADOW_TRIAL, RHT_SHADOW_TRIAL}, + {TK_SPIRIT_TRIAL, RHT_SPIRIT_TRIAL} +}; + +std::unordered_map StaticData::staticHintInfoMap = { + // RH_GANONDORF_HINT is special cased due to being different based on master sword shuffle + // Altar hints are special cased due to special hint marking rules + // warp song hints are special cased due to entrences not being done properly yet + // Ganondorf Joke is special Cased as the text is random + {RH_SHEIK_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_SHEIK_HINT_LA_ONLY}, RSK_SHEIK_LA_HINT, true, {}, {RG_LIGHT_ARROWS}, {RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC}, true)}, + {RH_DAMPES_DIARY, StaticHintInfo(HINT_TYPE_AREA, {RHT_DAMPE_DIARY}, RSK_DAMPES_DIARY_HINT, true, {}, {RG_PROGRESSIVE_HOOKSHOT}, {RC_DAMPE_HINT})}, + {RH_GREG_RUPEE, StaticHintInfo(HINT_TYPE_AREA, {RHT_GREG_HINT}, RSK_GREG_HINT, true, {}, {RG_GREG_RUPEE}, {RC_GREG_HINT})}, + {RH_SARIA_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT}, RSK_SARIA_HINT, true, {}, {RG_PROGRESSIVE_MAGIC_METER}, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, true)}, + {RH_FISHING_POLE, StaticHintInfo(HINT_TYPE_AREA, {RHT_FISHING_POLE_HINT}, RSK_FISHING_POLE_HINT, true, {}, {RG_FISHING_POLE}, {RC_FISHING_POLE_HINT}, true)}, + {RH_MEDIGORON, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_MEDIGORON_HINT}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_GC_MEDIGORON})}, + {RH_GRANNY, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_GRANNY_HINT}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_KAK_GRANNYS_SHOP})}, + {RH_CARPET_SALESMAN, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_CARPET_SALESMAN_DIALOG_HINTED}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_WASTELAND_BOMBCHU_SALESMAN})}, + {RH_BEAN_SALESMAN, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_BEAN_SALESMAN_HINT}, RSK_SHUFFLE_MAGIC_BEANS, true, {RC_ZR_MAGIC_BEAN_SALESMAN})}, + {RH_HBA_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_HBA_HINT_SIGN, RHT_HBA_HINT_NOT_ON_HORSE, RHT_HBA_HINT_INITIAL, RHT_HBA_HINT_HAVE_1000}, RSK_HBA_HINT, true, {RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS})}, + {RH_MALON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MALON_HINT_TURNING_EVIL, RHT_MALON_HINT_HOW_IS_EPONA, RHT_MALON_HINT_OBSTICLE_COURSE, RHT_MALON_HINT_INGO_TEMPTED},RSK_MALON_HINT, true, {RC_KF_LINKS_HOUSE_COW})}, + {RH_BIG_POES_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIG_POES_HINT}, RSK_BIG_POES_HINT, true, {RC_MARKET_10_BIG_POES})}, + {RH_CHICKENS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_CHICKENS_HINT}, RSK_CHICKENS_HINT, true, {RC_KAK_ANJU_AS_CHILD})}, + {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK})}, + {RH_FROGS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_FROGS_HINT}, RSK_FROGS_HINT, true, {RC_ZR_FROGS_OCARINA_GAME})}, + {RH_KAK_10_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_10_SKULLS_HINT, true, {RC_KAK_10_GOLD_SKULLTULA_REWARD}, {}, {}, false, 10)}, + {RH_KAK_20_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_20_SKULLS_HINT, true, {RC_KAK_20_GOLD_SKULLTULA_REWARD}, {}, {}, false, 20)}, + {RH_KAK_30_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_30_SKULLS_HINT, true, {RC_KAK_30_GOLD_SKULLTULA_REWARD}, {}, {}, false, 30)}, + {RH_KAK_40_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_40_SKULLS_HINT, true, {RC_KAK_40_GOLD_SKULLTULA_REWARD}, {}, {}, false, 40)}, + {RH_KAK_50_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_50_SKULLS_HINT, true, {RC_KAK_50_GOLD_SKULLTULA_REWARD}, {}, {}, false, 50)}, + {RH_KAK_100_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_100_SKULLS_HINT, true, {RC_KAK_100_GOLD_SKULLTULA_REWARD}, {}, {}, false, 100)} +}; + +std::unordered_map StaticData::PopulateTranslationMap(std::unordered_map input){ + std::unordered_map output = {}; + for (const auto& [key, message] : input) { + std::vector strings = message.GetAllMessages(); + for (std::string string: strings){ + if (output.contains(string)){ + if (output[string] != key){ + SPDLOG_DEBUG("\tREPEATED STRING IN " + message.GetEnglish(MF_CLEAN) + "\n\n"); //RANDOTODO should this cause an error of some kind? + } + } else { + output[string] = key; + } + } + } + return output; +} + +std::unordered_map StaticData::PopulateTranslationMap(std::unordered_map input){ + std::unordered_map output = {}; + for (const auto& [key, text] : input) { + std::vector strings = hintTextTable[text].GetClear().GetAllMessages(); + for (std::string string: strings){ + if (output.contains(string)){ + if (output[string] != key){ + SPDLOG_DEBUG("\tREPEATED STRING WITH " + string + "\n\n"); //RANDOTODO should this cause an error of some kind? + } + } else { + output[string] = key; + } + } + } + return output; +} + +std::unordered_map StaticData::hintNameToEnum = {}; +std::unordered_map StaticData::hintTypeNameToEnum = {}; +std::unordered_map StaticData::areaNameToEnum = {}; +std::unordered_map StaticData::trialNameToEnum = {}; +std::unordered_map StaticData::locationNameToEnum = {}; //is filled in context based on location table, not touching that because of VB + +std::unordered_map StaticData::stoneParamsToHint{ + {0x1, RH_ZF_FAIRY_GOSSIP_STONE}, + {0x2, RH_ZF_JABU_GOSSIP_STONE}, + {0x3, RH_LH_LAB_GOSSIP_STONE}, + {0x4, RH_DMT_GOSSIP_STONE}, + {0x5, RH_DMC_GOSSIP_STONE}, + {0x6, RH_TOT_LEFTMOST_GOSSIP_STONE}, + {0x7, RH_TOT_LEFT_CENTER_GOSSIP_STONE}, + {0x8, RH_LH_SOUTHWEST_GOSSIP_STONE}, + {0x9, RH_ZD_GOSSIP_STONE}, + {0xA, RH_GRAVEYARD_GOSSIP_STONE}, + {0xB, RH_HC_ROCK_WALL_GOSSIP_STONE}, + {0xC, RH_ZR_NEAR_DOMAIN_GOSSIP_STONE}, + {0xD, RH_ZR_NEAR_GROTTOS_GOSSIP_STONE}, + {0xE, RH_TOT_RIGHT_CENTER_GOSSIP_STONE }, + {0xF, RH_LH_SOUTHEAST_GOSSIP_STONE}, + {0x10, RH_TOT_RIGHTMOST_GOSSIP_STONE }, + {0x11, RH_GV_GOSSIP_STONE}, + {0x12, RH_HC_MALON_GOSSIP_STONE}, + {0x13, RH_HC_STORMS_GROTTO_GOSSIP_STONE}, + {0x14, RH_DODONGOS_CAVERN_GOSSIP_STONE}, + {0x15, RH_GC_MAZE_GOSSIP_STONE}, + {0x16, RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE}, + {0x17, RH_SFM_MAZE_CENTER_GOSSIP_STONE}, + //generic grottos all use 0x18, grottoChestParamsToHint is used for conversion + {0x19, RH_GC_MEDIGORON_GOSSIP_STONE}, + {0x1A, RH_COLOSSUS_GOSSIP_STONE}, + {0x1B, RH_HF_COW_GROTTO_GOSSIP_STONE}, + {0x1C, RH_SFM_SARIA_GOSSIP_STONE}, + {0x1D, RH_LW_GOSSIP_STONE}, + {0x1E, RH_KF_GOSSIP_STONE}, + {0x1F, RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE}, + {0x20, RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE}, +}; + +std::unordered_map StaticData::grottoChestParamsToHint{ + {22944, RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE}, + {22978, RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE}, + {22947, RH_HF_OPEN_GROTTO_GOSSIP_STONE}, + {22964, RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE}, + {23255, RH_DMT_STORMS_GROTTO_GOSSIP_STONE}, + {22984, RH_KAK_OPEN_GROTTO_GOSSIP_STONE}, + {22985, RH_ZR_OPEN_GROTTO_GOSSIP_STONE}, + {23802, RH_DMC_UPPER_GROTTO_GOSSIP_STONE}, + {22988, RH_KF_STORMS_GROTTO_GOSSIP_STONE} +}; + +std::array StaticData::hintTextTable = {}; +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index 0e5ba4c03..44e1ff1ff 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -22,25 +22,47 @@ class StaticData { public: static void InitItemTable(); + static void HintTable_Init(); + static void HintTable_Init_Item(); + static void HintTable_Init_Exclude_Overworld(); + static void HintTable_Init_Exclude_Dungeon(); static Item& RetrieveItem(const RandomizerGet rgid); static Item& ItemFromGIID(const int giid); - static std::array& GetItemTable(); + static std::array& GetItemTable();// is there a reason this is a function and not just an exposed table? static void InitLocationTable(); static Location* GetLocation(RandomizerCheck locKey); static std::array& GetLocationTable(); - static std::unordered_map SpoilerfileCheckNameToEnum; - static std::unordered_map SpoilerfileItemNameToEnum; + static std::unordered_map PopulateTranslationMap(std::unordered_map input); + static std::unordered_map PopulateTranslationMap(std::unordered_map input); static std::multimap, RandomizerCheck> CheckFromActorMultimap; static std::vector overworldLocations; static std::vector dungeonRewardLocations; static std::vector> shopLocationLists; static std::vector scrubLocations; static std::vector gossipStoneLocations; - static std::vector otherHintLocations; + static std::vector staticHintLocations; static std::vector pondFishLocations; static std::vector overworldFishLocations; static std::array, 17> randomizerFishingPondFish; static std::unordered_map randomizerGrottoFishMap; + static std::vector oldVerHintOrder; + static uint16_t oldVerGossipStoneStart; + static std::unordered_map locationNameToEnum; + static std::unordered_map itemNameToEnum; + static std::unordered_map hintNames; + static std::unordered_map hintNameToEnum; + static std::unordered_map hintTypeNames; + static std::unordered_map hintTypeNameToEnum; + static std::unordered_map gossipStoneCheckToHint; + static std::unordered_map areaNames; + static std::unordered_map areaNameToEnum; + static std::unordered_map trialData; + static std::unordered_map trialNameToEnum; + static std::unordered_map staticHintInfoMap; + static std::unordered_map stoneParamsToHint; + static std::unordered_map grottoChestParamsToHint; + static std::array hintTextTable; + StaticData(); ~StaticData(); }; diff --git a/soh/soh/Enhancements/randomizer/trial.cpp b/soh/soh/Enhancements/randomizer/trial.cpp index d3fc99951..1110d37d8 100644 --- a/soh/soh/Enhancements/randomizer/trial.cpp +++ b/soh/soh/Enhancements/randomizer/trial.cpp @@ -1,12 +1,21 @@ #include "trial.h" +#include "static_data.h" namespace Rando { -TrialInfo::TrialInfo(Text name_) : name(std::move(name_)) {} +TrialInfo::TrialInfo(RandomizerHintTextKey nameKey_, TrialKey trialKey_) : nameKey(std::move(nameKey_)), trialKey(std::move(trialKey_)) {} TrialInfo::TrialInfo() = default; TrialInfo::~TrialInfo() = default; -Text TrialInfo::GetName() const { - return name; +CustomMessage TrialInfo::GetName() const { + return StaticData::hintTextTable[nameKey].GetHintMessage(); +} + +RandomizerHintTextKey TrialInfo::GetNameKey() const { + return nameKey; +} + +TrialKey TrialInfo::GetTrialKey() const { + return trialKey; } bool TrialInfo::IsSkipped() const { @@ -26,12 +35,9 @@ void TrialInfo::SetAsSkipped() { } Trials::Trials() { - mTrials[FOREST_TRIAL] = TrialInfo(Text{"the Forest Trial", "l'épreuve de la Forêt", "la prueba del bosque"}); - mTrials[FIRE_TRIAL] = TrialInfo(Text{"the Fire Trial", "l'épreuve du Feu", "la prueba del fuego"}); - mTrials[WATER_TRIAL] = TrialInfo(Text{"the Water Trial", "l'épreuve de l'Eau", "la prueba del agua"}); - mTrials[SPIRIT_TRIAL] = TrialInfo(Text{"the Spirit Trial", "l'épreuve de l'Esprit", "la prueba del espíritu"}); - mTrials[SHADOW_TRIAL] = TrialInfo(Text{"the Shadow Trial", "l'épreuve de l'Ombre", "la prueba de las sombras"}); - mTrials[LIGHT_TRIAL] = TrialInfo(Text{"the Light Trial", "l'épreuve de la Lumière", "la prueba de la luz"}); + for (const auto trial : StaticData::trialData){ + mTrials[trial.first] = TrialInfo(trial.second, static_cast(trial.first)); + } } Trials::~Trials() = default; @@ -51,10 +57,10 @@ void Trials::RequireAll() { } } -std::array Trials::GetTrialList() { - std::array trialList{}; +std::vector Trials::GetTrialList() { + std::vector trialList{}; for (size_t i = 0; i < mTrials.size(); i++) { - trialList[i] = &mTrials[i]; + trialList.push_back(&mTrials[i]); } return trialList; } @@ -62,6 +68,7 @@ std::array Trials::GetTrialList() { size_t Trials::GetTrialListSize() const { return mTrials.size(); } + void Trials::ParseJson(nlohmann::json spoilerFileJson) { nlohmann::json trialsJson = spoilerFileJson["requiredTrials"]; for (auto it = trialsJson.begin(); it != trialsJson.end(); ++it) { @@ -75,4 +82,13 @@ void Trials::ParseJson(nlohmann::json spoilerFileJson) { } } } + +std::unordered_map Trials::GetAllTrialHintHeys() const { + std::unordered_map output = {}; + for (auto trial: mTrials){ + output[(uint32_t)trial.GetTrialKey()] = trial.GetNameKey(); + } + return output; +} + } // namespace Rando \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/trial.h b/soh/soh/Enhancements/randomizer/trial.h index 9e282f45d..2cc483898 100644 --- a/soh/soh/Enhancements/randomizer/trial.h +++ b/soh/soh/Enhancements/randomizer/trial.h @@ -1,36 +1,31 @@ #pragma once -#include "3drando/text.hpp" - -#include +#include "randomizerTypes.h" +#include "../custom-message/CustomMessageManager.h" #include +#include "static_data.h" +#include namespace Rando { class TrialInfo { public: - explicit TrialInfo(Text name_); + explicit TrialInfo(RandomizerHintTextKey nameKey_, TrialKey key_); TrialInfo(); ~TrialInfo(); - Text GetName() const; + CustomMessage GetName() const; + RandomizerHintTextKey GetNameKey() const; + TrialKey GetTrialKey() const; bool IsSkipped() const; bool IsRequired() const; void SetAsRequired(); void SetAsSkipped(); private: - Text name; + RandomizerHintTextKey nameKey; + TrialKey trialKey; bool skipped = true; }; -typedef enum { - LIGHT_TRIAL, - FOREST_TRIAL, - FIRE_TRIAL, - WATER_TRIAL, - SPIRIT_TRIAL, - SHADOW_TRIAL, -} TrialKey; - class Trials { public: Trials(); @@ -38,10 +33,11 @@ class Trials { TrialInfo* GetTrial(TrialKey key); void SkipAll(); void RequireAll(); - std::array GetTrialList(); + std::vector GetTrialList(); size_t GetTrialListSize() const; void ParseJson(nlohmann::json spoilerFileJson); + std::unordered_map GetAllTrialHintHeys() const; private: - std::array mTrials; + std::array mTrials; }; } \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2222d0007..f8c292b59 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -348,8 +348,9 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast(SOH::ResourceType::SOH_RawJson), 0); gSaveStateMgr = std::make_shared(); - gRandoContext = Rando::Context::CreateInstance(); gRandoContext->InitStaticData(); + gRandoContext = Rando::Context::CreateInstance(); + Rando::StaticData::InitItemTable();//RANDOTODO make this not rely on context's logic so it can be initialised in InitStaticData gRandoContext->AddExcludedOptions(); gRandoContext->GetSettings()->CreateOptions(); gRandomizer = std::make_shared(); @@ -2245,8 +2246,8 @@ extern "C" float OTRGetDimensionFromRightEdge(float v) { return (SCREEN_WIDTH / 2 + SCREEN_HEIGHT / 2 * OTRGetAspectRatio() - (SCREEN_WIDTH - v)); } -f32 floorf(f32 x); -f32 ceilf(f32 x); +f32 floorf(f32 x);// RANDOTODO False positive error "allowing all exceptions is incompatible with previous function" +f32 ceilf(f32 x); // This gets annoying extern "C" int16_t OTRGetRectDimensionFromLeftEdge(float v) { return ((int)floorf(OTRGetDimensionFromLeftEdge(v))); @@ -2316,15 +2317,7 @@ extern "C" int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSi "%w\x02"); customMessage.Format(); - std::string postfix; - - if (gSaveContext.language == LANGUAGE_FRA) { - postfix = customMessage.GetFrench(); - } else if (gSaveContext.language == LANGUAGE_GER) { - postfix = customMessage.GetGerman(); - } else { - postfix = customMessage.GetEnglish(); - } + std::string postfix = customMessage.GetForCurrentLanguage(); std::string str; std::string FixedBaseStr(src); int RemoveControlChar = FixedBaseStr.find_first_of("\x02"); @@ -2478,6 +2471,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { CustomMessage messageEntry; s16 actorParams = 0; if (IS_RANDO) { + auto ctx = Rando::Context::GetInstance(); Player* player = GET_PLAYER(play); if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) { if (player->getItemEntry.getItemId == RG_ICE_TRAP) { @@ -2526,39 +2520,45 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { Actor* stone = GET_PLAYER(play)->targetActor; - actorParams = stone->params; - - // if we're in a generic grotto - if (play->sceneNum == SCENE_GROTTOS && actorParams == 14360) { + RandomizerHint stoneHint = RH_NONE; + s16 hintParams = stone->params & 0xFF; + + if (Rando::StaticData::stoneParamsToHint.contains(hintParams)){ + stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; + } else if (hintParams == 0x18){ // look for the chest in the actorlist to determine // which grotto we're in int numOfActorLists = sizeof(play->actorCtx.actorLists) / sizeof(play->actorCtx.actorLists[0]); for (int i = 0; i < numOfActorLists; i++) { if (play->actorCtx.actorLists[i].length) { - if (play->actorCtx.actorLists[i].head->id == 10) { - // set the params for the hint check to be negative chest params - actorParams = 0 - play->actorCtx.actorLists[i].head->params; + if (play->actorCtx.actorLists[i].head->id == 10 && + Rando::StaticData::grottoChestParamsToHint.contains(play->actorCtx.actorLists[i].head->params)) { + //use the chest params to find the stone hint + stoneHint = Rando::StaticData::grottoChestParamsToHint[play->actorCtx.actorLists[i].head->params]; } } } } - - RandomizerCheck hintCheck = - Randomizer_GetCheckFromActor(stone->id, play->sceneNum, actorParams); - - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, hintCheck); + if (stoneHint == RH_NONE){ + messageEntry = CustomMessage("INVALID STONE. PARAMS: " + std::to_string(hintParams)); + } else { + messageEntry = ctx->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); + } } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar - messageEntry = (LINK_IS_ADULT) - ? CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT) - : CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD); + messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); } else if (textId == TEXT_GANONDORF) { - if ((INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) || - !Randomizer_GetSettingValue(RSK_LIGHT_ARROWS_HINT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT); - } else { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF); + if (ctx->GetOption(RSK_GANONDORF_HINT)){ + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)){ + messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT ? + ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1): + ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); + } else { + messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT ? + ctx->GetHint(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT): + ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } } } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); @@ -2585,74 +2585,131 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (CVarGetInteger("gRandoRelevantNavi", 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); - } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10); - } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && (textId == TEXT_MEDIGORON || - (textId == TEXT_GRANNYS_SHOP && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) || - (textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) || - (textId == TEXT_CARPET_SALESMAN_2 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)))) { + } + else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_10 && ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) { + messageEntry = ctx->GetHint(RH_BEAN_SALESMAN)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100); + } + else if (textId == TEXT_GRANNYS_SHOP && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)){ + messageEntry = messageEntry = ctx->GetHint(RH_GRANNY)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_MEDIGORON && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF){ + messageEntry = messageEntry = ctx->GetHint(RH_MEDIGORON)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_CARPET_SALESMAN_1 && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF){ + messageEntry = messageEntry = ctx->GetHint(RH_CARPET_SALESMAN)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_CARPET_SALESMAN_2 && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF){ messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId); - } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && - (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { + } + else if ((textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT) + && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); - } else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { + } + else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { actorParams = GET_PLAYER(play)->targetActor->params; - RandomizerSettingKey rsk = (RandomizerSettingKey)(RSK_KAK_10_SKULLS_HINT + (actorParams - 1)); - if (Randomizer_GetSettingValue(rsk)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(actorParams, - OTRGlobals::Instance->gRandomizer->GetCheckFromActor(ACTOR_EN_SSH, SCENE_HOUSE_OF_SKULLTULA, actorParams)); + if (actorParams == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ + messageEntry = ctx->GetHint(RH_KAK_10_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (actorParams == 2 && ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){ + messageEntry = ctx->GetHint(RH_KAK_20_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (actorParams == 3 && ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){ + messageEntry = ctx->GetHint(RH_KAK_30_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (actorParams == 4 && ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){ + messageEntry = ctx->GetHint(RH_KAK_40_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){ + messageEntry = ctx->GetHint(RH_KAK_50_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); } - } else if (Randomizer_GetSettingValue(RSK_DAMPES_DIARY_HINT) && textId == TEXT_DAMPES_DIARY) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY); - } else if (play->sceneNum == SCENE_TREASURE_BOX_SHOP && - Randomizer_GetSettingValue(RSK_GREG_HINT) && - (textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || textId == TEXT_CHEST_GAME_THANKS_A_LOT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED); - } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) && - (textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textId); - } else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { + } else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { + messageEntry = ctx->GetHint(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); + } + else if ((textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || textId == TEXT_CHEST_GAME_THANKS_A_LOT) && + play->sceneNum == SCENE_TREASURE_BOX_SHOP && ctx->GetOption(RSK_GREG_HINT)) { + messageEntry = ctx->GetHint(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_WARP_MINUET_OF_FOREST && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_MINUET_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId == TEXT_WARP_BOLERO_OF_FIRE && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId == TEXT_WARP_SERENADE_OF_WATER && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId == TEXT_WARP_REQUIEM_OF_SPIRIT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId == TEXT_WARP_NOCTURNE_OF_SHADOW && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId == TEXT_WARP_PRELUDE_OF_LIGHT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { + messageEntry = ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_FORMATTED); + } + else if (textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT + && ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST); + } + else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId); - } else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { + } + else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW); - } else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { + } + else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); - } else if (Randomizer_GetSettingValue(RSK_FROGS_HINT) && textId == TEXT_FROGS_UNDERWATER) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_FROGS_UNDERWATER, RC_ZR_FROGS_OCARINA_GAME); - } else if (Randomizer_GetSettingValue(RSK_FISHING_POLE_HINT) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND) && - (textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET)) { + } + else if (textId == TEXT_FROGS_UNDERWATER && ctx->GetOption(RSK_FROGS_HINT)) { + messageEntry = ctx->GetHint(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT), TEXTBOX_TYPE_BLUE; + } + else if ((textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET) && + ctx->GetOption(RSK_SHUFFLE_FISHING_POLE) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { messageEntry = OTRGlobals::Instance->gRandomizer->GetFishingPondOwnerMessage(textId); - } else if (Randomizer_GetSettingValue(RSK_SARIA_HINT) && - (gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId); - } else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100); - } else if (Randomizer_GetSettingValue(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_BIGGORON_BETTER_AT_SMITHING, RC_DMT_TRADE_CLAIM_CHECK); - } else if (Randomizer_GetSettingValue(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_GHOST_SHOP_CARD_HAS_POINTS, RC_MARKET_10_BIG_POES); - } else if (Randomizer_GetSettingValue(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RC_KAK_ANJU_AS_CHILD); - } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && (textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_EVERYONE_TURNING_EVIL, RC_KF_LINKS_HOUSE_COW); - } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_HOW_IS_EPONA_DOING) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_HOW_IS_EPONA_DOING, RC_KF_LINKS_HOUSE_COW); - } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_OBSTICLE_COURSE) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_OBSTICLE_COURSE, RC_KF_LINKS_HOUSE_COW); - } else if (Randomizer_GetSettingValue(RSK_MALON_HINT) && textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RC_KF_LINKS_HOUSE_COW); - } else if (Randomizer_GetSettingValue(RSK_KAK_100_SKULLS_HINT) && textId == TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(10, RC_KAK_100_GOLD_SKULLTULA_REWARD); - } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_GF_HBA_SIGN) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_GF_HBA_SIGN, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); - } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_NOT_ON_HORSE) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_NOT_ON_HORSE, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); - } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_INITIAL_EXPLAINATION) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_INITIAL_EXPLAINATION, RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS); - } else if (Randomizer_GetSettingValue(RSK_HBA_HINT) && textId == TEXT_HBA_ALREADY_HAVE_1000) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_HBA_ALREADY_HAVE_1000, RC_GF_HBA_1500_POINTS); + } + else if (textId == TEXT_SARIA_SFM && gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && ctx->GetOption(RSK_SARIA_HINT)){ + messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } + else if ((textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER) && ctx->GetOption(RSK_SARIA_HINT)){ + messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } + else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || + textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { + messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { + messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { + messageEntry = ctx->GetHint(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)&& ctx->GetOption(RSK_MALON_HINT)){ + messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } + else if (textId == TEXT_MALON_HOW_IS_EPONA_DOING && ctx->GetOption(RSK_MALON_HINT)){ + messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } + else if (textId == TEXT_MALON_OBSTICLE_COURSE && ctx->GetOption(RSK_MALON_HINT)){ + messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); + } + else if (textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED && ctx->GetOption(RSK_MALON_HINT)){ + messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); + } + else if (ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && textId == TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH) { + messageEntry = ctx->GetHint(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { + messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } + else if (textId == TEXT_HBA_NOT_ON_HORSE && ctx->GetOption(RSK_HBA_HINT)) { + messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } + else if (textId == TEXT_HBA_INITIAL_EXPLAINATION && ctx->GetOption(RSK_HBA_HINT)) { + messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); + } + else if (textId == TEXT_HBA_ALREADY_HAVE_1000 && ctx->GetOption(RSK_HBA_HINT)) { + messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { @@ -2674,16 +2731,16 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { // In rando we need to bump the token count by one to show the correct count s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); - messageEntry.Replace("{{gsCount}}", std::to_string(gsCount)); + messageEntry.Replace("[[gsCount]]", std::to_string(gsCount)); } } if (textId == TEXT_HEART_CONTAINER && CVarGetInteger("gInjectItemCounts", 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER); - messageEntry.Replace("{{heartContainerCount}}", std::to_string(gSaveContext.sohStats.heartContainers + 1)); + messageEntry.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.sohStats.heartContainers + 1)); } if (textId == TEXT_HEART_PIECE && CVarGetInteger("gInjectItemCounts", 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE); - messageEntry.Replace("{{heartPieceCount}}", std::to_string(gSaveContext.sohStats.heartPieces + 1)); + messageEntry.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.sohStats.heartPieces + 1)); } if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT); @@ -2695,14 +2752,14 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { switch (gSaveContext.language) { case LANGUAGE_FRA: return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetFrench(), buffer, maxBufferSize); + CopyStringToCharBuffer(messageEntry.GetFrench(MF_RAW), buffer, maxBufferSize); case LANGUAGE_GER: return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetGerman(), buffer, maxBufferSize); + CopyStringToCharBuffer(messageEntry.GetGerman(MF_RAW), buffer, maxBufferSize); case LANGUAGE_ENG: default: return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetEnglish(), buffer, maxBufferSize); + CopyStringToCharBuffer(messageEntry.GetEnglish(MF_RAW), buffer, maxBufferSize); } return false; } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 598a51139..a164c8a3d 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -6,6 +6,8 @@ #include "Enhancements/randomizer/dungeon.h" #include "Enhancements/randomizer/trial.h" #include "soh/util.h" +#include "Enhancements/randomizer/hint.h" +#include "Enhancements/randomizer/item.h" #include "z64.h" #include "functions.h" @@ -57,6 +59,51 @@ std::filesystem::path SaveManager::GetFileTempName(int fileNum) { return sSavePath / ("file" + std::to_string(fileNum + 1) + ".temp"); } +std::vector Rando::StaticData::oldVerHintOrder { + RH_COLOSSUS_GOSSIP_STONE, + RH_DMC_GOSSIP_STONE, + RH_DMC_UPPER_GROTTO_GOSSIP_STONE, + RH_DMT_GOSSIP_STONE, + RH_DMT_STORMS_GROTTO_GOSSIP_STONE, + RH_DODONGOS_CAVERN_GOSSIP_STONE, + RH_ZF_FAIRY_GOSSIP_STONE, + RH_GC_MAZE_GOSSIP_STONE, + RH_GC_MEDIGORON_GOSSIP_STONE, + RH_GV_GOSSIP_STONE, + RH_GRAVEYARD_GOSSIP_STONE, + RH_HC_MALON_GOSSIP_STONE, + RH_HC_ROCK_WALL_GOSSIP_STONE, + RH_HC_STORMS_GROTTO_GOSSIP_STONE, + RH_HF_COW_GROTTO_GOSSIP_STONE, + RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, + RH_HF_OPEN_GROTTO_GOSSIP_STONE, + RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, + RH_ZF_JABU_GOSSIP_STONE, + RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE, + RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, + RH_KF_GOSSIP_STONE, + RH_KF_STORMS_GROTTO_GOSSIP_STONE, + RH_KAK_OPEN_GROTTO_GOSSIP_STONE, + RH_LH_LAB_GOSSIP_STONE, + RH_LH_SOUTHEAST_GOSSIP_STONE, + RH_LH_SOUTHWEST_GOSSIP_STONE, + RH_LW_GOSSIP_STONE, + RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, + RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE, + RH_SFM_MAZE_CENTER_GOSSIP_STONE, + RH_SFM_SARIA_GOSSIP_STONE, + RH_TOT_LEFT_CENTER_GOSSIP_STONE, + RH_TOT_LEFTMOST_GOSSIP_STONE, + RH_TOT_RIGHT_CENTER_GOSSIP_STONE, + RH_TOT_RIGHTMOST_GOSSIP_STONE, + RH_ZD_GOSSIP_STONE, + RH_ZR_NEAR_DOMAIN_GOSSIP_STONE, + RH_ZR_NEAR_GROTTOS_GOSSIP_STONE, + RH_ZR_OPEN_GROTTO_GOSSIP_STONE, +}; + +uint16_t Rando::StaticData::oldVerGossipStoneStart = 740; + SaveManager::SaveManager() { coreSectionIDsByName["base"] = SECTION_ID_BASE; coreSectionIDsByName["randomizer"] = SECTION_ID_RANDOMIZER; @@ -106,6 +153,7 @@ SaveManager::SaveManager() { } } +// RANDOTODO should we just have dummy functions that raise warnings instead if these aren't supported? void SaveManager::LoadRandomizerVersion1() { auto randoContext = Rando::Context::GetInstance(); RandomizerCheck location = RC_UNKNOWN_CHECK; @@ -140,32 +188,33 @@ void SaveManager::LoadRandomizerVersion1() { for (int j = 0; j < ARRAY_COUNT(hintText); j++) { SaveManager::Instance->LoadData("ht" + std::to_string(i) + "-" + std::to_string(j), hintText[j]); } - randoContext->AddHint(RandomizerHintKey(check - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[Rando::StaticData::oldVerGossipStoneStart]; + randoContext->AddHint(stoneHint, Rando::Hint(stoneHint, {CustomMessage(hintText)})); } char childAltarText[250]; for (int i = 0; i < ARRAY_COUNT(childAltarText); i++) { SaveManager::Instance->LoadData("cat" + std::to_string(i), childAltarText[i]); } - randoContext->AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_ALTAR_CHILD, Rando::Hint(RH_ALTAR_CHILD, {CustomMessage(childAltarText)})); char adultAltarText[750]; for (int i = 0; i < ARRAY_COUNT(adultAltarText); i++) { SaveManager::Instance->LoadData("aat" + std::to_string(i), adultAltarText[i]); } - randoContext->AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_ALTAR_ADULT, Rando::Hint(RH_ALTAR_ADULT, {CustomMessage(adultAltarText)})); char ganonHintText[150]; for (int i = 0; i < ARRAY_COUNT(ganonHintText); i++) { SaveManager::Instance->LoadData("ght" + std::to_string(i), ganonHintText[i]); } - randoContext->AddHint(RH_GANONDORF_HINT, Text(ganonHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_GANONDORF_HINT, Rando::Hint(RH_GANONDORF_HINT, {CustomMessage(ganonHintText)})); char ganonText[250]; for (int i = 0; i < ARRAY_COUNT(ganonText); i++) { SaveManager::Instance->LoadData("gt" + std::to_string(i), ganonText[i]); } - randoContext->AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_GANONDORF_JOKE, Rando::Hint(RH_GANONDORF_JOKE, {CustomMessage(ganonText)})); SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems); @@ -193,6 +242,7 @@ void SaveManager::LoadRandomizerVersion1() { }); } +//RANDOTODO if we actually support this, be less lazy void SaveManager::LoadRandomizerVersion2() { auto randoContext = Rando::Context::GetInstance(); SaveManager::Instance->LoadArray("itemLocations", RC_MAX, [&](size_t i) { @@ -244,56 +294,57 @@ void SaveManager::LoadRandomizerVersion2() { if (rc != RC_UNKNOWN_CHECK) { std::string hintText; SaveManager::Instance->LoadData("hintText", hintText); - randoContext->AddHint(RandomizerHintKey(rc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[Rando::StaticData::oldVerGossipStoneStart]; + randoContext->AddHint(stoneHint, Rando::Hint(stoneHint, {CustomMessage(hintText)})); } }); }); std::string childAltarText; SaveManager::Instance->LoadData("childAltarText", childAltarText); - randoContext->AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_ALTAR_CHILD, Rando::Hint(RH_ALTAR_CHILD, {CustomMessage(childAltarText)})); std::string adultAltarText; SaveManager::Instance->LoadData("adultAltarText", adultAltarText); - randoContext->AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_ALTAR_ADULT, Rando::Hint(RH_ALTAR_ADULT, {CustomMessage(adultAltarText)})); std::string ganonHintText; SaveManager::Instance->LoadData("ganonHintText", ganonHintText); - randoContext->AddHint(RH_GANONDORF_HINT, Text(ganonHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_GANONDORF_HINT, Rando::Hint(RH_GANONDORF_HINT, {CustomMessage(ganonHintText)})); std::string ganonText; SaveManager::Instance->LoadData("ganonText", ganonText); - randoContext->AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_GANONDORF_JOKE, Rando::Hint(RH_GANONDORF_JOKE, {CustomMessage(ganonText)})); std::string dampeText; SaveManager::Instance->LoadData("dampeText", dampeText); - randoContext->AddHint(RH_DAMPES_DIARY, Text(dampeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_DAMPES_DIARY, Rando::Hint(RH_DAMPES_DIARY, {CustomMessage(dampeText)})); std::string gregHintText; SaveManager::Instance->LoadData("gregHintText", gregHintText); - randoContext->AddHint(RH_GREG_RUPEE, Text(gregHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_GREG_RUPEE, Rando::Hint(RH_GREG_RUPEE, {CustomMessage(gregHintText)})); std::string sheikText; SaveManager::Instance->LoadData("sheikText", sheikText); - randoContext->AddHint(RH_SHEIK_LIGHT_ARROWS, Text(sheikText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_SHEIK_HINT, Rando::Hint(RH_SHEIK_HINT, {CustomMessage(sheikText)})); std::string sariaText; SaveManager::Instance->LoadData("sariaText", sariaText); - randoContext->AddHint(RH_SARIA, Text(sariaText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_SARIA_HINT, Rando::Hint(RH_SARIA_HINT, {CustomMessage(sariaText)})); std::string fishingPoleText; SaveManager::Instance->LoadData("fishingPoleText", fishingPoleText); - randoContext->AddHint(RH_FISHING_POLE, Text(fishingPoleText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static"); + randoContext->AddHint(RH_FISHING_POLE, Rando::Hint(RH_FISHING_POLE, {CustomMessage(fishingPoleText)})); std::string warpMinuetText; SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText); - randoContext->AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpMinuetText)); + randoContext->AddHint(RH_MINUET_WARP_LOC, Rando::Hint(RH_MINUET_WARP_LOC, {CustomMessage(warpMinuetText)})); std::string warpBoleroText; SaveManager::Instance->LoadData("warpBoleroText", warpBoleroText); - randoContext->AddHint(RH_BOLERO_WARP_LOC, Text(warpBoleroText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpBoleroText)); + randoContext->AddHint(RH_BOLERO_WARP_LOC, Rando::Hint(RH_BOLERO_WARP_LOC, {CustomMessage(warpBoleroText)})); std::string warpSerenadeText; SaveManager::Instance->LoadData("warpSerenadeText", warpSerenadeText); - randoContext->AddHint(RH_SERENADE_WARP_LOC, Text(warpSerenadeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpSerenadeText)); + randoContext->AddHint(RH_SERENADE_WARP_LOC, Rando::Hint(RH_SERENADE_WARP_LOC, {CustomMessage(warpSerenadeText)})); std::string warpRequiemText; SaveManager::Instance->LoadData("warpRequiemText", warpRequiemText); - randoContext->AddHint(RH_REQUIEM_WARP_LOC, Text(warpRequiemText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpRequiemText)); + randoContext->AddHint(RH_REQUIEM_WARP_LOC, Rando::Hint(RH_REQUIEM_WARP_LOC, {CustomMessage(warpRequiemText)})); std::string warpNocturneText; SaveManager::Instance->LoadData("warpNocturneText", warpNocturneText); - randoContext->AddHint(RH_NOCTURNE_WARP_LOC, Text(warpNocturneText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpNocturneText)); + randoContext->AddHint(RH_NOCTURNE_WARP_LOC, Rando::Hint(RH_NOCTURNE_WARP_LOC, {CustomMessage(warpNocturneText)})); std::string warpPreludeText; SaveManager::Instance->LoadData("warpPreludeText", warpPreludeText); - randoContext->AddHint(RH_PRELUDE_WARP_LOC, Text(warpPreludeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpPreludeText)); + randoContext->AddHint(RH_PRELUDE_WARP_LOC, Rando::Hint(RH_PRELUDE_WARP_LOC, {CustomMessage(warpPreludeText)})); SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems); @@ -386,23 +437,10 @@ void SaveManager::LoadRandomizerVersion3() { }); SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) { - SaveManager::Instance->LoadStruct("", [&]() { - RandomizerHintKey rhk = RH_NONE; - SaveManager::Instance->LoadData("hintKey", rhk); - std::string english, french, german; - SaveManager::Instance->LoadStruct("hintText", [&]() { - SaveManager::Instance->LoadData("english", english); - SaveManager::Instance->LoadData("french", french); - SaveManager::Instance->LoadData("german", german); - }); - RandomizerCheck rc = RC_UNKNOWN_CHECK; - SaveManager::Instance->LoadData("hintedCheck", rc); - HintType ht = HINT_TYPE_STATIC; - SaveManager::Instance->LoadData("hintType", ht); - RandomizerArea savedArea; - SaveManager::Instance->LoadData("hintedArea", savedArea); - randoContext->AddHint(rhk, Text(english, french, /*spanish*/"", german), rc, ht, "Unknown", savedArea);//RANDOTODO, maybe store and load distrabution, but it's a string... - }); + auto hint = RandomizerHint(i); + nlohmann::ordered_json json; + SaveManager::Instance->LoadData("", json); + randoContext->AddHint(hint, Rando::Hint(hint, json)); }); SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems); @@ -477,17 +515,68 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f }); SaveManager::Instance->SaveArray("hintLocations", RH_MAX, [&](size_t i) { + auto hint = randoContext->GetHint(RandomizerHint(i)); + // RANDOTODO a way for saveData to accept a raw JSON would make maintaining hint code nicer. + // save manager forces code rewrites between the spoiler log and internal saves, when the code needs to do the exact same thing + // in cases where data needs to be loaded in from the spoiler log for plando mode. + // fails as push_back is ambiguous + // SaveManager::Instance->SaveData(Rando::StaticData::hintNames[(uint32_t)hint].GetEnglish(), hint->toJSON()); SaveManager::Instance->SaveStruct("", [&]() { - auto hint = randoContext->GetHint(RandomizerHintKey(i)); - SaveManager::Instance->SaveData("hintKey", RandomizerHintKey(i)); - SaveManager::Instance->SaveStruct("hintText", [&]() { - SaveManager::Instance->SaveData("english", hint->GetText().GetEnglish()); - SaveManager::Instance->SaveData("french", hint->GetText().GetFrench()); - SaveManager::Instance->SaveData("german", hint->GetText().GetGerman()); - }); - SaveManager::Instance->SaveData("hintedCheck", hint->GetHintedLocation()); - SaveManager::Instance->SaveData("hintType", hint->GetHintType()); - SaveManager::Instance->SaveData("hintedArea", hint->GetHintedArea()); + bool enabled = hint->IsEnabled(); + SaveManager::Instance->SaveData("enabled", enabled); + if (enabled){ + std::vector messages = hint->GetAllMessageStrings(MF_RAW); + SaveManager::Instance->SaveArray("messages", messages.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", messages[i]); + }); + + SaveManager::Instance->SaveData("distribution", hint->GetDistribution()); + SaveManager::Instance->SaveData("type", Rando::StaticData::hintTypeNames[hint->GetHintType()].GetEnglish(MF_CLEAN)); + + std::vector hintKeys = hint->GetHintTextKeys(); + SaveManager::Instance->SaveArray("hintKeys", hintKeys.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", hintKeys[i]); + }); + + std::vector locations = hint->GetHintedLocations(); + SaveManager::Instance->SaveArray("locations", locations.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", Rando::StaticData::GetLocation(locations[i])->GetName()); + }); + + std::vector items = hint->GetHintedItems(); + SaveManager::Instance->SaveArray("items", items.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", Rando::StaticData::GetItemTable()[items[i]].GetName().GetEnglish()); + }); + + std::vector itemNamesChosen = hint->GetItemNamesChosen(); + SaveManager::Instance->SaveArray("itemNamesChosen", itemNamesChosen.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", itemNamesChosen[i]); + }); + + std::vector hintTextsChosen = hint->GetHintTextsChosen(); + SaveManager::Instance->SaveArray("hintTextsChosen", hintTextsChosen.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", hintTextsChosen[i]); + }); + + std::vector areaTextsChosen = hint->GetAreaTextsChosen(); + SaveManager::Instance->SaveArray("areaTextsChosen", areaTextsChosen.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", areaTextsChosen[i]); + }); + + std::vector areas = hint->GetHintedAreas(); + SaveManager::Instance->SaveArray("areas", areas.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", Rando::StaticData::hintTextTable[Rando::StaticData::areaNames[areas[i]]].GetClear().GetForCurrentLanguage(MF_CLEAN)); + }); + + std::vector trials = hint->GetHintedTrials(); + SaveManager::Instance->SaveArray("trials", trials.size(), [&](size_t i) { + SaveManager::Instance->SaveData("", randoContext->GetTrial(trials[i])->GetName().GetForCurrentLanguage(MF_CLEAN)); + }); + + SaveManager::Instance->SaveData("num", hint->GetNum()); + + + } }); }); diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 935a6366e..f7d0910f6 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -183,6 +183,7 @@ class SaveManager { nlohmann::json* currentJsonContext = nullptr; nlohmann::json::iterator currentJsonArrayContext; std::shared_ptr smThreadPool; + }; #else diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 05432fc53..ce0255436 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -137,19 +137,19 @@ extern "C" void OTRMessage_Init() CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN, - CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r{{gsCount}}%w tokens&in total!\x0E\x3C", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r{{gsCount}}&%wGoldene " + CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!\x0E\x3C", + "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " "Skulltula-Symbole&gesammelt!\x0E\x3C", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r{{gsCount}}%w symboles en " + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " "tout!\x0E\x3C", TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN, CustomMessage( - "You got a %rGold Skulltula Token%w!&You've collected %r{{gsCount}}%w tokens&in total!", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r{{gsCount}}&%wGoldene " + "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", + "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " "Skulltula-Symbole&gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r{{gsCount}}%w symboles en tout!", + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en tout!", TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHU_10_DESC, @@ -168,14 +168,14 @@ extern "C" void OTRMessage_Init() CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_CONTAINER, ITEM_HEART_CONTAINER, CustomMessage( - "You got a %rHeart Container%w!&You've collected %r{{heartContainerCount}}%w containers&in total!", - "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r{{heartContainerCount}}%w&Herzcontainer gesammelt!", - "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r{{heartContainerCount}}%w en tout!")); + "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", + "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", + "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!")); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, - CustomMessage("You got a %rHeart Piece%w!&You've collected %r{{heartPieceCount}}%w pieces&in total!", - "Ein %rHerzteil%w!&Du hast nun insgesamt %r{{heartPieceCount}}%w&Herteile gesammelt!", - "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r{{heartPieceCount}}%w en tout!", + CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", + "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herteile gesammelt!", + "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index f0cdc2249..012531f66 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -16,9 +16,6 @@ #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED -#define TEXT_SHEIK_NEED_HOOK 0x700F -#define TEXT_SHEIK_HAVE_HOOK 0x7010 - void EnXc_Init(Actor* thisx, PlayState* play); void EnXc_Destroy(Actor* thisx, PlayState* play); void EnXc_Update(Actor* thisx, PlayState* play); @@ -2239,27 +2236,11 @@ void EnXc_SetupDialogueAction(EnXc* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, play)) { this->action = SHEIK_ACTION_IN_DIALOGUE; } else { - this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY; - if (IS_RANDO && gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME) { - if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { - this->actor.textId = TEXT_SHEIK_NEED_HOOK; - } else { - this->actor.textId = TEXT_SHEIK_HAVE_HOOK; - } - } else if (IS_RANDO && gPlayState->sceneNum == SCENE_INSIDE_GANONS_CASTLE) { - if (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && - CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired) { - this->actor.textId = TEXT_SHEIK_HAVE_HOOK; - } else { - this->actor.textId = TEXT_SHEIK_NEED_HOOK; - } - } - else { - if (INV_CONTENT(ITEM_HOOKSHOT) != ITEM_NONE) { - this->actor.textId = 0x7010; //"You have what you need" - } else { - this->actor.textId = 0x700F; //"You need another skill" - } + this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY; //this arrangment is cute but I would rather handle all message selection in ship code + if (INV_CONTENT(ITEM_HOOKSHOT) != ITEM_NONE) { + this->actor.textId = 0x7010; //"You have what you need" + } else { + this->actor.textId = 0x700F; //"You need another skill" } func_8002F2F4(&this->actor, play); } From 8b3f1f186859e01d24ef825c29cafd602ed83cc8 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 29 Apr 2024 20:26:03 -0400 Subject: [PATCH 199/300] bump LUS, remove switch and wii u from CI (#4087) --- .github/workflows/generate-builds.yml | 130 -------------------------- libultraship | 2 +- 2 files changed, 1 insertion(+), 131 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 4b8153a07..46e0abf53 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -241,136 +241,6 @@ jobs: path: | soh.appimage readme.txt - build-switch: - needs: generate-soh-otr - runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} - container: - image: devkitpro/devkita64:20240120 - steps: - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y ninja-build - sudo apt-get remove -y cmake - wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh - sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir - wget https://libzip.org/download/libzip-1.10.1.tar.gz - tar -xzvf libzip-1.10.1.tar.gz - cd libzip-1.10.1 - mkdir build - cd build - cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake - make - make install - cd ../.. - wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz - tar -xzvf v3.11.3.tar.gz - cd json-3.11.3 - mkdir build - cd build - cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake - make - make install - cd ../.. - - - name: Fix dubious ownership error - if: ${{ vars.LINUX_RUNNER }} - run: git config --global --add safe.directory '*' - - uses: actions/checkout@v3 - with: - submodules: true - - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.11 - with: - key: ${{ runner.os }}-switch-ccache-${{ github.ref }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-switch-ccache-${{ github.ref }} - ${{ runner.os }}-switch-ccache- - - name: Build SoH - run: | - cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache - cmake --build build-switch --target soh_nro -j3 - - mv build-switch/soh/*.nro soh.nro - mv README.md readme.txt - - name: Download soh.otr - uses: actions/download-artifact@v4 - with: - name: soh.otr - - name: Upload build - uses: actions/upload-artifact@v4 - with: - name: soh-switch - path: | - soh.nro - soh.otr - readme.txt - build-wiiu: - needs: generate-soh-otr - runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} - container: - image: devkitpro/devkitppc:20230110 - steps: - - name: Install dependencies - if: ${{ !vars.LINUX_RUNNER }} - run: | - sudo apt-get install -y ninja-build - sudo apt-get remove -y cmake - wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh - sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir - wget https://libzip.org/download/libzip-1.10.1.tar.gz - tar -xzvf libzip-1.10.1.tar.gz - cd libzip-1.10.1 - mkdir build - cd build - cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake - make - make install - cd ../.. - wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz - tar -xzvf v3.11.3.tar.gz - cd json-3.11.3 - mkdir build - cd build - cmake -H.. -B. -DJSON_BuildTests=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake - make - make install - cd ../.. - - - uses: actions/checkout@v3 - with: - submodules: true - - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.11 - with: - key: ${{ runner.os }}-wiiu-ccache-${{ github.ref }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-wiiu-ccache-${{ github.ref }} - ${{ runner.os }}-wiiu-ccache- - - name: Build SoH - run: | - cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache - cmake --build build-wiiu --target soh_wuhb --config Release -j3 - - mv build-wiiu/soh/*.rpx soh.rpx - mv build-wiiu/soh/*.wuhb soh.wuhb - mv README.md readme.txt - env: - DEVKITPRO: /opt/devkitpro - DEVKITPPC: /opt/devkitpro/devkitPPC - - name: Download soh.otr - uses: actions/download-artifact@v4 - with: - name: soh.otr - - name: Upload build - uses: actions/upload-artifact@v4 - with: - name: soh-wiiu - path: | - soh.rpx - soh.wuhb - soh.otr - readme.txt build-windows: needs: generate-soh-otr runs-on: ${{ (vars.WINDOWS_RUNNER && fromJSON(vars.WINDOWS_RUNNER)) || 'windows-latest' }} diff --git a/libultraship b/libultraship index 6f978e0d2..3d2e6bc12 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 6f978e0d237530f304ba2018bbdc539b175c184a +Subproject commit 3d2e6bc128a105f0cba9109573a2401a8ba43f49 From 4ecb76b117ae135ea1487dc3cfd2a6898c8c2490 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 30 Apr 2024 01:19:02 -0400 Subject: [PATCH 200/300] tinyxml from package manager (#4073) --- .github/workflows/apt-deps.txt | 2 +- .github/workflows/generate-builds.yml | 29 + .github/workflows/macports-deps.txt | 2 +- .github/workflows/test-builds-on-distros.yml | 1 + CMakeLists.txt | 2 +- libultraship | 2 +- .../randomizer/3drando/tinyxml2.cpp | 2956 ----------------- .../randomizer/3drando/tinyxml2.h | 2365 ------------- 8 files changed, 34 insertions(+), 5325 deletions(-) delete mode 100644 soh/soh/Enhancements/randomizer/3drando/tinyxml2.cpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/tinyxml2.h diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index af6f8aabd..62eba0386 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev ninja-build diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 46e0abf53..5c1930ede 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -47,6 +47,20 @@ jobs: make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ + - name: Install latest tinyxml2 + run: | + sudo apt-get remove libtinyxml2-dev + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + if [ ! -d "tinyxml2-10.0.0" ]; then + wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz + tar -xzf 10.0.0.tar.gz + fi + cd tinyxml2-10.0.0 + mkdir build + cd build + cmake .. + make + sudo make install - name: Generate soh.otr run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" @@ -205,6 +219,21 @@ jobs: cmake .. make sudo make install + - name: Install latest tinyxml2 + if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} + run: | + sudo apt-get remove libtinyxml2-dev + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + if [ ! -d "tinyxml2-10.0.0" ]; then + wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz + tar -xzf 10.0.0.tar.gz + fi + cd tinyxml2-10.0.0 + mkdir build + cd build + cmake .. + make + sudo make install - name: Install latest SDL_net if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | diff --git a/.github/workflows/macports-deps.txt b/.github/workflows/macports-deps.txt index 96bb9d40a..d15039078 100644 --- a/.github/workflows/macports-deps.txt +++ b/.github/workflows/macports-deps.txt @@ -1 +1 @@ -libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal \ No newline at end of file +libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal tinyxml2 +universal \ No newline at end of file diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index 82709d1af..683e07b24 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -1,5 +1,6 @@ # todo: # nlohmann +# tinyxml2 name: test-builds-on-distros on: diff --git a/CMakeLists.txt b/CMakeLists.txt index 386142065..34fe61b65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") set(VCPKG_TARGET_TRIPLET x64-windows-static) vcpkg_bootstrap() - vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json) + vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2) if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) diff --git a/libultraship b/libultraship index 3d2e6bc12..6c375a8b5 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 3d2e6bc128a105f0cba9109573a2401a8ba43f49 +Subproject commit 6c375a8b5eb8c44088b5bb2b472d40c50ad36d1f diff --git a/soh/soh/Enhancements/randomizer/3drando/tinyxml2.cpp b/soh/soh/Enhancements/randomizer/3drando/tinyxml2.cpp deleted file mode 100644 index 3187ad558..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/tinyxml2.cpp +++ /dev/null @@ -1,2956 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml2.h" - -#include // yes, this one new style header, is in the Android SDK. -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) -# include -# include -#else -# include -# include -#endif - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - // Microsoft Visual Studio, version 2005 and higher. Not WinCE. - /*int _snprintf_s( - char *buffer, - size_t sizeOfBuffer, - size_t count, - const char *format [, - argument] ... - );*/ - static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) - { - va_list va; - va_start( va, format ); - const int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - va_end( va ); - return result; - } - - static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) - { - const int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - return result; - } - - #define TIXML_VSCPRINTF _vscprintf - #define TIXML_SSCANF sscanf_s -#elif defined _MSC_VER - // Microsoft Visual Studio 2003 and earlier or WinCE - #define TIXML_SNPRINTF _snprintf - #define TIXML_VSNPRINTF _vsnprintf - #define TIXML_SSCANF sscanf - #if (_MSC_VER < 1400 ) && (!defined WINCE) - // Microsoft Visual Studio 2003 and not WinCE. - #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. - #else - // Microsoft Visual Studio 2003 and earlier or WinCE. - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = 512; - for (;;) { - len = len*2; - char* str = new char[len](); - const int required = _vsnprintf(str, len, format, va); - delete[] str; - if ( required != -1 ) { - TIXMLASSERT( required >= 0 ); - len = required; - break; - } - } - TIXMLASSERT( len >= 0 ); - return len; - } - #endif -#else - // GCC version 3 and higher - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_VSNPRINTF vsnprintf - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = vsnprintf( 0, 0, format, va ); - TIXMLASSERT( len >= 0 ); - return len; - } - #define TIXML_SSCANF sscanf -#endif - - -static const char LINE_FEED = static_cast(0x0a); // all line endings are normalized to LF -static const char LF = LINE_FEED; -static const char CARRIAGE_RETURN = static_cast(0x0d); // CR gets filtered out -static const char CR = CARRIAGE_RETURN; -static const char SINGLE_QUOTE = '\''; -static const char DOUBLE_QUOTE = '\"'; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// ef bb bf (Microsoft "lead bytes") - designates UTF-8 - -static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -namespace tinyxml2 -{ - -struct Entity { - const char* pattern; - int length; - char value; -}; - -static const int NUM_ENTITIES = 5; -static const Entity entities[NUM_ENTITIES] = { - { "quot", 4, DOUBLE_QUOTE }, - { "amp", 3, '&' }, - { "apos", 4, SINGLE_QUOTE }, - { "lt", 2, '<' }, - { "gt", 2, '>' } -}; - - -StrPair::~StrPair() -{ - Reset(); -} - - -void StrPair::TransferTo( StrPair* other ) -{ - if ( this == other ) { - return; - } - // This in effect implements the assignment operator by "moving" - // ownership (as in auto_ptr). - - TIXMLASSERT( other != 0 ); - TIXMLASSERT( other->_flags == 0 ); - TIXMLASSERT( other->_start == 0 ); - TIXMLASSERT( other->_end == 0 ); - - other->Reset(); - - other->_flags = _flags; - other->_start = _start; - other->_end = _end; - - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::Reset() -{ - if ( _flags & NEEDS_DELETE ) { - delete [] _start; - } - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::SetStr( const char* str, int flags ) -{ - TIXMLASSERT( str ); - Reset(); - size_t len = strlen( str ); - TIXMLASSERT( _start == 0 ); - _start = new char[ len+1 ]; - memcpy( _start, str, len+1 ); - _end = _start + len; - _flags = flags | NEEDS_DELETE; -} - - -char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( endTag && *endTag ); - TIXMLASSERT(curLineNumPtr); - - char* start = p; - const char endChar = *endTag; - size_t length = strlen( endTag ); - - // Inner loop of text parsing. - while ( *p ) { - if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { - Set( start, p, strFlags ); - return p + length; - } else if (*p == '\n') { - ++(*curLineNumPtr); - } - ++p; - TIXMLASSERT( p ); - } - return 0; -} - - -char* StrPair::ParseName( char* p ) -{ - if ( !p || !(*p) ) { - return 0; - } - if ( !XMLUtil::IsNameStartChar( *p ) ) { - return 0; - } - - char* const start = p; - ++p; - while ( *p && XMLUtil::IsNameChar( *p ) ) { - ++p; - } - - Set( start, p, 0 ); - return p; -} - - -void StrPair::CollapseWhitespace() -{ - // Adjusting _start would cause undefined behavior on delete[] - TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); - // Trim leading space. - _start = XMLUtil::SkipWhiteSpace( _start, 0 ); - - if ( *_start ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( *p ) { - if ( XMLUtil::IsWhiteSpace( *p )) { - p = XMLUtil::SkipWhiteSpace( p, 0 ); - if ( *p == 0 ) { - break; // don't write to q; this trims the trailing space. - } - *q = ' '; - ++q; - } - *q = *p; - ++q; - ++p; - } - *q = 0; - } -} - - -const char* StrPair::GetStr() -{ - TIXMLASSERT( _start ); - TIXMLASSERT( _end ); - if ( _flags & NEEDS_FLUSH ) { - *_end = 0; - _flags ^= NEEDS_FLUSH; - - if ( _flags ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( p < _end ) { - if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { - // CR-LF pair becomes LF - // CR alone becomes LF - // LF-CR becomes LF - if ( *(p+1) == LF ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { - if ( *(p+1) == CR ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { - // Entities handled by tinyXML2: - // - special entities in the entity table [in/out] - // - numeric character reference [in] - // 中 or 中 - - if ( *(p+1) == '#' ) { - const int buflen = 10; - char buf[buflen] = { 0 }; - int len = 0; - const char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); - if ( adjusted == 0 ) { - *q = *p; - ++p; - ++q; - } - else { - TIXMLASSERT( 0 <= len && len <= buflen ); - TIXMLASSERT( q + len <= adjusted ); - p = adjusted; - memcpy( q, buf, len ); - q += len; - } - } - else { - bool entityFound = false; - for( int i = 0; i < NUM_ENTITIES; ++i ) { - const Entity& entity = entities[i]; - if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 - && *( p + entity.length + 1 ) == ';' ) { - // Found an entity - convert. - *q = entity.value; - ++q; - p += entity.length + 2; - entityFound = true; - break; - } - } - if ( !entityFound ) { - // fixme: treat as error? - ++p; - ++q; - } - } - } - else { - *q = *p; - ++p; - ++q; - } - } - *q = 0; - } - // The loop below has plenty going on, and this - // is a less useful mode. Break it out. - if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { - CollapseWhitespace(); - } - _flags = (_flags & NEEDS_DELETE); - } - TIXMLASSERT( _start ); - return _start; -} - - - - -// --------- XMLUtil ----------- // - -const char* XMLUtil::writeBoolTrue = "true"; -const char* XMLUtil::writeBoolFalse = "false"; - -void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) -{ - static const char* defTrue = "true"; - static const char* defFalse = "false"; - - writeBoolTrue = (writeTrue) ? writeTrue : defTrue; - writeBoolFalse = (writeFalse) ? writeFalse : defFalse; -} - - -const char* XMLUtil::ReadBOM( const char* p, bool* bom ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( bom ); - *bom = false; - const unsigned char* pu = reinterpret_cast(p); - // Check for BOM: - if ( *(pu+0) == TIXML_UTF_LEAD_0 - && *(pu+1) == TIXML_UTF_LEAD_1 - && *(pu+2) == TIXML_UTF_LEAD_2 ) { - *bom = true; - p += 3; - } - TIXMLASSERT( p ); - return p; -} - - -void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) { - *length = 1; - } - else if ( input < 0x800 ) { - *length = 2; - } - else if ( input < 0x10000 ) { - *length = 3; - } - else if ( input < 0x200000 ) { - *length = 4; - } - else { - *length = 0; // This code won't convert this correctly anyway. - return; - } - - output += *length; - - // Scary scary fall throughs are annotated with carefully designed comments - // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc - switch (*length) { - case 4: - --output; - *output = static_cast((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 3: - --output; - *output = static_cast((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 2: - --output; - *output = static_cast((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 1: - --output; - *output = static_cast(input | FIRST_BYTE_MARK[*length]); - break; - default: - TIXMLASSERT( false ); - } -} - - -const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) -{ - // Presume an entity, and pull it out. - *length = 0; - - if ( *(p+1) == '#' && *(p+2) ) { - unsigned long ucs = 0; - TIXMLASSERT( sizeof( ucs ) >= 4 ); - ptrdiff_t delta = 0; - unsigned mult = 1; - static const char SEMICOLON = ';'; - - if ( *(p+2) == 'x' ) { - // Hexadecimal. - const char* q = p+3; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != 'x' ) { - unsigned int digit = 0; - - if ( *q >= '0' && *q <= '9' ) { - digit = *q - '0'; - } - else if ( *q >= 'a' && *q <= 'f' ) { - digit = *q - 'a' + 10; - } - else if ( *q >= 'A' && *q <= 'F' ) { - digit = *q - 'A' + 10; - } - else { - return 0; - } - TIXMLASSERT( digit < 16 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - TIXMLASSERT( mult <= UINT_MAX / 16 ); - mult *= 16; - --q; - } - } - else { - // Decimal. - const char* q = p+2; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != '#' ) { - if ( *q >= '0' && *q <= '9' ) { - const unsigned int digit = *q - '0'; - TIXMLASSERT( digit < 10 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - } - else { - return 0; - } - TIXMLASSERT( mult <= UINT_MAX / 10 ); - mult *= 10; - --q; - } - } - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - return p + delta + 1; - } - return p+1; -} - - -void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); -} - - -void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); -} - - -void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); -} - -/* - ToStr() of a number is a very tricky topic. - https://github.com/leethomason/tinyxml2/issues/106 -*/ -void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); -} - - -void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); -} - - -void XMLUtil::ToStr( int64_t v, char* buffer, int bufferSize ) -{ - // horrible syntax trick to make the compiler happy about %lld - TIXML_SNPRINTF(buffer, bufferSize, "%lld", static_cast(v)); -} - -void XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize ) -{ - // horrible syntax trick to make the compiler happy about %llu - TIXML_SNPRINTF(buffer, bufferSize, "%llu", (long long)v); -} - -bool XMLUtil::ToInt( const char* str, int* value ) -{ - if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) -{ - if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToBool( const char* str, bool* value ) -{ - int ival = 0; - if ( ToInt( str, &ival )) { - *value = (ival==0) ? false : true; - return true; - } - static const char* TRUE_VALS[] = { "true", "True", "TRUE", 0 }; - static const char* FALSE_VALS[] = { "false", "False", "FALSE", 0 }; - - for (int i = 0; TRUE_VALS[i]; ++i) { - if (StringEqual(str, TRUE_VALS[i])) { - *value = true; - return true; - } - } - for (int i = 0; FALSE_VALS[i]; ++i) { - if (StringEqual(str, FALSE_VALS[i])) { - *value = false; - return true; - } - } - return false; -} - - -bool XMLUtil::ToFloat( const char* str, float* value ) -{ - if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToDouble( const char* str, double* value ) -{ - if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToInt64(const char* str, int64_t* value) -{ - long long v = 0; // horrible syntax trick to make the compiler happy about %lld - if (TIXML_SSCANF(str, "%lld", &v) == 1) { - *value = static_cast(v); - return true; - } - return false; -} - - -bool XMLUtil::ToUnsigned64(const char* str, uint64_t* value) { - unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llu - if(TIXML_SSCANF(str, "%llu", &v) == 1) { - *value = (uint64_t)v; - return true; - } - return false; -} - - -char* XMLDocument::Identify( char* p, XMLNode** node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( p ); - char* const start = p; - int const startLine = _parseCurLineNum; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - if( !*p ) { - *node = 0; - TIXMLASSERT( p ); - return p; - } - - // These strings define the matching patterns: - static const char* xmlHeader = { "( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += xmlHeaderLen; - } - else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += commentHeaderLen; - } - else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - XMLText* text = CreateUnlinkedNode( _textPool ); - returnNode = text; - returnNode->_parseLineNum = _parseCurLineNum; - p += cdataHeaderLen; - text->SetCData( true ); - } - else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += dtdHeaderLen; - } - else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _elementPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += elementHeaderLen; - } - else { - returnNode = CreateUnlinkedNode( _textPool ); - returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character - p = start; // Back it up, all the text counts. - _parseCurLineNum = startLine; - } - - TIXMLASSERT( returnNode ); - TIXMLASSERT( p ); - *node = returnNode; - return p; -} - - -bool XMLDocument::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLNode ----------- // - -XMLNode::XMLNode( XMLDocument* doc ) : - _document( doc ), - _parent( 0 ), - _value(), - _parseLineNum( 0 ), - _firstChild( 0 ), _lastChild( 0 ), - _prev( 0 ), _next( 0 ), - _userData( 0 ), - _memPool( 0 ) -{ -} - - -XMLNode::~XMLNode() -{ - DeleteChildren(); - if ( _parent ) { - _parent->Unlink( this ); - } -} - -const char* XMLNode::Value() const -{ - // Edge case: XMLDocuments don't have a Value. Return null. - if ( this->ToDocument() ) - return 0; - return _value.GetStr(); -} - -void XMLNode::SetValue( const char* str, bool staticMem ) -{ - if ( staticMem ) { - _value.SetInternedStr( str ); - } - else { - _value.SetStr( str ); - } -} - -XMLNode* XMLNode::DeepClone(XMLDocument* target) const -{ - XMLNode* clone = this->ShallowClone(target); - if (!clone) return 0; - - for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { - XMLNode* childClone = child->DeepClone(target); - TIXMLASSERT(childClone); - clone->InsertEndChild(childClone); - } - return clone; -} - -void XMLNode::DeleteChildren() -{ - while( _firstChild ) { - TIXMLASSERT( _lastChild ); - DeleteChild( _firstChild ); - } - _firstChild = _lastChild = 0; -} - - -void XMLNode::Unlink( XMLNode* child ) -{ - TIXMLASSERT( child ); - TIXMLASSERT( child->_document == _document ); - TIXMLASSERT( child->_parent == this ); - if ( child == _firstChild ) { - _firstChild = _firstChild->_next; - } - if ( child == _lastChild ) { - _lastChild = _lastChild->_prev; - } - - if ( child->_prev ) { - child->_prev->_next = child->_next; - } - if ( child->_next ) { - child->_next->_prev = child->_prev; - } - child->_next = 0; - child->_prev = 0; - child->_parent = 0; -} - - -void XMLNode::DeleteChild( XMLNode* node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( node->_document == _document ); - TIXMLASSERT( node->_parent == this ); - Unlink( node ); - TIXMLASSERT(node->_prev == 0); - TIXMLASSERT(node->_next == 0); - TIXMLASSERT(node->_parent == 0); - DeleteNode( node ); -} - - -XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _lastChild ) { - TIXMLASSERT( _firstChild ); - TIXMLASSERT( _lastChild->_next == 0 ); - _lastChild->_next = addThis; - addThis->_prev = _lastChild; - _lastChild = addThis; - - addThis->_next = 0; - } - else { - TIXMLASSERT( _firstChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _firstChild ) { - TIXMLASSERT( _lastChild ); - TIXMLASSERT( _firstChild->_prev == 0 ); - - _firstChild->_prev = addThis; - addThis->_next = _firstChild; - _firstChild = addThis; - - addThis->_prev = 0; - } - else { - TIXMLASSERT( _lastChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - - TIXMLASSERT( afterThis ); - - if ( afterThis->_parent != this ) { - TIXMLASSERT( false ); - return 0; - } - if ( afterThis == addThis ) { - // Current state: BeforeThis -> AddThis -> OneAfterAddThis - // Now AddThis must disappear from it's location and then - // reappear between BeforeThis and OneAfterAddThis. - // So just leave it where it is. - return addThis; - } - - if ( afterThis->_next == 0 ) { - // The last node or the only node. - return InsertEndChild( addThis ); - } - InsertChildPreamble( addThis ); - addThis->_prev = afterThis; - addThis->_next = afterThis->_next; - afterThis->_next->_prev = addThis; - afterThis->_next = addThis; - addThis->_parent = this; - return addThis; -} - - - - -const XMLElement* XMLNode::FirstChildElement( const char* name ) const -{ - for( const XMLNode* node = _firstChild; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::LastChildElement( const char* name ) const -{ - for( const XMLNode* node = _lastChild; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::NextSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _next; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _prev; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // This is a recursive method, but thinking about it "at the current level" - // it is a pretty simple flat list: - // - // - // - // With a special case: - // - // - // - // - // Where the closing element (/foo) *must* be the next thing after the opening - // element, and the names must match. BUT the tricky bit is that the closing - // element will be read by the child. - // - // 'endTag' is the end tag for this node, it is returned by a call to a child. - // 'parentEnd' is the end tag for the parent, which is filled in and returned. - - XMLDocument::DepthTracker tracker(_document); - if (_document->Error()) - return 0; - - while( p && *p ) { - XMLNode* node = 0; - - p = _document->Identify( p, &node ); - TIXMLASSERT( p ); - if ( node == 0 ) { - break; - } - - const int initialLineNum = node->_parseLineNum; - - StrPair endTag; - p = node->ParseDeep( p, &endTag, curLineNumPtr ); - if ( !p ) { - DeleteNode( node ); - if ( !_document->Error() ) { - _document->SetError( XML_ERROR_PARSING, initialLineNum, 0); - } - break; - } - - const XMLDeclaration* const decl = node->ToDeclaration(); - if ( decl ) { - // Declarations are only allowed at document level - // - // Multiple declarations are allowed but all declarations - // must occur before anything else. - // - // Optimized due to a security test case. If the first node is - // a declaration, and the last node is a declaration, then only - // declarations have so far been added. - bool wellLocated = false; - - if (ToDocument()) { - if (FirstChild()) { - wellLocated = - FirstChild() && - FirstChild()->ToDeclaration() && - LastChild() && - LastChild()->ToDeclaration(); - } - else { - wellLocated = true; - } - } - if ( !wellLocated ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); - DeleteNode( node ); - break; - } - } - - XMLElement* ele = node->ToElement(); - if ( ele ) { - // We read the end tag. Return it to the parent. - if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEndTag ) { - ele->_value.TransferTo( parentEndTag ); - } - node->_memPool->SetTracked(); // created and then immediately deleted. - DeleteNode( node ); - return p; - } - - // Handle an end tag returned to this level. - // And handle a bunch of annoying errors. - bool mismatch = false; - if ( endTag.Empty() ) { - if ( ele->ClosingType() == XMLElement::OPEN ) { - mismatch = true; - } - } - else { - if ( ele->ClosingType() != XMLElement::OPEN ) { - mismatch = true; - } - else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { - mismatch = true; - } - } - if ( mismatch ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); - DeleteNode( node ); - break; - } - } - InsertEndChild( node ); - } - return 0; -} - -/*static*/ void XMLNode::DeleteNode( XMLNode* node ) -{ - if ( node == 0 ) { - return; - } - TIXMLASSERT(node->_document); - if (!node->ToDocument()) { - node->_document->MarkInUse(node); - } - - MemPool* pool = node->_memPool; - node->~XMLNode(); - pool->Free( node ); -} - -void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const -{ - TIXMLASSERT( insertThis ); - TIXMLASSERT( insertThis->_document == _document ); - - if (insertThis->_parent) { - insertThis->_parent->Unlink( insertThis ); - } - else { - insertThis->_document->MarkInUse(insertThis); - insertThis->_memPool->SetTracked(); - } -} - -const XMLElement* XMLNode::ToElementWithName( const char* name ) const -{ - const XMLElement* element = this->ToElement(); - if ( element == 0 ) { - return 0; - } - if ( name == 0 ) { - return element; - } - if ( XMLUtil::StringEqual( element->Name(), name ) ) { - return element; - } - return 0; -} - -// --------- XMLText ---------- // -char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - if ( this->CData() ) { - p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 ); - } - return p; - } - else { - int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; - if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { - flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; - } - - p = _value.ParseText( p, "<", flags, curLineNumPtr ); - if ( p && *p ) { - return p-1; - } - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 ); - } - } - return 0; -} - - -XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? - text->SetCData( this->CData() ); - return text; -} - - -bool XMLText::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLText* text = compare->ToText(); - return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); -} - - -bool XMLText::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLComment ---------- // - -XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLComment::~XMLComment() -{ -} - - -char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Comment parses as text. - p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? - return comment; -} - - -bool XMLComment::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLComment* comment = compare->ToComment(); - return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); -} - - -bool XMLComment::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLDeclaration ---------- // - -XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLDeclaration::~XMLDeclaration() -{ - //printf( "~XMLDeclaration\n" ); -} - - -char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Declaration parses as text. - p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? - return dec; -} - - -bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLDeclaration* declaration = compare->ToDeclaration(); - return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); -} - - - -bool XMLDeclaration::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLUnknown ---------- // - -XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLUnknown::~XMLUnknown() -{ -} - - -char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Unknown parses as text. - p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? - return text; -} - - -bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLUnknown* unknown = compare->ToUnknown(); - return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); -} - - -bool XMLUnknown::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLAttribute ---------- // - -const char* XMLAttribute::Name() const -{ - return _name.GetStr(); -} - -const char* XMLAttribute::Value() const -{ - return _value.GetStr(); -} - -char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr ) -{ - // Parse using the name rules: bug fix, was using ParseText before - p = _name.ParseName( p ); - if ( !p || !*p ) { - return 0; - } - - // Skip white space before = - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '=' ) { - return 0; - } - - ++p; // move up to opening quote - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '\"' && *p != '\'' ) { - return 0; - } - - const char endTag[2] = { *p, 0 }; - ++p; // move past opening quote - - p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr ); - return p; -} - - -void XMLAttribute::SetName( const char* n ) -{ - _name.SetStr( n ); -} - - -XMLError XMLAttribute::QueryIntValue( int* value ) const -{ - if ( XMLUtil::ToInt( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const -{ - if ( XMLUtil::ToUnsigned( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryInt64Value(int64_t* value) const -{ - if (XMLUtil::ToInt64(Value(), value)) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryUnsigned64Value(uint64_t* value) const -{ - if(XMLUtil::ToUnsigned64(Value(), value)) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryBoolValue( bool* value ) const -{ - if ( XMLUtil::ToBool( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryFloatValue( float* value ) const -{ - if ( XMLUtil::ToFloat( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryDoubleValue( double* value ) const -{ - if ( XMLUtil::ToDouble( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -void XMLAttribute::SetAttribute( const char* v ) -{ - _value.SetStr( v ); -} - - -void XMLAttribute::SetAttribute( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - _value.SetStr(buf); -} - -void XMLAttribute::SetAttribute(uint64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - _value.SetStr(buf); -} - - -void XMLAttribute::SetAttribute( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -// --------- XMLElement ---------- // -XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( OPEN ), - _rootAttribute( 0 ) -{ -} - - -XMLElement::~XMLElement() -{ - while( _rootAttribute ) { - XMLAttribute* next = _rootAttribute->_next; - DeleteAttribute( _rootAttribute ); - _rootAttribute = next; - } -} - - -const XMLAttribute* XMLElement::FindAttribute( const char* name ) const -{ - for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - -const char* XMLElement::Attribute( const char* name, const char* value ) const -{ - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return 0; - } - if ( !value || XMLUtil::StringEqual( a->Value(), value )) { - return a->Value(); - } - return 0; -} - -int XMLElement::IntAttribute(const char* name, int defaultValue) const -{ - int i = defaultValue; - QueryIntAttribute(name, &i); - return i; -} - -unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedAttribute(name, &i); - return i; -} - -int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Attribute(name, &i); - return i; -} - -uint64_t XMLElement::Unsigned64Attribute(const char* name, uint64_t defaultValue) const -{ - uint64_t i = defaultValue; - QueryUnsigned64Attribute(name, &i); - return i; -} - -bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolAttribute(name, &b); - return b; -} - -double XMLElement::DoubleAttribute(const char* name, double defaultValue) const -{ - double d = defaultValue; - QueryDoubleAttribute(name, &d); - return d; -} - -float XMLElement::FloatAttribute(const char* name, float defaultValue) const -{ - float f = defaultValue; - QueryFloatAttribute(name, &f); - return f; -} - -const char* XMLElement::GetText() const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - return FirstChild()->Value(); - } - return 0; -} - - -void XMLElement::SetText( const char* inText ) -{ - if ( FirstChild() && FirstChild()->ToText() ) - FirstChild()->SetValue( inText ); - else { - XMLText* theText = GetDocument()->NewText( inText ); - InsertFirstChild( theText ); - } -} - - -void XMLElement::SetText( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - SetText(buf); -} - -void XMLElement::SetText(uint64_t v) { - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - SetText(buf); -} - - -void XMLElement::SetText( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -XMLError XMLElement::QueryIntText( int* ival ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToInt( t, ival ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToUnsigned( t, uval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryInt64Text(int64_t* ival) const -{ - if (FirstChild() && FirstChild()->ToText()) { - const char* t = FirstChild()->Value(); - if (XMLUtil::ToInt64(t, ival)) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryUnsigned64Text(uint64_t* ival) const -{ - if(FirstChild() && FirstChild()->ToText()) { - const char* t = FirstChild()->Value(); - if(XMLUtil::ToUnsigned64(t, ival)) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryBoolText( bool* bval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToBool( t, bval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryDoubleText( double* dval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToDouble( t, dval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryFloatText( float* fval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToFloat( t, fval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - -int XMLElement::IntText(int defaultValue) const -{ - int i = defaultValue; - QueryIntText(&i); - return i; -} - -unsigned XMLElement::UnsignedText(unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedText(&i); - return i; -} - -int64_t XMLElement::Int64Text(int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Text(&i); - return i; -} - -uint64_t XMLElement::Unsigned64Text(uint64_t defaultValue) const -{ - uint64_t i = defaultValue; - QueryUnsigned64Text(&i); - return i; -} - -bool XMLElement::BoolText(bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolText(&b); - return b; -} - -double XMLElement::DoubleText(double defaultValue) const -{ - double d = defaultValue; - QueryDoubleText(&d); - return d; -} - -float XMLElement::FloatText(float defaultValue) const -{ - float f = defaultValue; - QueryFloatText(&f); - return f; -} - - -XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) -{ - XMLAttribute* last = 0; - XMLAttribute* attrib = 0; - for( attrib = _rootAttribute; - attrib; - last = attrib, attrib = attrib->_next ) { - if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { - break; - } - } - if ( !attrib ) { - attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - if ( last ) { - TIXMLASSERT( last->_next == 0 ); - last->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - attrib->SetName( name ); - } - return attrib; -} - - -void XMLElement::DeleteAttribute( const char* name ) -{ - XMLAttribute* prev = 0; - for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { - if ( XMLUtil::StringEqual( name, a->Name() ) ) { - if ( prev ) { - prev->_next = a->_next; - } - else { - _rootAttribute = a->_next; - } - DeleteAttribute( a ); - break; - } - prev = a; - } -} - - -char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) -{ - XMLAttribute* prevAttribute = 0; - - // Read the attributes. - while( p ) { - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); - return 0; - } - - // attribute. - if (XMLUtil::IsNameStartChar( *p ) ) { - XMLAttribute* attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - attrib->_parseLineNum = _document->_parseCurLineNum; - - const int attrLineNum = attrib->_parseLineNum; - - p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); - if ( !p || Attribute( attrib->Name() ) ) { - DeleteAttribute( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); - return 0; - } - // There is a minor bug here: if the attribute in the source xml - // document is duplicated, it will not be detected and the - // attribute will be doubly added. However, tracking the 'prevAttribute' - // avoids re-scanning the attribute list. Preferring performance for - // now, may reconsider in the future. - if ( prevAttribute ) { - TIXMLASSERT( prevAttribute->_next == 0 ); - prevAttribute->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - prevAttribute = attrib; - } - // end of the tag - else if ( *p == '>' ) { - ++p; - break; - } - // end of the tag - else if ( *p == '/' && *(p+1) == '>' ) { - _closingType = CLOSED; - return p+2; // done; sealed element. - } - else { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 ); - return 0; - } - } - return p; -} - -void XMLElement::DeleteAttribute( XMLAttribute* attribute ) -{ - if ( attribute == 0 ) { - return; - } - MemPool* pool = attribute->_memPool; - attribute->~XMLAttribute(); - pool->Free( attribute ); -} - -XMLAttribute* XMLElement::CreateAttribute() -{ - TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); - XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); - TIXMLASSERT( attrib ); - attrib->_memPool = &_document->_attributePool; - attrib->_memPool->SetTracked(); - return attrib; -} - - -XMLElement* XMLElement::InsertNewChildElement(const char* name) -{ - XMLElement* node = _document->NewElement(name); - return InsertEndChild(node) ? node : 0; -} - -XMLComment* XMLElement::InsertNewComment(const char* comment) -{ - XMLComment* node = _document->NewComment(comment); - return InsertEndChild(node) ? node : 0; -} - -XMLText* XMLElement::InsertNewText(const char* text) -{ - XMLText* node = _document->NewText(text); - return InsertEndChild(node) ? node : 0; -} - -XMLDeclaration* XMLElement::InsertNewDeclaration(const char* text) -{ - XMLDeclaration* node = _document->NewDeclaration(text); - return InsertEndChild(node) ? node : 0; -} - -XMLUnknown* XMLElement::InsertNewUnknown(const char* text) -{ - XMLUnknown* node = _document->NewUnknown(text); - return InsertEndChild(node) ? node : 0; -} - - - -// -// -// foobar -// -char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // Read the element name. - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - - // The closing element is the form. It is - // parsed just like a regular element then deleted from - // the DOM. - if ( *p == '/' ) { - _closingType = CLOSING; - ++p; - } - - p = _value.ParseName( p ); - if ( _value.Empty() ) { - return 0; - } - - p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType != OPEN ) { - return p; - } - - p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); - return p; -} - - - -XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? - for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { - element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? - } - return element; -} - - -bool XMLElement::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLElement* other = compare->ToElement(); - if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { - - const XMLAttribute* a=FirstAttribute(); - const XMLAttribute* b=other->FirstAttribute(); - - while ( a && b ) { - if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { - return false; - } - a = a->Next(); - b = b->Next(); - } - if ( a || b ) { - // different count - return false; - } - return true; - } - return false; -} - - -bool XMLElement::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this, _rootAttribute ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLDocument ----------- // - -// Warning: List must match 'enum XMLError' -const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { - "XML_SUCCESS", - "XML_NO_ATTRIBUTE", - "XML_WRONG_ATTRIBUTE_TYPE", - "XML_ERROR_FILE_NOT_FOUND", - "XML_ERROR_FILE_COULD_NOT_BE_OPENED", - "XML_ERROR_FILE_READ_ERROR", - "XML_ERROR_PARSING_ELEMENT", - "XML_ERROR_PARSING_ATTRIBUTE", - "XML_ERROR_PARSING_TEXT", - "XML_ERROR_PARSING_CDATA", - "XML_ERROR_PARSING_COMMENT", - "XML_ERROR_PARSING_DECLARATION", - "XML_ERROR_PARSING_UNKNOWN", - "XML_ERROR_EMPTY_DOCUMENT", - "XML_ERROR_MISMATCHED_ELEMENT", - "XML_ERROR_PARSING", - "XML_CAN_NOT_CONVERT_TEXT", - "XML_NO_TEXT_NODE", - "XML_ELEMENT_DEPTH_EXCEEDED" -}; - - -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : - XMLNode( 0 ), - _writeBOM( false ), - _processEntities( processEntities ), - _errorID(XML_SUCCESS), - _whitespaceMode( whitespaceMode ), - _errorStr(), - _errorLineNum( 0 ), - _charBuffer( 0 ), - _parseCurLineNum( 0 ), - _parsingDepth(0), - _unlinked(), - _elementPool(), - _attributePool(), - _textPool(), - _commentPool() -{ - // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) - _document = this; -} - - -XMLDocument::~XMLDocument() -{ - Clear(); -} - - -void XMLDocument::MarkInUse(const XMLNode* const node) -{ - TIXMLASSERT(node); - TIXMLASSERT(node->_parent == 0); - - for (int i = 0; i < _unlinked.Size(); ++i) { - if (node == _unlinked[i]) { - _unlinked.SwapRemove(i); - break; - } - } -} - -void XMLDocument::Clear() -{ - DeleteChildren(); - while( _unlinked.Size()) { - DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. - } - -#ifdef TINYXML2_DEBUG - const bool hadError = Error(); -#endif - ClearError(); - - delete [] _charBuffer; - _charBuffer = 0; - _parsingDepth = 0; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef TINYXML2_DEBUG - if ( !hadError ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif -} - - -void XMLDocument::DeepCopy(XMLDocument* target) const -{ - TIXMLASSERT(target); - if (target == this) { - return; // technically success - a no-op. - } - - target->Clear(); - for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { - target->InsertEndChild(node->DeepClone(target)); - } -} - -XMLElement* XMLDocument::NewElement( const char* name ) -{ - XMLElement* ele = CreateUnlinkedNode( _elementPool ); - ele->SetName( name ); - return ele; -} - - -XMLComment* XMLDocument::NewComment( const char* str ) -{ - XMLComment* comment = CreateUnlinkedNode( _commentPool ); - comment->SetValue( str ); - return comment; -} - - -XMLText* XMLDocument::NewText( const char* str ) -{ - XMLText* text = CreateUnlinkedNode( _textPool ); - text->SetValue( str ); - return text; -} - - -XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) -{ - XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); - dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); - return dec; -} - - -XMLUnknown* XMLDocument::NewUnknown( const char* str ) -{ - XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); - unk->SetValue( str ); - return unk; -} - -static FILE* callfopen( const char* filepath, const char* mode ) -{ - TIXMLASSERT( filepath ); - TIXMLASSERT( mode ); -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - FILE* fp = 0; - const errno_t err = fopen_s( &fp, filepath, mode ); - if ( err ) { - return 0; - } -#else - FILE* fp = fopen( filepath, mode ); -#endif - return fp; -} - -void XMLDocument::DeleteNode( XMLNode* node ) { - TIXMLASSERT( node ); - TIXMLASSERT(node->_document == this ); - if (node->_parent) { - node->_parent->DeleteChild( node ); - } - else { - // Isn't in the tree. - // Use the parent delete. - // Also, we need to mark it tracked: we 'know' - // it was never used. - node->_memPool->SetTracked(); - // Call the static XMLNode version: - XMLNode::DeleteNode(node); - } -} - - -XMLError XMLDocument::LoadFile( const char* filename ) -{ - if ( !filename ) { - TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); - return _errorID; - } - - Clear(); - FILE* fp = callfopen( filename, "rb" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ); - return _errorID; - } - LoadFile( fp ); - fclose( fp ); - return _errorID; -} - -// This is likely overengineered template art to have a check that unsigned long value incremented -// by one still fits into size_t. If size_t type is larger than unsigned long type -// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit -// -Wtype-limits warning. This piece makes the compiler select code with a check when a check -// is useful and code with no check when a check is redundant depending on how size_t and unsigned long -// types sizes relate to each other. -template -= sizeof(size_t))> -struct LongFitsIntoSizeTMinusOne { - static bool Fits( unsigned long value ) - { - return value < static_cast(-1); - } -}; - -template <> -struct LongFitsIntoSizeTMinusOne { - static bool Fits( unsigned long ) - { - return true; - } -}; - -XMLError XMLDocument::LoadFile( FILE* fp ) -{ - Clear(); - - fseek( fp, 0, SEEK_SET ); - if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - fseek( fp, 0, SEEK_END ); - const long filelength = ftell( fp ); - fseek( fp, 0, SEEK_SET ); - if ( filelength == -1L ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - TIXMLASSERT( filelength >= 0 ); - - if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { - // Cannot handle files which won't fit in buffer together with null terminator - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - if ( filelength == 0 ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - - const size_t size = filelength; - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = new char[size+1]; - const size_t read = fread( _charBuffer, 1, size, fp ); - if ( read != size ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - _charBuffer[size] = 0; - - Parse(); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( const char* filename, bool compact ) -{ - if ( !filename ) { - TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); - return _errorID; - } - - FILE* fp = callfopen( filename, "w" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ); - return _errorID; - } - SaveFile(fp, compact); - fclose( fp ); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) -{ - // Clear any error from the last save, otherwise it will get reported - // for *this* call. - ClearError(); - XMLPrinter stream( fp, compact ); - Print( &stream ); - return _errorID; -} - - -XMLError XMLDocument::Parse( const char* p, size_t len ) -{ - Clear(); - - if ( len == 0 || !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - if ( len == static_cast(-1) ) { - len = strlen( p ); - } - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = new char[ len+1 ]; - memcpy( _charBuffer, p, len ); - _charBuffer[len] = 0; - - Parse(); - if ( Error() ) { - // clean up now essentially dangling memory. - // and the parse fail can put objects in the - // pools that are dead and inaccessible. - DeleteChildren(); - _elementPool.Clear(); - _attributePool.Clear(); - _textPool.Clear(); - _commentPool.Clear(); - } - return _errorID; -} - - -void XMLDocument::Print( XMLPrinter* streamer ) const -{ - if ( streamer ) { - Accept( streamer ); - } - else { - XMLPrinter stdoutStreamer( stdout ); - Accept( &stdoutStreamer ); - } -} - - -void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... ) -{ - TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); - _errorID = error; - _errorLineNum = lineNum; - _errorStr.Reset(); - - const size_t BUFFER_SIZE = 1000; - char* buffer = new char[BUFFER_SIZE]; - - TIXMLASSERT(sizeof(error) <= sizeof(int)); - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum); - - if (format) { - size_t len = strlen(buffer); - TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": "); - len = strlen(buffer); - - va_list va; - va_start(va, format); - TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va); - va_end(va); - } - _errorStr.SetStr(buffer); - delete[] buffer; -} - - -/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID) -{ - TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT ); - const char* errorName = _errorNames[errorID]; - TIXMLASSERT( errorName && errorName[0] ); - return errorName; -} - -const char* XMLDocument::ErrorStr() const -{ - return _errorStr.Empty() ? "" : _errorStr.GetStr(); -} - - -void XMLDocument::PrintError() const -{ - printf("%s\n", ErrorStr()); -} - -const char* XMLDocument::ErrorName() const -{ - return ErrorIDToName(_errorID); -} - -void XMLDocument::Parse() -{ - TIXMLASSERT( NoChildren() ); // Clear() must have been called previously - TIXMLASSERT( _charBuffer ); - _parseCurLineNum = 1; - _parseLineNum = 1; - char* p = _charBuffer; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); - if ( !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return; - } - ParseDeep(p, 0, &_parseCurLineNum ); -} - -void XMLDocument::PushDepth() -{ - _parsingDepth++; - if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) { - SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." ); - } -} - -void XMLDocument::PopDepth() -{ - TIXMLASSERT(_parsingDepth > 0); - --_parsingDepth; -} - -XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : - _elementJustOpened( false ), - _stack(), - _firstElement( true ), - _fp( file ), - _depth( depth ), - _textDepth( -1 ), - _processEntities( true ), - _compactMode( compact ), - _buffer() -{ - for( int i=0; i(entityValue); - TIXMLASSERT( flagIndex < ENTITY_RANGE ); - _entityFlag[flagIndex] = true; - } - _restrictedEntityFlag[static_cast('&')] = true; - _restrictedEntityFlag[static_cast('<')] = true; - _restrictedEntityFlag[static_cast('>')] = true; // not required, but consistency is nice - _buffer.Push( 0 ); -} - - -void XMLPrinter::Print( const char* format, ... ) -{ - va_list va; - va_start( va, format ); - - if ( _fp ) { - vfprintf( _fp, format, va ); - } - else { - const int len = TIXML_VSCPRINTF( format, va ); - // Close out and re-start the va-args - va_end( va ); - TIXMLASSERT( len >= 0 ); - va_start( va, format ); - TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); - char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. - TIXML_VSNPRINTF( p, len+1, format, va ); - } - va_end( va ); -} - - -void XMLPrinter::Write( const char* data, size_t size ) -{ - if ( _fp ) { - fwrite ( data , sizeof(char), size, _fp); - } - else { - char* p = _buffer.PushArr( static_cast(size) ) - 1; // back up over the null terminator. - memcpy( p, data, size ); - p[size] = 0; - } -} - - -void XMLPrinter::Putc( char ch ) -{ - if ( _fp ) { - fputc ( ch, _fp); - } - else { - char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator. - p[0] = ch; - p[1] = 0; - } -} - - -void XMLPrinter::PrintSpace( int depth ) -{ - for( int i=0; i 0 && *q < ENTITY_RANGE ) { - // Check for entities. If one is found, flush - // the stream up until the entity, write the - // entity, and keep looking. - if ( flag[static_cast(*q)] ) { - while ( p < q ) { - const size_t delta = q - p; - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast(delta); - Write( p, toPrint ); - p += toPrint; - } - bool entityPatternPrinted = false; - for( int i=0; i(delta); - Write( p, toPrint ); - } - } - else { - Write( p ); - } -} - - -void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) -{ - if ( writeBOM ) { - static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; - Write( reinterpret_cast< const char* >( bom ) ); - } - if ( writeDec ) { - PushDeclaration( "xml version=\"1.0\"" ); - } -} - - -void XMLPrinter::OpenElement( const char* name, bool compactMode ) -{ - SealElementIfJustOpened(); - _stack.Push( name ); - - if ( _textDepth < 0 && !_firstElement && !compactMode ) { - Putc( '\n' ); - PrintSpace( _depth ); - } - - Write ( "<" ); - Write ( name ); - - _elementJustOpened = true; - _firstElement = false; - ++_depth; -} - - -void XMLPrinter::PushAttribute( const char* name, const char* value ) -{ - TIXMLASSERT( _elementJustOpened ); - Putc ( ' ' ); - Write( name ); - Write( "=\"" ); - PrintString( value, false ); - Putc ( '\"' ); -} - - -void XMLPrinter::PushAttribute( const char* name, int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute(const char* name, int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - PushAttribute(name, buf); -} - - -void XMLPrinter::PushAttribute(const char* name, uint64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - PushAttribute(name, buf); -} - - -void XMLPrinter::PushAttribute( const char* name, bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::CloseElement( bool compactMode ) -{ - --_depth; - const char* name = _stack.Pop(); - - if ( _elementJustOpened ) { - Write( "/>" ); - } - else { - if ( _textDepth < 0 && !compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - Write ( "" ); - } - - if ( _textDepth == _depth ) { - _textDepth = -1; - } - if ( _depth == 0 && !compactMode) { - Putc( '\n' ); - } - _elementJustOpened = false; -} - - -void XMLPrinter::SealElementIfJustOpened() -{ - if ( !_elementJustOpened ) { - return; - } - _elementJustOpened = false; - Putc( '>' ); -} - - -void XMLPrinter::PushText( const char* text, bool cdata ) -{ - _textDepth = _depth-1; - - SealElementIfJustOpened(); - if ( cdata ) { - Write( "" ); - } - else { - PrintString( text, true ); - } -} - - -void XMLPrinter::PushText( int64_t value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( uint64_t value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(value, buf, BUF_SIZE); - PushText(buf, false); -} - - -void XMLPrinter::PushText( int value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( unsigned value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( bool value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( float value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( double value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushComment( const char* comment ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "" ); -} - - -void XMLPrinter::PushDeclaration( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "" ); -} - - -void XMLPrinter::PushUnknown( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "' ); -} - - -bool XMLPrinter::VisitEnter( const XMLDocument& doc ) -{ - _processEntities = doc.ProcessEntities(); - if ( doc.HasBOM() ) { - PushHeader( true, false ); - } - return true; -} - - -bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) -{ - const XMLElement* parentElem = 0; - if ( element.Parent() ) { - parentElem = element.Parent()->ToElement(); - } - const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; - OpenElement( element.Name(), compactMode ); - while ( attribute ) { - PushAttribute( attribute->Name(), attribute->Value() ); - attribute = attribute->Next(); - } - return true; -} - - -bool XMLPrinter::VisitExit( const XMLElement& element ) -{ - CloseElement( CompactMode(element) ); - return true; -} - - -bool XMLPrinter::Visit( const XMLText& text ) -{ - PushText( text.Value(), text.CData() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLComment& comment ) -{ - PushComment( comment.Value() ); - return true; -} - -bool XMLPrinter::Visit( const XMLDeclaration& declaration ) -{ - PushDeclaration( declaration.Value() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLUnknown& unknown ) -{ - PushUnknown( unknown.Value() ); - return true; -} - -} // namespace tinyxml2 diff --git a/soh/soh/Enhancements/randomizer/3drando/tinyxml2.h b/soh/soh/Enhancements/randomizer/3drando/tinyxml2.h deleted file mode 100644 index 093de69bf..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/tinyxml2.h +++ /dev/null @@ -1,2365 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#ifndef TINYXML2_INCLUDED -#define TINYXML2_INCLUDED - -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) -# include -# include -# include -# include -# include -# if defined(__PS3__) -# include -# endif -#else -# include -# include -# include -# include -# include -#endif -#include - -/* - TODO: intern strings instead of allocation. -*/ -/* - gcc: - g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe - - Formatting, Artistic Style: - AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h -*/ - -#if defined( _DEBUG ) || defined (__DEBUG__) -# ifndef TINYXML2_DEBUG -# define TINYXML2_DEBUG -# endif -#endif - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4251) -#endif - -#ifdef _WIN32 -# ifdef TINYXML2_EXPORT -# define TINYXML2_LIB __declspec(dllexport) -# elif defined(TINYXML2_IMPORT) -# define TINYXML2_LIB __declspec(dllimport) -# else -# define TINYXML2_LIB -# endif -#elif __GNUC__ >= 4 -# define TINYXML2_LIB __attribute__((visibility("default"))) -#else -# define TINYXML2_LIB -#endif - - -#if defined(TINYXML2_DEBUG) -# if defined(_MSC_VER) -# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like -# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } -# elif defined (ANDROID_NDK) -# include -# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } -# else -# include -# define TIXMLASSERT assert -# endif -#else -# define TIXMLASSERT( x ) {} -#endif - - -/* Versioning, past 1.0.14: - http://semver.org/ -*/ -static const int TIXML2_MAJOR_VERSION = 8; -static const int TIXML2_MINOR_VERSION = 0; -static const int TIXML2_PATCH_VERSION = 0; - -#define TINYXML2_MAJOR_VERSION 8 -#define TINYXML2_MINOR_VERSION 0 -#define TINYXML2_PATCH_VERSION 0 - -// A fixed element depth limit is problematic. There needs to be a -// limit to avoid a stack overflow. However, that limit varies per -// system, and the capacity of the stack. On the other hand, it's a trivial -// attack that can result from ill, malicious, or even correctly formed XML, -// so there needs to be a limit in place. -static const int TINYXML2_MAX_ELEMENT_DEPTH = 100; - -namespace tinyxml2 -{ -class XMLDocument; -class XMLElement; -class XMLAttribute; -class XMLComment; -class XMLText; -class XMLDeclaration; -class XMLUnknown; -class XMLPrinter; - -/* - A class that wraps strings. Normally stores the start and end - pointers into the XML file itself, and will apply normalization - and entity translation if actually read. Can also store (and memory - manage) a traditional char[] - - Isn't clear why TINYXML2_LIB is needed; but seems to fix #719 -*/ -class TINYXML2_LIB StrPair -{ -public: - enum { - NEEDS_ENTITY_PROCESSING = 0x01, - NEEDS_NEWLINE_NORMALIZATION = 0x02, - NEEDS_WHITESPACE_COLLAPSING = 0x04, - - TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_NAME = 0, - ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - COMMENT = NEEDS_NEWLINE_NORMALIZATION - }; - - StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} - ~StrPair(); - - void Set( char* start, char* end, int flags ) { - TIXMLASSERT( start ); - TIXMLASSERT( end ); - Reset(); - _start = start; - _end = end; - _flags = flags | NEEDS_FLUSH; - } - - const char* GetStr(); - - bool Empty() const { - return _start == _end; - } - - void SetInternedStr( const char* str ) { - Reset(); - _start = const_cast(str); - } - - void SetStr( const char* str, int flags=0 ); - - char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr ); - char* ParseName( char* in ); - - void TransferTo( StrPair* other ); - void Reset(); - -private: - void CollapseWhitespace(); - - enum { - NEEDS_FLUSH = 0x100, - NEEDS_DELETE = 0x200 - }; - - int _flags; - char* _start; - char* _end; - - StrPair( const StrPair& other ); // not supported - void operator=( const StrPair& other ); // not supported, use TransferTo() -}; - - -/* - A dynamic array of Plain Old Data. Doesn't support constructors, etc. - Has a small initial memory pool, so that low or no usage will not - cause a call to new/delete -*/ -template -class DynArray -{ -public: - DynArray() : - _mem( _pool ), - _allocated( INITIAL_SIZE ), - _size( 0 ) - { - } - - ~DynArray() { - if ( _mem != _pool ) { - delete [] _mem; - } - } - - void Clear() { - _size = 0; - } - - void Push( T t ) { - TIXMLASSERT( _size < INT_MAX ); - EnsureCapacity( _size+1 ); - _mem[_size] = t; - ++_size; - } - - T* PushArr( int count ) { - TIXMLASSERT( count >= 0 ); - TIXMLASSERT( _size <= INT_MAX - count ); - EnsureCapacity( _size+count ); - T* ret = &_mem[_size]; - _size += count; - return ret; - } - - T Pop() { - TIXMLASSERT( _size > 0 ); - --_size; - return _mem[_size]; - } - - void PopArr( int count ) { - TIXMLASSERT( _size >= count ); - _size -= count; - } - - bool Empty() const { - return _size == 0; - } - - T& operator[](int i) { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - const T& operator[](int i) const { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - const T& PeekTop() const { - TIXMLASSERT( _size > 0 ); - return _mem[ _size - 1]; - } - - int Size() const { - TIXMLASSERT( _size >= 0 ); - return _size; - } - - int Capacity() const { - TIXMLASSERT( _allocated >= INITIAL_SIZE ); - return _allocated; - } - - void SwapRemove(int i) { - TIXMLASSERT(i >= 0 && i < _size); - TIXMLASSERT(_size > 0); - _mem[i] = _mem[_size - 1]; - --_size; - } - - const T* Mem() const { - TIXMLASSERT( _mem ); - return _mem; - } - - T* Mem() { - TIXMLASSERT( _mem ); - return _mem; - } - -private: - DynArray( const DynArray& ); // not supported - void operator=( const DynArray& ); // not supported - - void EnsureCapacity( int cap ) { - TIXMLASSERT( cap > 0 ); - if ( cap > _allocated ) { - TIXMLASSERT( cap <= INT_MAX / 2 ); - const int newAllocated = cap * 2; - T* newMem = new T[newAllocated]; - TIXMLASSERT( newAllocated >= _size ); - memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs - if ( _mem != _pool ) { - delete [] _mem; - } - _mem = newMem; - _allocated = newAllocated; - } - } - - T* _mem; - T _pool[INITIAL_SIZE]; - int _allocated; // objects allocated - int _size; // number objects in use -}; - - -/* - Parent virtual class of a pool for fast allocation - and deallocation of objects. -*/ -class MemPool -{ -public: - MemPool() {} - virtual ~MemPool() {} - - virtual int ItemSize() const = 0; - virtual void* Alloc() = 0; - virtual void Free( void* ) = 0; - virtual void SetTracked() = 0; -}; - - -/* - Template child class to create pools of the correct type. -*/ -template< int ITEM_SIZE > -class MemPoolT : public MemPool -{ -public: - MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} - ~MemPoolT() { - MemPoolT< ITEM_SIZE >::Clear(); - } - - void Clear() { - // Delete the blocks. - while( !_blockPtrs.Empty()) { - Block* lastBlock = _blockPtrs.Pop(); - delete lastBlock; - } - _root = 0; - _currentAllocs = 0; - _nAllocs = 0; - _maxAllocs = 0; - _nUntracked = 0; - } - - virtual int ItemSize() const { - return ITEM_SIZE; - } - int CurrentAllocs() const { - return _currentAllocs; - } - - virtual void* Alloc() { - if ( !_root ) { - // Need a new block. - Block* block = new Block(); - _blockPtrs.Push( block ); - - Item* blockItems = block->items; - for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) { - blockItems[i].next = &(blockItems[i + 1]); - } - blockItems[ITEMS_PER_BLOCK - 1].next = 0; - _root = blockItems; - } - Item* const result = _root; - TIXMLASSERT( result != 0 ); - _root = _root->next; - - ++_currentAllocs; - if ( _currentAllocs > _maxAllocs ) { - _maxAllocs = _currentAllocs; - } - ++_nAllocs; - ++_nUntracked; - return result; - } - - virtual void Free( void* mem ) { - if ( !mem ) { - return; - } - --_currentAllocs; - Item* item = static_cast( mem ); -#ifdef TINYXML2_DEBUG - memset( item, 0xfe, sizeof( *item ) ); -#endif - item->next = _root; - _root = item; - } - void Trace( const char* name ) { - printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", - name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs, - ITEM_SIZE, _nAllocs, _blockPtrs.Size() ); - } - - void SetTracked() { - --_nUntracked; - } - - int Untracked() const { - return _nUntracked; - } - - // This number is perf sensitive. 4k seems like a good tradeoff on my machine. - // The test file is large, 170k. - // Release: VS2010 gcc(no opt) - // 1k: 4000 - // 2k: 4000 - // 4k: 3900 21000 - // 16k: 5200 - // 32k: 4300 - // 64k: 4000 21000 - // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK - // in private part if ITEMS_PER_BLOCK is private - enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE }; - -private: - MemPoolT( const MemPoolT& ); // not supported - void operator=( const MemPoolT& ); // not supported - - union Item { - Item* next; - char itemData[ITEM_SIZE]; - }; - struct Block { - Item items[ITEMS_PER_BLOCK]; - }; - DynArray< Block*, 10 > _blockPtrs; - Item* _root; - - int _currentAllocs; - int _nAllocs; - int _maxAllocs; - int _nUntracked; -}; - - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a XMLVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its siblings will be visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the XMLDocument, although all nodes support visiting. - - You should never change the document from a callback. - - @sa XMLNode::Accept() -*/ -class TINYXML2_LIB XMLVisitor -{ -public: - virtual ~XMLVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { - return true; - } - /// Visit a document. - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - /// Visit an element. - virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { - return true; - } - /// Visit an element. - virtual bool VisitExit( const XMLElement& /*element*/ ) { - return true; - } - - /// Visit a declaration. - virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { - return true; - } - /// Visit a text node. - virtual bool Visit( const XMLText& /*text*/ ) { - return true; - } - /// Visit a comment node. - virtual bool Visit( const XMLComment& /*comment*/ ) { - return true; - } - /// Visit an unknown node. - virtual bool Visit( const XMLUnknown& /*unknown*/ ) { - return true; - } -}; - -// WARNING: must match XMLDocument::_errorNames[] -enum XMLError { - XML_SUCCESS = 0, - XML_NO_ATTRIBUTE, - XML_WRONG_ATTRIBUTE_TYPE, - XML_ERROR_FILE_NOT_FOUND, - XML_ERROR_FILE_COULD_NOT_BE_OPENED, - XML_ERROR_FILE_READ_ERROR, - XML_ERROR_PARSING_ELEMENT, - XML_ERROR_PARSING_ATTRIBUTE, - XML_ERROR_PARSING_TEXT, - XML_ERROR_PARSING_CDATA, - XML_ERROR_PARSING_COMMENT, - XML_ERROR_PARSING_DECLARATION, - XML_ERROR_PARSING_UNKNOWN, - XML_ERROR_EMPTY_DOCUMENT, - XML_ERROR_MISMATCHED_ELEMENT, - XML_ERROR_PARSING, - XML_CAN_NOT_CONVERT_TEXT, - XML_NO_TEXT_NODE, - XML_ELEMENT_DEPTH_EXCEEDED, - - XML_ERROR_COUNT -}; - - -/* - Utility functionality. -*/ -class TINYXML2_LIB XMLUtil -{ -public: - static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { - TIXMLASSERT( p ); - - while( IsWhiteSpace(*p) ) { - if (curLineNumPtr && *p == '\n') { - ++(*curLineNumPtr); - } - ++p; - } - TIXMLASSERT( p ); - return p; - } - static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) { - return const_cast( SkipWhiteSpace( const_cast(p), curLineNumPtr ) ); - } - - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't - // correct, but simple, and usually works. - static bool IsWhiteSpace( char p ) { - return !IsUTF8Continuation(p) && isspace( static_cast(p) ); - } - - inline static bool IsNameStartChar( unsigned char ch ) { - if ( ch >= 128 ) { - // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() - return true; - } - if ( isalpha( ch ) ) { - return true; - } - return ch == ':' || ch == '_'; - } - - inline static bool IsNameChar( unsigned char ch ) { - return IsNameStartChar( ch ) - || isdigit( ch ) - || ch == '.' - || ch == '-'; - } - - inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { - if ( p == q ) { - return true; - } - TIXMLASSERT( p ); - TIXMLASSERT( q ); - TIXMLASSERT( nChar >= 0 ); - return strncmp( p, q, nChar ) == 0; - } - - inline static bool IsUTF8Continuation( const char p ) { - return ( p & 0x80 ) != 0; - } - - static const char* ReadBOM( const char* p, bool* hasBOM ); - // p is the starting location, - // the UTF-8 value of the entity will be placed in value, and length filled in. - static const char* GetCharacterRef( const char* p, char* value, int* length ); - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - - // converts primitive types to strings - static void ToStr( int v, char* buffer, int bufferSize ); - static void ToStr( unsigned v, char* buffer, int bufferSize ); - static void ToStr( bool v, char* buffer, int bufferSize ); - static void ToStr( float v, char* buffer, int bufferSize ); - static void ToStr( double v, char* buffer, int bufferSize ); - static void ToStr(int64_t v, char* buffer, int bufferSize); - static void ToStr(uint64_t v, char* buffer, int bufferSize); - - // converts strings to primitive types - static bool ToInt( const char* str, int* value ); - static bool ToUnsigned( const char* str, unsigned* value ); - static bool ToBool( const char* str, bool* value ); - static bool ToFloat( const char* str, float* value ); - static bool ToDouble( const char* str, double* value ); - static bool ToInt64(const char* str, int64_t* value); - static bool ToUnsigned64(const char* str, uint64_t* value); - // Changes what is serialized for a boolean value. - // Default to "true" and "false". Shouldn't be changed - // unless you have a special testing or compatibility need. - // Be careful: static, global, & not thread safe. - // Be sure to set static const memory as parameters. - static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); - -private: - static const char* writeBoolTrue; - static const char* writeBoolFalse; -}; - - -/** XMLNode is a base class for every object that is in the - XML Document Object Model (DOM), except XMLAttributes. - Nodes have siblings, a parent, and children which can - be navigated. A node is always in a XMLDocument. - The type of a XMLNode can be queried, and it can - be cast to its more defined type. - - A XMLDocument allocates memory for all its Nodes. - When the XMLDocument gets deleted, all its Nodes - will also be deleted. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - @endverbatim -*/ -class TINYXML2_LIB XMLNode -{ - friend class XMLDocument; - friend class XMLElement; -public: - - /// Get the XMLDocument that owns this XMLNode. - const XMLDocument* GetDocument() const { - TIXMLASSERT( _document ); - return _document; - } - /// Get the XMLDocument that owns this XMLNode. - XMLDocument* GetDocument() { - TIXMLASSERT( _document ); - return _document; - } - - /// Safely cast to an Element, or null. - virtual XMLElement* ToElement() { - return 0; - } - /// Safely cast to Text, or null. - virtual XMLText* ToText() { - return 0; - } - /// Safely cast to a Comment, or null. - virtual XMLComment* ToComment() { - return 0; - } - /// Safely cast to a Document, or null. - virtual XMLDocument* ToDocument() { - return 0; - } - /// Safely cast to a Declaration, or null. - virtual XMLDeclaration* ToDeclaration() { - return 0; - } - /// Safely cast to an Unknown, or null. - virtual XMLUnknown* ToUnknown() { - return 0; - } - - virtual const XMLElement* ToElement() const { - return 0; - } - virtual const XMLText* ToText() const { - return 0; - } - virtual const XMLComment* ToComment() const { - return 0; - } - virtual const XMLDocument* ToDocument() const { - return 0; - } - virtual const XMLDeclaration* ToDeclaration() const { - return 0; - } - virtual const XMLUnknown* ToUnknown() const { - return 0; - } - - /** The meaning of 'value' changes for the specific type. - @verbatim - Document: empty (NULL is returned, not an empty string) - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - const char* Value() const; - - /** Set the Value of an XML node. - @sa Value() - */ - void SetValue( const char* val, bool staticMem=false ); - - /// Gets the line number the node is in, if the document was parsed from a file. - int GetLineNum() const { return _parseLineNum; } - - /// Get the parent of this node on the DOM. - const XMLNode* Parent() const { - return _parent; - } - - XMLNode* Parent() { - return _parent; - } - - /// Returns true if this node has no children. - bool NoChildren() const { - return !_firstChild; - } - - /// Get the first child node, or null if none exists. - const XMLNode* FirstChild() const { - return _firstChild; - } - - XMLNode* FirstChild() { - return _firstChild; - } - - /** Get the first child element, or optionally the first child - element with the specified name. - */ - const XMLElement* FirstChildElement( const char* name = 0 ) const; - - XMLElement* FirstChildElement( const char* name = 0 ) { - return const_cast(const_cast(this)->FirstChildElement( name )); - } - - /// Get the last child node, or null if none exists. - const XMLNode* LastChild() const { - return _lastChild; - } - - XMLNode* LastChild() { - return _lastChild; - } - - /** Get the last child element or optionally the last child - element with the specified name. - */ - const XMLElement* LastChildElement( const char* name = 0 ) const; - - XMLElement* LastChildElement( const char* name = 0 ) { - return const_cast(const_cast(this)->LastChildElement(name) ); - } - - /// Get the previous (left) sibling node of this node. - const XMLNode* PreviousSibling() const { - return _prev; - } - - XMLNode* PreviousSibling() { - return _prev; - } - - /// Get the previous (left) sibling element of this node, with an optionally supplied name. - const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; - - XMLElement* PreviousSiblingElement( const char* name = 0 ) { - return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); - } - - /// Get the next (right) sibling node of this node. - const XMLNode* NextSibling() const { - return _next; - } - - XMLNode* NextSibling() { - return _next; - } - - /// Get the next (right) sibling element of this node, with an optionally supplied name. - const XMLElement* NextSiblingElement( const char* name = 0 ) const; - - XMLElement* NextSiblingElement( const char* name = 0 ) { - return const_cast(const_cast(this)->NextSiblingElement( name ) ); - } - - /** - Add a child node as the last (right) child. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the node does not - belong to the same document. - */ - XMLNode* InsertEndChild( XMLNode* addThis ); - - XMLNode* LinkEndChild( XMLNode* addThis ) { - return InsertEndChild( addThis ); - } - /** - Add a child node as the first (left) child. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the node does not - belong to the same document. - */ - XMLNode* InsertFirstChild( XMLNode* addThis ); - /** - Add a node after the specified child node. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the afterThis node - is not a child of this node, or if the node does not - belong to the same document. - */ - XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); - - /** - Delete all the children of this node. - */ - void DeleteChildren(); - - /** - Delete a child of this node. - */ - void DeleteChild( XMLNode* node ); - - /** - Make a copy of this node, but not its children. - You may pass in a Document pointer that will be - the owner of the new Node. If the 'document' is - null, then the node returned will be allocated - from the current Document. (this->GetDocument()) - - Note: if called on a XMLDocument, this will return null. - */ - virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; - - /** - Make a copy of this node and all its children. - - If the 'target' is null, then the nodes will - be allocated in the current document. If 'target' - is specified, the memory will be allocated is the - specified XMLDocument. - - NOTE: This is probably not the correct tool to - copy a document, since XMLDocuments can have multiple - top level XMLNodes. You probably want to use - XMLDocument::DeepCopy() - */ - XMLNode* DeepClone( XMLDocument* target ) const; - - /** - Test if 2 nodes are the same, but don't test children. - The 2 nodes do not need to be in the same Document. - - Note: if called on a XMLDocument, this will return false. - */ - virtual bool ShallowEqual( const XMLNode* compare ) const = 0; - - /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the XMLVisitor interface. - - This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - XMLPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( XMLVisitor* visitor ) const = 0; - - /** - Set user data into the XMLNode. TinyXML-2 in - no way processes or interprets user data. - It is initially 0. - */ - void SetUserData(void* userData) { _userData = userData; } - - /** - Get user data set into the XMLNode. TinyXML-2 in - no way processes or interprets user data. - It is initially 0. - */ - void* GetUserData() const { return _userData; } - -protected: - explicit XMLNode( XMLDocument* ); - virtual ~XMLNode(); - - virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); - - XMLDocument* _document; - XMLNode* _parent; - mutable StrPair _value; - int _parseLineNum; - - XMLNode* _firstChild; - XMLNode* _lastChild; - - XMLNode* _prev; - XMLNode* _next; - - void* _userData; - -private: - MemPool* _memPool; - void Unlink( XMLNode* child ); - static void DeleteNode( XMLNode* node ); - void InsertChildPreamble( XMLNode* insertThis ) const; - const XMLElement* ToElementWithName( const char* name ) const; - - XMLNode( const XMLNode& ); // not supported - XMLNode& operator=( const XMLNode& ); // not supported -}; - - -/** XML text. - - Note that a text node can have child element nodes, for example: - @verbatim - This is bold - @endverbatim - - A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCData() and query it with CData(). -*/ -class TINYXML2_LIB XMLText : public XMLNode -{ - friend class XMLDocument; -public: - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLText* ToText() { - return this; - } - virtual const XMLText* ToText() const { - return this; - } - - /// Declare whether this should be CDATA or standard text. - void SetCData( bool isCData ) { - _isCData = isCData; - } - /// Returns true if this is a CDATA text element. - bool CData() const { - return _isCData; - } - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} - virtual ~XMLText() {} - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - bool _isCData; - - XMLText( const XMLText& ); // not supported - XMLText& operator=( const XMLText& ); // not supported -}; - - -/** An XML Comment. */ -class TINYXML2_LIB XMLComment : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLComment* ToComment() { - return this; - } - virtual const XMLComment* ToComment() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - explicit XMLComment( XMLDocument* doc ); - virtual ~XMLComment(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); - -private: - XMLComment( const XMLComment& ); // not supported - XMLComment& operator=( const XMLComment& ); // not supported -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXML-2 will happily read or write files without a declaration, - however. - - The text of the declaration isn't interpreted. It is parsed - and written as a string. -*/ -class TINYXML2_LIB XMLDeclaration : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLDeclaration* ToDeclaration() { - return this; - } - virtual const XMLDeclaration* ToDeclaration() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - explicit XMLDeclaration( XMLDocument* doc ); - virtual ~XMLDeclaration(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLDeclaration( const XMLDeclaration& ); // not supported - XMLDeclaration& operator=( const XMLDeclaration& ); // not supported -}; - - -/** Any tag that TinyXML-2 doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into XMLUnknowns. -*/ -class TINYXML2_LIB XMLUnknown : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLUnknown* ToUnknown() { - return this; - } - virtual const XMLUnknown* ToUnknown() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - explicit XMLUnknown( XMLDocument* doc ); - virtual ~XMLUnknown(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLUnknown( const XMLUnknown& ); // not supported - XMLUnknown& operator=( const XMLUnknown& ); // not supported -}; - - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not XMLNodes. You may only query the - Next() attribute in a list. -*/ -class TINYXML2_LIB XMLAttribute -{ - friend class XMLElement; -public: - /// The name of the attribute. - const char* Name() const; - - /// The value of the attribute. - const char* Value() const; - - /// Gets the line number the attribute is in, if the document was parsed from a file. - int GetLineNum() const { return _parseLineNum; } - - /// The next attribute in the list. - const XMLAttribute* Next() const { - return _next; - } - - /** IntValue interprets the attribute as an integer, and returns the value. - If the value isn't an integer, 0 will be returned. There is no error checking; - use QueryIntValue() if you need error checking. - */ - int IntValue() const { - int i = 0; - QueryIntValue(&i); - return i; - } - - int64_t Int64Value() const { - int64_t i = 0; - QueryInt64Value(&i); - return i; - } - - uint64_t Unsigned64Value() const { - uint64_t i = 0; - QueryUnsigned64Value(&i); - return i; - } - - /// Query as an unsigned integer. See IntValue() - unsigned UnsignedValue() const { - unsigned i=0; - QueryUnsignedValue( &i ); - return i; - } - /// Query as a boolean. See IntValue() - bool BoolValue() const { - bool b=false; - QueryBoolValue( &b ); - return b; - } - /// Query as a double. See IntValue() - double DoubleValue() const { - double d=0; - QueryDoubleValue( &d ); - return d; - } - /// Query as a float. See IntValue() - float FloatValue() const { - float f=0; - QueryFloatValue( &f ); - return f; - } - - /** QueryIntValue interprets the attribute as an integer, and returns the value - in the provided parameter. The function will return XML_SUCCESS on success, - and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. - */ - XMLError QueryIntValue( int* value ) const; - /// See QueryIntValue - XMLError QueryUnsignedValue( unsigned int* value ) const; - /// See QueryIntValue - XMLError QueryInt64Value(int64_t* value) const; - /// See QueryIntValue - XMLError QueryUnsigned64Value(uint64_t* value) const; - /// See QueryIntValue - XMLError QueryBoolValue( bool* value ) const; - /// See QueryIntValue - XMLError QueryDoubleValue( double* value ) const; - /// See QueryIntValue - XMLError QueryFloatValue( float* value ) const; - - /// Set the attribute to a string value. - void SetAttribute( const char* value ); - /// Set the attribute to value. - void SetAttribute( int value ); - /// Set the attribute to value. - void SetAttribute( unsigned value ); - /// Set the attribute to value. - void SetAttribute(int64_t value); - /// Set the attribute to value. - void SetAttribute(uint64_t value); - /// Set the attribute to value. - void SetAttribute( bool value ); - /// Set the attribute to value. - void SetAttribute( double value ); - /// Set the attribute to value. - void SetAttribute( float value ); - -private: - enum { BUF_SIZE = 200 }; - - XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} - virtual ~XMLAttribute() {} - - XMLAttribute( const XMLAttribute& ); // not supported - void operator=( const XMLAttribute& ); // not supported - void SetName( const char* name ); - - char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr ); - - mutable StrPair _name; - mutable StrPair _value; - int _parseLineNum; - XMLAttribute* _next; - MemPool* _memPool; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TINYXML2_LIB XMLElement : public XMLNode -{ - friend class XMLDocument; -public: - /// Get the name of an element (which is the Value() of the node.) - const char* Name() const { - return Value(); - } - /// Set the name of the element. - void SetName( const char* str, bool staticMem=false ) { - SetValue( str, staticMem ); - } - - virtual XMLElement* ToElement() { - return this; - } - virtual const XMLElement* ToElement() const { - return this; - } - virtual bool Accept( XMLVisitor* visitor ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none - exists. For example: - - @verbatim - const char* value = ele->Attribute( "foo" ); - @endverbatim - - The 'value' parameter is normally null. However, if specified, - the attribute will only be returned if the 'name' and 'value' - match. This allow you to write code: - - @verbatim - if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); - @endverbatim - - rather than: - @verbatim - if ( ele->Attribute( "foo" ) ) { - if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); - } - @endverbatim - */ - const char* Attribute( const char* name, const char* value=0 ) const; - - /** Given an attribute name, IntAttribute() returns the value - of the attribute interpreted as an integer. The default - value will be returned if the attribute isn't present, - or if there is an error. (For a method with error - checking, see QueryIntAttribute()). - */ - int IntAttribute(const char* name, int defaultValue = 0) const; - /// See IntAttribute() - unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const; - /// See IntAttribute() - int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const; - /// See IntAttribute() - uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const; - /// See IntAttribute() - bool BoolAttribute(const char* name, bool defaultValue = false) const; - /// See IntAttribute() - double DoubleAttribute(const char* name, double defaultValue = 0) const; - /// See IntAttribute() - float FloatAttribute(const char* name, float defaultValue = 0) const; - - /** Given an attribute name, QueryIntAttribute() returns - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - XMLError QueryIntAttribute( const char* name, int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryIntValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryUnsignedValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryInt64Attribute(const char* name, int64_t* value) const { - const XMLAttribute* a = FindAttribute(name); - if (!a) { - return XML_NO_ATTRIBUTE; - } - return a->QueryInt64Value(value); - } - - /// See QueryIntAttribute() - XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const { - const XMLAttribute* a = FindAttribute(name); - if(!a) { - return XML_NO_ATTRIBUTE; - } - return a->QueryUnsigned64Value(value); - } - - /// See QueryIntAttribute() - XMLError QueryBoolAttribute( const char* name, bool* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryBoolValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryDoubleAttribute( const char* name, double* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryDoubleValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryFloatAttribute( const char* name, float* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryFloatValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryStringAttribute(const char* name, const char** value) const { - const XMLAttribute* a = FindAttribute(name); - if (!a) { - return XML_NO_ATTRIBUTE; - } - *value = a->Value(); - return XML_SUCCESS; - } - - - - /** Given an attribute name, QueryAttribute() returns - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. It is overloaded for the primitive types, - and is a generally more convenient replacement of - QueryIntAttribute() and related functions. - - If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - XMLError QueryAttribute( const char* name, int* value ) const { - return QueryIntAttribute( name, value ); - } - - XMLError QueryAttribute( const char* name, unsigned int* value ) const { - return QueryUnsignedAttribute( name, value ); - } - - XMLError QueryAttribute(const char* name, int64_t* value) const { - return QueryInt64Attribute(name, value); - } - - XMLError QueryAttribute(const char* name, uint64_t* value) const { - return QueryUnsigned64Attribute(name, value); - } - - XMLError QueryAttribute( const char* name, bool* value ) const { - return QueryBoolAttribute( name, value ); - } - - XMLError QueryAttribute( const char* name, double* value ) const { - return QueryDoubleAttribute( name, value ); - } - - XMLError QueryAttribute( const char* name, float* value ) const { - return QueryFloatAttribute( name, value ); - } - - /// Sets the named attribute to value. - void SetAttribute( const char* name, const char* value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, int value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, unsigned value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - - /// Sets the named attribute to value. - void SetAttribute(const char* name, int64_t value) { - XMLAttribute* a = FindOrCreateAttribute(name); - a->SetAttribute(value); - } - - /// Sets the named attribute to value. - void SetAttribute(const char* name, uint64_t value) { - XMLAttribute* a = FindOrCreateAttribute(name); - a->SetAttribute(value); - } - - /// Sets the named attribute to value. - void SetAttribute( const char* name, bool value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, double value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, float value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - - /** - Delete an attribute. - */ - void DeleteAttribute( const char* name ); - - /// Return the first attribute in the list. - const XMLAttribute* FirstAttribute() const { - return _rootAttribute; - } - /// Query a specific attribute in the list. - const XMLAttribute* FindAttribute( const char* name ) const; - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the XMLText child - and accessing it directly. - - If the first child of 'this' is a XMLText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - */ - const char* GetText() const; - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, SetText() is limited compared to creating an XMLText child - and mutating it directly. - - If the first child of 'this' is a XMLText, SetText() sets its value to - the given string, otherwise it will create a first child that is an XMLText. - - This is a convenient method for setting the text of simple contained text: - @verbatim - This is text - fooElement->SetText( "Hullaballoo!" ); - Hullaballoo! - @endverbatim - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then it will not change "This is text", but rather prefix it with a text element: - @verbatim - Hullaballoo!This is text - @endverbatim - - For this XML: - @verbatim - - @endverbatim - SetText() will generate - @verbatim - Hullaballoo! - @endverbatim - */ - void SetText( const char* inText ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( int value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( unsigned value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText(int64_t value); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText(uint64_t value); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( bool value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( double value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( float value ); - - /** - Convenience method to query the value of a child text node. This is probably best - shown by example. Given you have a document is this form: - @verbatim - - 1 - 1.4 - - @endverbatim - - The QueryIntText() and similar functions provide a safe and easier way to get to the - "value" of x and y. - - @verbatim - int x = 0; - float y = 0; // types of x and y are contrived for example - const XMLElement* xElement = pointElement->FirstChildElement( "x" ); - const XMLElement* yElement = pointElement->FirstChildElement( "y" ); - xElement->QueryIntText( &x ); - yElement->QueryFloatText( &y ); - @endverbatim - - @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted - to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. - - */ - XMLError QueryIntText( int* ival ) const; - /// See QueryIntText() - XMLError QueryUnsignedText( unsigned* uval ) const; - /// See QueryIntText() - XMLError QueryInt64Text(int64_t* uval) const; - /// See QueryIntText() - XMLError QueryUnsigned64Text(uint64_t* uval) const; - /// See QueryIntText() - XMLError QueryBoolText( bool* bval ) const; - /// See QueryIntText() - XMLError QueryDoubleText( double* dval ) const; - /// See QueryIntText() - XMLError QueryFloatText( float* fval ) const; - - int IntText(int defaultValue = 0) const; - - /// See QueryIntText() - unsigned UnsignedText(unsigned defaultValue = 0) const; - /// See QueryIntText() - int64_t Int64Text(int64_t defaultValue = 0) const; - /// See QueryIntText() - uint64_t Unsigned64Text(uint64_t defaultValue = 0) const; - /// See QueryIntText() - bool BoolText(bool defaultValue = false) const; - /// See QueryIntText() - double DoubleText(double defaultValue = 0) const; - /// See QueryIntText() - float FloatText(float defaultValue = 0) const; - - /** - Convenience method to create a new XMLElement and add it as last (right) - child of this node. Returns the created and inserted element. - */ - XMLElement* InsertNewChildElement(const char* name); - /// See InsertNewChildElement() - XMLComment* InsertNewComment(const char* comment); - /// See InsertNewChildElement() - XMLText* InsertNewText(const char* text); - /// See InsertNewChildElement() - XMLDeclaration* InsertNewDeclaration(const char* text); - /// See InsertNewChildElement() - XMLUnknown* InsertNewUnknown(const char* text); - - - // internal: - enum ElementClosingType { - OPEN, // - CLOSED, // - CLOSING // - }; - ElementClosingType ClosingType() const { - return _closingType; - } - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLElement( XMLDocument* doc ); - virtual ~XMLElement(); - XMLElement( const XMLElement& ); // not supported - void operator=( const XMLElement& ); // not supported - - XMLAttribute* FindOrCreateAttribute( const char* name ); - char* ParseAttributes( char* p, int* curLineNumPtr ); - static void DeleteAttribute( XMLAttribute* attribute ); - XMLAttribute* CreateAttribute(); - - enum { BUF_SIZE = 200 }; - ElementClosingType _closingType; - // The attribute list is ordered; there is no 'lastAttribute' - // because the list needs to be scanned for dupes before adding - // a new attribute. - XMLAttribute* _rootAttribute; -}; - - -enum Whitespace { - PRESERVE_WHITESPACE, - COLLAPSE_WHITESPACE -}; - - -/** A Document binds together all the functionality. - It can be saved, loaded, and printed to the screen. - All Nodes are connected and allocated to a Document. - If the Document is deleted, all its Nodes are also deleted. -*/ -class TINYXML2_LIB XMLDocument : public XMLNode -{ - friend class XMLElement; - // Gives access to SetError and Push/PopDepth, but over-access for everything else. - // Wishing C++ had "internal" scope. - friend class XMLNode; - friend class XMLText; - friend class XMLComment; - friend class XMLDeclaration; - friend class XMLUnknown; -public: - /// constructor - XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); - ~XMLDocument(); - - virtual XMLDocument* ToDocument() { - TIXMLASSERT( this == _document ); - return this; - } - virtual const XMLDocument* ToDocument() const { - TIXMLASSERT( this == _document ); - return this; - } - - /** - Parse an XML file from a character string. - Returns XML_SUCCESS (0) on success, or - an errorID. - - You may optionally pass in the 'nBytes', which is - the number of bytes which will be parsed. If not - specified, TinyXML-2 will assume 'xml' points to a - null terminated string. - */ - XMLError Parse( const char* xml, size_t nBytes=static_cast(-1) ); - - /** - Load an XML file from disk. - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError LoadFile( const char* filename ); - - /** - Load an XML file from disk. You are responsible - for providing and closing the FILE*. - - NOTE: The file should be opened as binary ("rb") - not text in order for TinyXML-2 to correctly - do newline normalization. - - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError LoadFile( FILE* ); - - /** - Save the XML file to disk. - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError SaveFile( const char* filename, bool compact = false ); - - /** - Save the XML file to disk. You are responsible - for providing and closing the FILE*. - - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError SaveFile( FILE* fp, bool compact = false ); - - bool ProcessEntities() const { - return _processEntities; - } - Whitespace WhitespaceMode() const { - return _whitespaceMode; - } - - /** - Returns true if this document has a leading Byte Order Mark of UTF8. - */ - bool HasBOM() const { - return _writeBOM; - } - /** Sets whether to write the BOM when writing the file. - */ - void SetBOM( bool useBOM ) { - _writeBOM = useBOM; - } - - /** Return the root element of DOM. Equivalent to FirstChildElement(). - To get the first node, use FirstChild(). - */ - XMLElement* RootElement() { - return FirstChildElement(); - } - const XMLElement* RootElement() const { - return FirstChildElement(); - } - - /** Print the Document. If the Printer is not provided, it will - print to stdout. If you provide Printer, this can print to a file: - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Or you can use a printer to print to memory: - @verbatim - XMLPrinter printer; - doc.Print( &printer ); - // printer.CStr() has a const char* to the XML - @endverbatim - */ - void Print( XMLPrinter* streamer=0 ) const; - virtual bool Accept( XMLVisitor* visitor ) const; - - /** - Create a new Element associated with - this Document. The memory for the Element - is managed by the Document. - */ - XMLElement* NewElement( const char* name ); - /** - Create a new Comment associated with - this Document. The memory for the Comment - is managed by the Document. - */ - XMLComment* NewComment( const char* comment ); - /** - Create a new Text associated with - this Document. The memory for the Text - is managed by the Document. - */ - XMLText* NewText( const char* text ); - /** - Create a new Declaration associated with - this Document. The memory for the object - is managed by the Document. - - If the 'text' param is null, the standard - declaration is used.: - @verbatim - - @endverbatim - */ - XMLDeclaration* NewDeclaration( const char* text=0 ); - /** - Create a new Unknown associated with - this Document. The memory for the object - is managed by the Document. - */ - XMLUnknown* NewUnknown( const char* text ); - - /** - Delete a node associated with this document. - It will be unlinked from the DOM. - */ - void DeleteNode( XMLNode* node ); - - void ClearError() { - SetError(XML_SUCCESS, 0, 0); - } - - /// Return true if there was an error parsing the document. - bool Error() const { - return _errorID != XML_SUCCESS; - } - /// Return the errorID. - XMLError ErrorID() const { - return _errorID; - } - const char* ErrorName() const; - static const char* ErrorIDToName(XMLError errorID); - - /** Returns a "long form" error description. A hopefully helpful - diagnostic with location, line number, and/or additional info. - */ - const char* ErrorStr() const; - - /// A (trivial) utility function that prints the ErrorStr() to stdout. - void PrintError() const; - - /// Return the line where the error occurred, or zero if unknown. - int ErrorLineNum() const - { - return _errorLineNum; - } - - /// Clear the document, resetting it to the initial state. - void Clear(); - - /** - Copies this document to a target document. - The target will be completely cleared before the copy. - If you want to copy a sub-tree, see XMLNode::DeepClone(). - - NOTE: that the 'target' must be non-null. - */ - void DeepCopy(XMLDocument* target) const; - - // internal - char* Identify( char* p, XMLNode** node ); - - // internal - void MarkInUse(const XMLNode* const); - - virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { - return 0; - } - virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { - return false; - } - -private: - XMLDocument( const XMLDocument& ); // not supported - void operator=( const XMLDocument& ); // not supported - - bool _writeBOM; - bool _processEntities; - XMLError _errorID; - Whitespace _whitespaceMode; - mutable StrPair _errorStr; - int _errorLineNum; - char* _charBuffer; - int _parseCurLineNum; - int _parsingDepth; - // Memory tracking does add some overhead. - // However, the code assumes that you don't - // have a bunch of unlinked nodes around. - // Therefore it takes less memory to track - // in the document vs. a linked list in the XMLNode, - // and the performance is the same. - DynArray _unlinked; - - MemPoolT< sizeof(XMLElement) > _elementPool; - MemPoolT< sizeof(XMLAttribute) > _attributePool; - MemPoolT< sizeof(XMLText) > _textPool; - MemPoolT< sizeof(XMLComment) > _commentPool; - - static const char* _errorNames[XML_ERROR_COUNT]; - - void Parse(); - - void SetError( XMLError error, int lineNum, const char* format, ... ); - - // Something of an obvious security hole, once it was discovered. - // Either an ill-formed XML or an excessively deep one can overflow - // the stack. Track stack depth, and error out if needed. - class DepthTracker { - public: - explicit DepthTracker(XMLDocument * document) { - this->_document = document; - document->PushDepth(); - } - ~DepthTracker() { - _document->PopDepth(); - } - private: - XMLDocument * _document; - }; - void PushDepth(); - void PopDepth(); - - template - NodeType* CreateUnlinkedNode( MemPoolT& pool ); -}; - -template -inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) -{ - TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); - TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); - NodeType* returnNode = new (pool.Alloc()) NodeType( this ); - TIXMLASSERT( returnNode ); - returnNode->_memPool = &pool; - - _unlinked.Push(returnNode); - return returnNode; -} - -/** - A XMLHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - XMLElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - XMLElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - XMLElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - XMLElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. XMLHandle addresses the verbosity - of such code. A XMLHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - XMLHandle docHandle( &document ); - XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - XMLHandle handleCopy = handle; - @endverbatim - - See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. -*/ -class TINYXML2_LIB XMLHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - explicit XMLHandle( XMLNode* node ) : _node( node ) { - } - /// Create a handle from a node. - explicit XMLHandle( XMLNode& node ) : _node( &node ) { - } - /// Copy constructor - XMLHandle( const XMLHandle& ref ) : _node( ref._node ) { - } - /// Assignment - XMLHandle& operator=( const XMLHandle& ref ) { - _node = ref._node; - return *this; - } - - /// Get the first child of this handle. - XMLHandle FirstChild() { - return XMLHandle( _node ? _node->FirstChild() : 0 ); - } - /// Get the first child element of this handle. - XMLHandle FirstChildElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); - } - /// Get the last child of this handle. - XMLHandle LastChild() { - return XMLHandle( _node ? _node->LastChild() : 0 ); - } - /// Get the last child element of this handle. - XMLHandle LastChildElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); - } - /// Get the previous sibling of this handle. - XMLHandle PreviousSibling() { - return XMLHandle( _node ? _node->PreviousSibling() : 0 ); - } - /// Get the previous sibling element of this handle. - XMLHandle PreviousSiblingElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); - } - /// Get the next sibling of this handle. - XMLHandle NextSibling() { - return XMLHandle( _node ? _node->NextSibling() : 0 ); - } - /// Get the next sibling element of this handle. - XMLHandle NextSiblingElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); - } - - /// Safe cast to XMLNode. This can return null. - XMLNode* ToNode() { - return _node; - } - /// Safe cast to XMLElement. This can return null. - XMLElement* ToElement() { - return ( _node ? _node->ToElement() : 0 ); - } - /// Safe cast to XMLText. This can return null. - XMLText* ToText() { - return ( _node ? _node->ToText() : 0 ); - } - /// Safe cast to XMLUnknown. This can return null. - XMLUnknown* ToUnknown() { - return ( _node ? _node->ToUnknown() : 0 ); - } - /// Safe cast to XMLDeclaration. This can return null. - XMLDeclaration* ToDeclaration() { - return ( _node ? _node->ToDeclaration() : 0 ); - } - -private: - XMLNode* _node; -}; - - -/** - A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the - same in all regards, except for the 'const' qualifiers. See XMLHandle for API. -*/ -class TINYXML2_LIB XMLConstHandle -{ -public: - explicit XMLConstHandle( const XMLNode* node ) : _node( node ) { - } - explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) { - } - XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) { - } - - XMLConstHandle& operator=( const XMLConstHandle& ref ) { - _node = ref._node; - return *this; - } - - const XMLConstHandle FirstChild() const { - return XMLConstHandle( _node ? _node->FirstChild() : 0 ); - } - const XMLConstHandle FirstChildElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); - } - const XMLConstHandle LastChild() const { - return XMLConstHandle( _node ? _node->LastChild() : 0 ); - } - const XMLConstHandle LastChildElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); - } - const XMLConstHandle PreviousSibling() const { - return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); - } - const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); - } - const XMLConstHandle NextSibling() const { - return XMLConstHandle( _node ? _node->NextSibling() : 0 ); - } - const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); - } - - - const XMLNode* ToNode() const { - return _node; - } - const XMLElement* ToElement() const { - return ( _node ? _node->ToElement() : 0 ); - } - const XMLText* ToText() const { - return ( _node ? _node->ToText() : 0 ); - } - const XMLUnknown* ToUnknown() const { - return ( _node ? _node->ToUnknown() : 0 ); - } - const XMLDeclaration* ToDeclaration() const { - return ( _node ? _node->ToDeclaration() : 0 ); - } - -private: - const XMLNode* _node; -}; - - -/** - Printing functionality. The XMLPrinter gives you more - options than the XMLDocument::Print() method. - - It can: - -# Print to memory. - -# Print to a file you provide. - -# Print XML without a XMLDocument. - - Print to Memory - - @verbatim - XMLPrinter printer; - doc.Print( &printer ); - SomeFunction( printer.CStr() ); - @endverbatim - - Print to a File - - You provide the file pointer. - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Print without a XMLDocument - - When loading, an XML parser is very useful. However, sometimes - when saving, it just gets in the way. The code is often set up - for streaming, and constructing the DOM is just overhead. - - The Printer supports the streaming case. The following code - prints out a trivially simple XML file without ever creating - an XML document. - - @verbatim - XMLPrinter printer( fp ); - printer.OpenElement( "foo" ); - printer.PushAttribute( "foo", "bar" ); - printer.CloseElement(); - @endverbatim -*/ -class TINYXML2_LIB XMLPrinter : public XMLVisitor -{ -public: - /** Construct the printer. If the FILE* is specified, - this will print to the FILE. Else it will print - to memory, and the result is available in CStr(). - If 'compact' is set to true, then output is created - with only required whitespace and newlines. - */ - XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); - virtual ~XMLPrinter() {} - - /** If streaming, write the BOM and declaration. */ - void PushHeader( bool writeBOM, bool writeDeclaration ); - /** If streaming, start writing an element. - The element must be closed with CloseElement() - */ - void OpenElement( const char* name, bool compactMode=false ); - /// If streaming, add an attribute to an open element. - void PushAttribute( const char* name, const char* value ); - void PushAttribute( const char* name, int value ); - void PushAttribute( const char* name, unsigned value ); - void PushAttribute( const char* name, int64_t value ); - void PushAttribute( const char* name, uint64_t value ); - void PushAttribute( const char* name, bool value ); - void PushAttribute( const char* name, double value ); - /// If streaming, close the Element. - virtual void CloseElement( bool compactMode=false ); - - /// Add a text node. - void PushText( const char* text, bool cdata=false ); - /// Add a text node from an integer. - void PushText( int value ); - /// Add a text node from an unsigned. - void PushText( unsigned value ); - /// Add a text node from a signed 64bit integer. - void PushText( int64_t value ); - /// Add a text node from an unsigned 64bit integer. - void PushText( uint64_t value ); - /// Add a text node from a bool. - void PushText( bool value ); - /// Add a text node from a float. - void PushText( float value ); - /// Add a text node from a double. - void PushText( double value ); - - /// Add a comment - void PushComment( const char* comment ); - - void PushDeclaration( const char* value ); - void PushUnknown( const char* value ); - - virtual bool VisitEnter( const XMLDocument& /*doc*/ ); - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); - virtual bool VisitExit( const XMLElement& element ); - - virtual bool Visit( const XMLText& text ); - virtual bool Visit( const XMLComment& comment ); - virtual bool Visit( const XMLDeclaration& declaration ); - virtual bool Visit( const XMLUnknown& unknown ); - - /** - If in print to memory mode, return a pointer to - the XML file in memory. - */ - const char* CStr() const { - return _buffer.Mem(); - } - /** - If in print to memory mode, return the size - of the XML file in memory. (Note the size returned - includes the terminating null.) - */ - int CStrSize() const { - return _buffer.Size(); - } - /** - If in print to memory mode, reset the buffer to the - beginning. - */ - void ClearBuffer( bool resetToFirstElement = true ) { - _buffer.Clear(); - _buffer.Push(0); - _firstElement = resetToFirstElement; - } - -protected: - virtual bool CompactMode( const XMLElement& ) { return _compactMode; } - - /** Prints out the space before an element. You may override to change - the space and tabs used. A PrintSpace() override should call Print(). - */ - virtual void PrintSpace( int depth ); - void Print( const char* format, ... ); - void Write( const char* data, size_t size ); - inline void Write( const char* data ) { Write( data, strlen( data ) ); } - void Putc( char ch ); - - void SealElementIfJustOpened(); - bool _elementJustOpened; - DynArray< const char*, 10 > _stack; - -private: - void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. - - bool _firstElement; - FILE* _fp; - int _depth; - int _textDepth; - bool _processEntities; - bool _compactMode; - - enum { - ENTITY_RANGE = 64, - BUF_SIZE = 200 - }; - bool _entityFlag[ENTITY_RANGE]; - bool _restrictedEntityFlag[ENTITY_RANGE]; - - DynArray< char, 20 > _buffer; - - // Prohibit cloning, intentionally not implemented - XMLPrinter( const XMLPrinter& ); - XMLPrinter& operator=( const XMLPrinter& ); -}; - - -} // tinyxml2 - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif // TINYXML2_INCLUDED From c70e6d280a139f7e3f6e6e9fdcc8d17c96c1d6d4 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 30 Apr 2024 18:50:06 -0400 Subject: [PATCH 201/300] spdlog from package managers (#4088) --- .github/workflows/apt-deps.txt | 2 +- .github/workflows/test-builds-on-distros.yml | 1 + CMakeLists.txt | 2 +- OTRExporter | 2 +- libultraship | 2 +- soh/CMakeLists.txt | 3 ++- soh/soh/Enhancements/crowd-control/CrowdControl.cpp | 2 +- soh/soh/OTRGlobals.cpp | 2 +- 8 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt index 62eba0386..c06068ab4 100644 --- a/.github/workflows/apt-deps.txt +++ b/.github/workflows/apt-deps.txt @@ -1 +1 @@ -libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev ninja-build +libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev ninja-build diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index 683e07b24..36bbc67a9 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -1,6 +1,7 @@ # todo: # nlohmann # tinyxml2 +# spdlog name: test-builds-on-distros on: diff --git a/CMakeLists.txt b/CMakeLists.txt index 34fe61b65..7c1f3dbed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") set(VCPKG_TARGET_TRIPLET x64-windows-static) vcpkg_bootstrap() - vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2) + vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2 spdlog) if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) diff --git a/OTRExporter b/OTRExporter index 467434c56..ac64c159b 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 467434c5666e11a3a7b756ff04401cd54da5c3f2 +Subproject commit ac64c159b62361301f48f7fd05bfd3db931ebc9c diff --git a/libultraship b/libultraship index 6c375a8b5..5b67a45fc 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 6c375a8b5eb8c44088b5bb2b472d40c50ad36d1f +Subproject commit 5b67a45fc47d8d6e86d104651d83d0939d807ae4 diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 4ed9fec72..a32c0ac4f 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -388,7 +388,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern/tinyxml2 ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/spdlog/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic/Fast3D/U64/PR ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils @@ -417,6 +416,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") "_UNICODE" STORMLIB_NO_AUTO_LINK "_CRT_SECURE_NO_WARNINGS;" + NOMINMAX ) elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32") target_compile_definitions(${PROJECT_NAME} PRIVATE @@ -434,6 +434,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") "UNICODE;" "_UNICODE" STORMLIB_NO_AUTO_LINK + NOMINMAX ) endif() elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS") diff --git a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp index 9c0d5cb2d..6443a7ff3 100644 --- a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp +++ b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp @@ -179,7 +179,7 @@ CrowdControl::EffectResult CrowdControl::TranslateGiEnum(GameInteractionEffectQu CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { if (!dataReceived.contains("id") || !dataReceived.contains("type")) { - SPDLOG_ERROR("[CrowdControl] Invalid payload received:\n{}", dataReceived); + SPDLOG_ERROR("[CrowdControl] Invalid payload received:\n{}", dataReceived.dump()); return nullptr; } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index e796d9f96..a848d9247 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -324,7 +324,7 @@ OTRGlobals::OTRGlobals() { auto overlay = context->GetInstance()->GetWindow()->GetGui()->GetGameOverlay(); overlay->LoadFont("Press Start 2P", "fonts/PressStart2P-Regular.ttf", 12.0f); overlay->LoadFont("Fipps", "fonts/Fipps-Regular.otf", 32.0f); - overlay->SetCurrentFont(CVarGetString(CVAR_GAME_OVERLAY_FONT, "Press Start 2P")); + overlay->SetCurrentFont(CVarGetString("gOverlayFont", "Press Start 2P")); context->InitAudio(); From 8480f37f77c7db798ce80bb4c71fc942187babaf Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:49:54 -0400 Subject: [PATCH 202/300] fetch imgui (#4094) --- libultraship | 2 +- soh/soh/Enhancements/audio/AudioEditor.h | 2 +- soh/soh/Enhancements/controls/InputViewer.cpp | 2 +- soh/soh/Enhancements/controls/SohInputEditorWindow.h | 2 +- soh/soh/Enhancements/debugconsole.cpp | 4 ++-- .../Enhancements/game-interactor/GameInteractor_Remote.cpp | 4 ++-- soh/soh/Enhancements/randomizer/randomizer.cpp | 4 ++-- soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp | 2 +- soh/soh/OTRGlobals.cpp | 2 +- soh/soh/SohGui.cpp | 4 ++-- soh/soh/SohMenuBar.cpp | 2 +- soh/soh/SohModals.cpp | 2 +- soh/soh/UIWidgets.cpp | 4 ++-- soh/soh/UIWidgets.hpp | 2 +- 14 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libultraship b/libultraship index 5b67a45fc..8b4a7a627 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 5b67a45fc47d8d6e86d104651d83d0939d807ae4 +Subproject commit 8b4a7a627b36abbc21955bed8adc59eaf9385fcb diff --git a/soh/soh/Enhancements/audio/AudioEditor.h b/soh/soh/Enhancements/audio/AudioEditor.h index 45c2654e5..93ae3c440 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.h +++ b/soh/soh/Enhancements/audio/AudioEditor.h @@ -7,7 +7,7 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include +#include #include "AudioCollection.h" class AudioEditor : public Ship::GuiWindow { diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 52b3527cc..c9b85c607 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -7,7 +7,7 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include +#include #include #include diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h index 079aa805b..b418a041e 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h @@ -5,7 +5,7 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include +#include #include #include #include diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 7c73ea61e..470785f7b 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -20,8 +20,8 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include -#include +#include +#include #undef PATH_HACK #undef Path diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp index 1d933d8d2..662d2ea78 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Remote.cpp @@ -2,8 +2,8 @@ #include "GameInteractor.h" #include -#include -#include +#include +#include #include #include #include diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 0c7f30e0f..187e50eab 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -15,8 +15,8 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include -#include +#include +#include #include "../custom-message/CustomMessageTypes.h" #include "../item-tables/ItemTableManager.h" #include "../presets.h" diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp index 69dec46bc..e20f46939 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp @@ -1,5 +1,5 @@ #include "ResolutionEditor.h" -#include +#include #include #include diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a848d9247..a6ea015da 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -319,7 +319,7 @@ OTRGlobals::OTRGlobals() { context->InitConsole(); auto sohInputEditorWindow = std::make_shared("gControllerConfigurationEnabled", "Input Editor"); - context->InitWindow(sohInputEditorWindow); + context->InitWindow({ sohInputEditorWindow }); auto overlay = context->GetInstance()->GetWindow()->GetGui()->GetGameOverlay(); overlay->LoadFont("Press Start 2P", "fonts/PressStart2P-Regular.ttf", 12.0f); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 9055087bd..0ac185706 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -11,8 +11,8 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include -#include +#include +#include #include #include diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index e7a99b39f..6639f7a8a 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -2,7 +2,7 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include "ImGui/imgui.h" +#include #include "regex" #include "public/bridge/consolevariablebridge.h" #include diff --git a/soh/soh/SohModals.cpp b/soh/soh/SohModals.cpp index 087bc8ab1..44dc93d74 100644 --- a/soh/soh/SohModals.cpp +++ b/soh/soh/SohModals.cpp @@ -1,5 +1,5 @@ #include "SohModals.h" -#include "ImGui/imgui.h" +#include #include #include #include diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 5bf2e7b73..bd0843e96 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -10,8 +10,8 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include -#include +#include +#include #include #include diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index f1086a944..70580340c 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -16,7 +16,7 @@ #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif -#include +#include namespace UIWidgets { From baaa00569d13ab690fa837295091a6efba0e4907 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 30 Apr 2024 23:31:08 -0400 Subject: [PATCH 203/300] Adds Quick Boss Death checkbox and implements Phantom Ganon's quick death (#119) * Adds Quick Boss Death checkbox and implements Phantom Ganon's quick death. * Clarifies relocation comment. --- .../game-interactor/GameInteractor.h | 4 + .../Enhancements/timesaver_hook_handlers.cpp | 27 ++++++ soh/soh/SohMenuBar.cpp | 5 ++ .../ovl_Boss_Ganondrof/z_boss_ganondrof.c | 83 ++++++------------- .../ovl_Boss_Ganondrof/z_boss_ganondrof.h | 17 ++++ 5 files changed, 80 insertions(+), 56 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index fd5611df8..716d20b08 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -376,6 +376,10 @@ typedef enum { /*** Fixes ***/ // Vanilla condition: false GI_VB_FIX_SAW_SOFTLOCK, + + /*** Quick Boss Deaths ***/ + // Vanilla condition: true + GI_VB_PHANTOM_GANON_DEATH_SCENE, } GIVanillaBehavior; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 46b4353ee..52e14ab8c 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -24,6 +24,8 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" +#include +#include extern SaveContext gSaveContext; extern PlayState* gPlayState; extern int32_t D_8011D3AC; @@ -719,6 +721,31 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case GI_VB_PHANTOM_GANON_DEATH_SCENE: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO || IS_BOSS_RUSH)) { + *should = false; + BossGanondrof* pg = static_cast(opt); + Player* player = GET_PLAYER(gPlayState); + if (pg != nullptr && pg->work[GND_ACTION_STATE] == DEATH_SPASM) { + // Skip to death scream animation and move ganondrof to middle + pg->deathState = DEATH_SCREAM; + pg->timers[0] = 50; + AnimationHeader* screamAnim = (AnimationHeader*)gPhantomGanonScreamAnim; + Animation_MorphToLoop(&pg->skelAnime, screamAnim, -10.0f); + pg->actor.world.pos.x = GND_BOSSROOM_CENTER_X; + pg->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f; + pg->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; + pg->actor.shape.rot.y = 0; + pg->work[GND_BODY_DECAY_INDEX] = 0; + Audio_PlayActorSound2(&pg->actor, NA_SE_EN_FANTOM_LAST); + + // Move Player out of the center of the room + player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f; + player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; + } + } + break; + } } } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 3821f9df4..98de7a48c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -581,6 +581,7 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) && CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && @@ -592,6 +593,7 @@ void DrawEnhancementsMenu() { CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) || CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || @@ -608,6 +610,7 @@ void DrawEnhancementsMenu() { CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1); CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1); CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 1); CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1); CVarSetInteger("gTimeSavers.NoForcedDialog", 1); CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1); @@ -619,6 +622,7 @@ void DrawEnhancementsMenu() { CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0); CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0); CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 0); CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0); CVarSetInteger("gTimeSavers.NoForcedDialog", 0); CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0); @@ -633,6 +637,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Quick Boss Deaths", "gTimeSavers.SkipCutscene.QuickBossDeaths", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs"); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 82fe2c131..0b025dcd6 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -12,19 +12,10 @@ #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) -typedef enum { - /* 0 */ NOT_DEAD, - /* 1 */ DEATH_START, - /* 2 */ DEATH_THROES, - /* 3 */ DEATH_WARP, - /* 4 */ DEATH_SCREAM, - /* 5 */ DEATH_DISINTEGRATE, - /* 6 */ DEATH_FINISH -} BossGanondrofDeathState; - typedef enum { /* 0 */ THROW_NORMAL, /* 1 */ THROW_SLOW @@ -42,12 +33,6 @@ typedef enum { /* 3 */ CHARGE_FINISH } BossGanondrofChargeAction; -typedef enum { - /* 0 */ DEATH_SPASM, - /* 1 */ DEATH_LIMP, - /* 2 */ DEATH_HUNCHED -} BossGanondrofDeathAction; - void BossGanondrof_Init(Actor* thisx, PlayState* play); void BossGanondrof_Destroy(Actor* thisx, PlayState* play); void BossGanondrof_Update(Actor* thisx, PlayState* play); @@ -959,26 +944,13 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { case DEATH_THROES: switch (this->work[GND_ACTION_STATE]) { case DEATH_SPASM: - if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME]) && !IS_RANDO && !IS_BOSS_RUSH) { - this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim); - Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f, - this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f); - this->work[GND_ACTION_STATE] = DEATH_LIMP; - } else if (IS_RANDO || IS_BOSS_RUSH) { - // Skip to death scream animation and move ganondrof to middle - this->deathState = DEATH_SCREAM; - this->timers[0] = 50; - Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonScreamAnim, -10.0f); - this->actor.world.pos.x = GND_BOSSROOM_CENTER_X; - this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f; - this->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; - this->actor.shape.rot.y = 0; - this->work[GND_BODY_DECAY_INDEX] = 0; - Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAST); - - // Move Player out of the center of the room - player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f; - player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; + if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, this)) { + if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) { + this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim); + Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f, + this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f); + this->work[GND_ACTION_STATE] = DEATH_LIMP; + } } break; case DEATH_LIMP: @@ -991,26 +963,25 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { bodyDecayLevel = 1; break; } - if (IS_RANDO || IS_BOSS_RUSH) { - break; - } - Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8); - Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f); - Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f); - this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500); - this->cameraNextAt.x = this->targetPos.x; - this->cameraNextAt.y = this->targetPos.y - 10.0f; - this->cameraNextAt.z = this->targetPos.z; - if (this->timers[0] == 0) { - this->deathState = DEATH_WARP; - this->timers[0] = 350; - this->timers[1] = 50; - this->fwork[GND_CAMERA_ZOOM] = 300.0f; - this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f; - player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f; - player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; - holdCamera = true; - bodyDecayLevel = 1; + if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, NULL)) { + Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8); + Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f); + Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f); + this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500); + this->cameraNextAt.x = this->targetPos.x; + this->cameraNextAt.y = this->targetPos.y - 10.0f; + this->cameraNextAt.z = this->targetPos.z; + if (this->timers[0] == 0) { + this->deathState = DEATH_WARP; + this->timers[0] = 350; + this->timers[1] = 50; + this->fwork[GND_CAMERA_ZOOM] = 300.0f; + this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f; + player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f; + player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; + holdCamera = true; + bodyDecayLevel = 1; + } } break; case DEATH_WARP: diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h index ff4a841d6..1e45ca766 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h @@ -61,6 +61,23 @@ typedef enum { /* 13 */ GND_FLOAT_COUNT = 13 } BossGanondrofF32Var; +// SOH [Enhancements] Relocated from z_boss_ganondrof.c to use in time saver. +typedef enum { + /* 0 */ NOT_DEAD, + /* 1 */ DEATH_START, + /* 2 */ DEATH_THROES, + /* 3 */ DEATH_WARP, + /* 4 */ DEATH_SCREAM, + /* 5 */ DEATH_DISINTEGRATE, + /* 6 */ DEATH_FINISH +} BossGanondrofDeathState; + +typedef enum { + /* 0 */ DEATH_SPASM, + /* 1 */ DEATH_LIMP, + /* 2 */ DEATH_HUNCHED +} BossGanondrofDeathAction; + typedef struct BossGanondrof { /* 0x0000 */ Actor actor; /* 0x014C */ SkelAnime skelAnime; From 7da6a5b604f3fe2143fabdea9b5dcd154aaa5edd Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:36:26 -0400 Subject: [PATCH 204/300] vb deku stick cheat (#115) * vb deku stick cheat * it's the 21st now --------- Co-authored-by: Garrett Cox --- soh/soh/Enhancements/cheat_hook_handlers.cpp | 56 +++++++++++++++++++ soh/soh/Enhancements/cheat_hook_handlers.h | 6 ++ .../game-interactor/GameInteractor.h | 7 +++ soh/soh/Enhancements/mods.cpp | 2 + .../actors/ovl_player_actor/z_player.c | 37 +++++------- 5 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 soh/soh/Enhancements/cheat_hook_handlers.cpp create mode 100644 soh/soh/Enhancements/cheat_hook_handlers.h diff --git a/soh/soh/Enhancements/cheat_hook_handlers.cpp b/soh/soh/Enhancements/cheat_hook_handlers.cpp new file mode 100644 index 000000000..cdc8333ce --- /dev/null +++ b/soh/soh/Enhancements/cheat_hook_handlers.cpp @@ -0,0 +1,56 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/enhancementTypes.h" + +extern "C" { +#include "macros.h" +#include "variables.h" + +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { + switch (id) { + case GI_VB_DEKU_STICK_BREAK: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + case GI_VB_DEKU_STICK_BE_ON_FIRE: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { + Player* player = GET_PLAYER(gPlayState); + player->unk_860 = 200; // Keeps the stick's flame lit + player->unk_85C = 1.0f; // Ensures the stick is the proper length + *should = true; + } + break; + } + case GI_VB_DEKU_STICK_BURN_OUT: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + case GI_VB_DEKU_STICK_BURN_DOWN: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + } +} + +static uint32_t onVanillaBehaviorHook = 0; +void CheatsRegisterHooks() { + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) mutable { + + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + onVanillaBehaviorHook = 0; + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(CheatsOnVanillaBehaviorHandler); + + }); +} diff --git a/soh/soh/Enhancements/cheat_hook_handlers.h b/soh/soh/Enhancements/cheat_hook_handlers.h new file mode 100644 index 000000000..88a79f285 --- /dev/null +++ b/soh/soh/Enhancements/cheat_hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef CHEAT_HOOK_HANDLERS_H +#define CHEAT_HOOK_HANDLERS_H + +void CheatsRegisterHooks(); + +#endif // CHEAT_HOOK_HANDLERS_H diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 716d20b08..17b6198b3 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -377,6 +377,13 @@ typedef enum { // Vanilla condition: false GI_VB_FIX_SAW_SOFTLOCK, + /*** Cheats? ***/ + GI_VB_DEKU_STICK_BE_ON_FIRE, + GI_VB_DEKU_STICK_BREAK, + GI_VB_DEKU_STICK_BURN_DOWN, + GI_VB_DEKU_STICK_BURN_OUT, + GI_VB_DEKU_UPDATE_BURNING_DEKU_STICK, + /*** Quick Boss Deaths ***/ // Vanilla condition: true GI_VB_PHANTOM_GANON_DEATH_SCENE, diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 580c29b3c..c0425f148 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -11,6 +11,7 @@ #include #include "soh/Enhancements/nametag.h" #include "soh/Enhancements/timesaver_hook_handlers.h" +#include "soh/Enhancements/cheat_hook_handlers.h" #include "soh/Enhancements/randomizer/hook_handlers.h" #include "objects/object_gi_compass/object_gi_compass.h" @@ -1715,6 +1716,7 @@ void RegisterRandomizerCompasses() { void InitMods() { RandomizerRegisterHooks(); TimeSaverRegisterHooks(); + CheatsRegisterHooks(); RegisterTTS(); RegisterInfiniteMoney(); RegisterInfiniteHealth(); diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 2b994f56f..43a34c778 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -8515,15 +8515,14 @@ void func_80842A28(PlayState* play, Player* this) { } void func_80842A88(PlayState* play, Player* this) { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { - Inventory_ChangeAmmo(ITEM_STICK, -1); - Player_UseItem(play, this, ITEM_NONE); - } + Inventory_ChangeAmmo(ITEM_STICK, -1); + Player_UseItem(play, this, ITEM_NONE); } s32 func_80842AC4(PlayState* play, Player* this) { if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) { - if (AMMO(ITEM_STICK) != 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + + if (GameInteractor_Should(GI_VB_DEKU_STICK_BREAK, AMMO(ITEM_STICK) != 0, NULL)) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; @@ -10942,37 +10941,30 @@ static Vec3f D_808547B0 = { 0.0f, 0.5f, 0.0f }; static Color_RGBA8 D_808547BC = { 255, 255, 100, 255 }; static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 }; -void func_80848A04(PlayState* play, Player* this) { +void Player_UpdateBurningDekuStick(PlayState* play, Player* this) { f32 temp; - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { - f32 temp2 = 1.0f; // Secondary temporary variable to use with the alleged draw flame function - this->unk_860 = 200; // Keeps the stick's flame lit - this->unk_85C = 1.0f; // Ensures the stick is the proper length - func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp2 * 200.0f, - 0, 8); // I believe this draws the flame effect - } - - if (this->unk_85C == 0.0f && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { - Player_UseItem(play, this, 0xFF); + if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, this->unk_85C == 0.0f, NULL)) { + Player_UseItem(play, this, ITEM_NONE); return; } temp = 1.0f; - if (DECR(this->unk_860) == 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + uint8_t vanillaShouldBurnOutCondition = DECR(this->unk_860) == 0; + if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, vanillaShouldBurnOutCondition, NULL)) { Inventory_ChangeAmmo(ITEM_STICK, -1); this->unk_860 = 1; temp = 0.0f; this->unk_85C = temp; } else if (this->unk_860 > 200) { temp = (210 - this->unk_860) / 10.0f; - } else if (this->unk_860 < 20 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + } else if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_DOWN, this->unk_860 < 20, NULL)) { temp = this->unk_860 / 20.0f; this->unk_85C = temp; } - func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp * 200.0f, - 0, 8); + func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, + temp * 200.0f, 0, 8); } void Player_UpdateBodyShock(PlayState* play, Player* this) { @@ -11267,8 +11259,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { func_808473D4(play, this); func_80836BEC(this, play); - if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { - func_80848A04(play, this); + if (this->heldItemAction == PLAYER_IA_DEKU_STICK && + GameInteractor_Should(GI_VB_DEKU_STICK_BE_ON_FIRE, this->unk_860 != 0, NULL)) { + Player_UpdateBurningDekuStick(play, this); } else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) { this->unk_860++; } From 56fe44968996b88a412885c8b978ef881455d763 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 1 May 2024 12:53:33 -0400 Subject: [PATCH 205/300] fetchcontent stormlib (#4095) --- OTRExporter | 2 +- libultraship | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OTRExporter b/OTRExporter index ac64c159b..8815dd98f 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit ac64c159b62361301f48f7fd05bfd3db931ebc9c +Subproject commit 8815dd98f25d5f4c7a80f162e9ee1ec0a3f7dd4e diff --git a/libultraship b/libultraship index 8b4a7a627..fd603a40e 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 8b4a7a627b36abbc21955bed8adc59eaf9385fcb +Subproject commit fd603a40e0c847092d142d77f144ec44c386f323 From 715bf39d4373ef22dea3ca6a229db7bb2e2d5e95 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 1 May 2024 11:48:51 -0700 Subject: [PATCH 206/300] Incorporate LUS CMake CVar system (#4093) * Incorporate LUS CMake CVar system. Customize all LUS CMake CVars to align with plans for preset system. Swap "gOverlayFont" usage back to LUS CVar macro. * Change CMake sets to use the cache to allow for including LUS's file for the add_compile_defines and remove the duplication on SoH's side. * Move SoH CMake CVars to `soh-cvars.cmake` for clarity. --- CMake/lus-cvars.cmake | 24 +++++++++++++ CMake/soh-cvars.cmake | 26 ++++++++++++++ CMakeLists.txt | 2 ++ soh/soh/Enhancements/bootcommands.c | 2 +- soh/soh/Enhancements/mods.cpp | 4 +-- soh/soh/Enhancements/presets.h | 8 ++--- .../resolution-editor/ResolutionEditor.cpp | 16 ++++----- soh/soh/OTRGlobals.cpp | 18 +++++----- soh/soh/OTRGlobals.h | 30 ++++++++-------- soh/soh/SohGui.cpp | 2 +- soh/soh/SohMenuBar.cpp | 34 +++++++++---------- soh/soh/config/ConfigUpdaters.cpp | 2 +- soh/soh/resource/type/Skeleton.cpp | 2 +- soh/src/code/game.c | 2 +- soh/src/code/gfxprint.c | 2 +- 15 files changed, 113 insertions(+), 61 deletions(-) create mode 100644 CMake/lus-cvars.cmake create mode 100644 CMake/soh-cvars.cmake diff --git a/CMake/lus-cvars.cmake b/CMake/lus-cvars.cmake new file mode 100644 index 000000000..e7376cfe2 --- /dev/null +++ b/CMake/lus-cvars.cmake @@ -0,0 +1,24 @@ +set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "") +set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "") +set(CVAR_NEW_FILE_DROPPED "${CVAR_PREFIX_GENERAL}.NewFileDropped" CACHE STRING "") +set(CVAR_DROPPED_FILE "${CVAR_PREFIX_GENERAL}.DroppedFile" CACHE STRING "") +set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "") +set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "") +set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "") +set(CVAR_TEXTURE_FILTER "${CVAR_PREFIX_SETTING}.TextureFilter" CACHE STRING "") +set(CVAR_IMGUI_CONTROLLER_NAV "${CVAR_PREFIX_SETTING}.ControlNav" CACHE STRING "") +set(CVAR_CONSOLE_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Console" CACHE STRING "") +set(CVAR_CONTROLLER_CONFIGURATION_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.ControllerConfiguration" CACHE STRING "") +set(CVAR_CONTROLLER_DISCONNECTED_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.ControllerDisconnected" CACHE STRING "") +set(CVAR_CONTROLLER_REORDERING_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.ControllerReordering" CACHE STRING "") +set(CVAR_GFX_DEBUGGER_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.GfxDebugger" CACHE STRING "") +set(CVAR_STATS_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Stats" CACHE STRING "") +set(CVAR_ENABLE_MULTI_VIEWPORTS "${CVAR_PREFIX_SETTING}.EnableMultiViewports" CACHE STRING "") +set(CVAR_LOW_RES_MODE "${CVAR_PREFIX_SETTING}.LowResMode" CACHE STRING "") +set(CVAR_SIMULATED_INPUT_LAG "${CVAR_PREFIX_SETTING}.SimulatedInputLag" CACHE STRING "") +set(CVAR_ALT_ASSETS "${CVAR_PREFIX_ENHANCEMENT}.AltAssets" CACHE STRING "") +set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont" CACHE STRING "") +set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar" CACHE STRING "") +set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers" CACHE STRING "") +set(CVAR_PREFIX_ADVANCED_RESOLUTION "${CVAR_PREFIX_SETTING}.AdvancedResolution" CACHE STRING "") +include("libultraship/cmake/cvars.cmake") \ No newline at end of file diff --git a/CMake/soh-cvars.cmake b/CMake/soh-cvars.cmake new file mode 100644 index 000000000..e5ff8a384 --- /dev/null +++ b/CMake/soh-cvars.cmake @@ -0,0 +1,26 @@ +set(CVAR_PREFIX_RANDOMIZER_ENHANCEMENT "gRandoEnhancements") +set(CVAR_PREFIX_RANDOMIZER_SETTING "gRandoSettings") +set(CVAR_PREFIX_COSMETIC "gCosmetics") +set(CVAR_PREFIX_AUDIO "gAudioEditor") +set(CVAR_PREFIX_CHEAT "gCheats") +set(CVAR_PREFIX_ENHANCEMENT "gEnhancements") +set(CVAR_PREFIX_SETTING "gSettings") +set(CVAR_PREFIX_WINDOW "gOpenWindows") +set(CVAR_PREFIX_TRACKER "gTrackers") +set(CVAR_PREFIX_DEVELOPER_TOOLS "gDeveloperTools") +set(CVAR_PREFIX_GENERAL "gGeneral") +set(CVAR_PREFIX_REMOTE "gRemote") +add_compile_definitions( + CVAR_PREFIX_RANDOMIZER_ENHANCEMENT="${CVAR_PREFIX_RANDOMIZER_ENHANCEMENT}" + CVAR_PREFIX_RANDOMIZER_SETTING="${CVAR_PREFIX_RANDOMIZER_SETTING}" + CVAR_PREFIX_COSMETIC="${CVAR_PREFIX_COSMETIC}" + CVAR_PREFIX_AUDIO="${CVAR_PREFIX_AUDIO}" + CVAR_PREFIX_CHEAT="${CVAR_PREFIX_CHEAT}" + CVAR_PREFIX_ENHANCEMENT="${CVAR_PREFIX_ENHANCEMENT}" + CVAR_PREFIX_SETTING="${CVAR_PREFIX_SETTING}" + CVAR_PREFIX_WINDOW="${CVAR_PREFIX_WINDOW}" + CVAR_PREFIX_TRACKER="${CVAR_PREFIX_TRACKER}" + CVAR_PREFIX_DEVELOPER_TOOLS="${CVAR_PREFIX_DEVELOPER_TOOLS}" + CVAR_PREFIX_GENERAL="${CVAR_PREFIX_GENERAL}" + CVAR_PREFIX_REMOTE="${CVAR_PREFIX_REMOTE}" +) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c1f3dbed..891d6ad26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") project(Ship VERSION 8.0.5 LANGUAGES C CXX) +include(CMake/soh-cvars.cmake) +include(CMake/lus-cvars.cmake) set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "") set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index 385a544a6..be3a766dc 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -29,7 +29,7 @@ void BootCommands_Init() CVarClear("gCheatEasyPauseBufferLastInputs"); CVarClear("gCheatEasyPauseBufferTimer"); #if defined(__SWITCH__) || defined(__WIIU__) - CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u + CVarRegisterInteger(CVAR_IMGUI_CONTROLLER_NAV, 1); // always enable controller nav on switch/wii u #endif } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 8f9819f08..8ddd59cef 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -660,10 +660,10 @@ void UpdateDirtPathFixState(int32_t sceneNum) { case SCENE_HYRULE_FIELD: case SCENE_KOKIRI_FOREST: case SCENE_HYRULE_CASTLE: - CVarSetInteger("gZFightingMode", CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED)); + CVarSetInteger(CVAR_Z_FIGHTING_MODE, CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED)); return; default: - CVarClear("gZFightingMode"); + CVarClear(CVAR_Z_FIGHTING_MODE); } } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 8064fc66c..1392691df 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -223,12 +223,12 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("DisableLOD"), CVAR_ENHANCEMENT("DisableDrawDistance"), CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), - "gLowResMode", + CVAR_LOW_RES_MODE, CVAR_ENHANCEMENT("DrawLineupTick"), CVAR_ENHANCEMENT("QuickBongoKill"), CVAR_ENHANCEMENT("FirstPersonGauntlets"), CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), - "gZFightingMode", + CVAR_Z_FIGHTING_MODE, CVAR_ENHANCEMENT("AuthenticLogo"), CVAR_ENHANCEMENT("PauseLiveLinkRotationSpeed"), CVAR_ENHANCEMENT("BowReticle"), @@ -282,7 +282,7 @@ const std::vector enhancementsCvars = { }; const std::vector cheatCvars = { - "gConsoleEnabled", + CVAR_CONSOLE_WINDOW_OPEN, CVAR_WINDOW("ActorViewer"), CVAR_WINDOW("CollisionViewer"), CVAR_WINDOW("DLViewer"), @@ -336,7 +336,7 @@ const std::vector cheatCvars = { CVAR_CHEAT("NoFishDespawn"), CVAR_CHEAT("NoBugsDespawn"), "gWalkModifierDoesntChangeJump", - "gStatsEnabled", + CVAR_STATS_WINDOW_OPEN, CVAR_CHEAT("SaveStatesEnabled"), CVAR_CHEAT("SaveStatePromise"), CVAR_DEVELOPER_TOOLS("RegEditEnabled"), diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp index e20f46939..b522879cb 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp @@ -114,19 +114,19 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // The original resolution slider (for convenience) const bool disabled_resolutionSlider = (CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && CVarGetInteger("gAdvancedResolution.Enabled", 0)) || - CVarGetInteger("gLowResMode", 0); - if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", "gInternalResolution", 0.5f, + CVarGetInteger(CVAR_LOW_RES_MODE, 0); + if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", CVAR_INTERNAL_RESOLUTION, 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier( - CVarGetFloat("gInternalResolution", 1)); + CVarGetFloat(CVAR_INTERNAL_RESOLUTION, 1)); } UIWidgets::Tooltip("Multiplies your output resolution by the value entered."); // The original MSAA slider (also for convenience) #ifndef __WIIU__ - if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, + if (UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", CVAR_MSAA_VALUE, 1, 8, "", 1, true, true, false)) { - Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); + Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger(CVAR_MSAA_VALUE, 1)); }; UIWidgets::Tooltip( "Activates multi-sample anti-aliasing when above 1x, up to 8x for 8 samples for every pixel.\n\n" @@ -135,7 +135,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { #endif // N64 Mode toggle (again for convenience) - // UIWidgets::PaddedEnhancementCheckbox("(Enhancements>Graphics) N64 Mode", "gLowResMode", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + // UIWidgets::PaddedEnhancementCheckbox("(Enhancements>Graphics) N64 Mode", CVAR_LOW_RES_MODE, false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); } UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); @@ -143,7 +143,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { UIWidgets::PaddedEnhancementCheckbox("Enable advanced settings.", "gAdvancedResolution.Enabled", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); // Error/Warning display - if (!CVarGetInteger("gLowResMode", 0)) { + if (!CVarGetInteger(CVAR_LOW_RES_MODE, 0)) { if (IsDroppingFrames()) { // Significant frame drop warning ImGui::TextColored(messageColor[MESSAGE_WARNING], ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring."); @@ -156,7 +156,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { ICON_FA_QUESTION_CIRCLE " \"N64 Mode\" is overriding these settings."); ImGui::SameLine(); if (ImGui::Button("Click to disable")) { - CVarSetInteger("gLowResMode", 0); + CVarSetInteger(CVAR_LOW_RES_MODE, 0); CVarSave(); } } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a6ea015da..744db9561 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -318,13 +318,13 @@ OTRGlobals::OTRGlobals() { context->InitCrashHandler(); context->InitConsole(); - auto sohInputEditorWindow = std::make_shared("gControllerConfigurationEnabled", "Input Editor"); + auto sohInputEditorWindow = std::make_shared(CVAR_CONTROLLER_CONFIGURATION_WINDOW_OPEN, "Input Editor"); context->InitWindow({ sohInputEditorWindow }); auto overlay = context->GetInstance()->GetWindow()->GetGui()->GetGameOverlay(); overlay->LoadFont("Press Start 2P", "fonts/PressStart2P-Regular.ttf", 12.0f); overlay->LoadFont("Fipps", "fonts/Fipps-Regular.otf", 32.0f); - overlay->SetCurrentFont(CVarGetString("gOverlayFont", "Press Start 2P")); + overlay->SetCurrentFont(CVarGetString(CVAR_GAME_OVERLAY_FONT, "Press Start 2P")); context->InitAudio(); @@ -1330,13 +1330,13 @@ extern "C" void Graph_StartFrame() { } #endif - if (CVarGetInteger("gNewFileDropped", 0)) { - std::string filePath = SohUtils::Sanitize(CVarGetString("gDroppedFile", "")); + if (CVarGetInteger(CVAR_NEW_FILE_DROPPED, 0)) { + std::string filePath = SohUtils::Sanitize(CVarGetString(CVAR_DROPPED_FILE, "")); if (!filePath.empty()) { GameInteractor::Instance->ExecuteHooks(filePath); } - CVarClear("gNewFileDropped"); - CVarClear("gDroppedFile"); + CVarClear(CVAR_NEW_FILE_DROPPED); + CVarClear(CVAR_DROPPED_FILE); } OTRGlobals::Instance->context->GetWindow()->StartFrame(); @@ -1408,7 +1408,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { ToggleAltAssetsAtEndOfFrame = false; // Actually update the CVar now before runing the alt asset update listeners - CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); + CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); gfx_texture_cache_clear(); SOH::SkeletonPatcher::UpdateSkeletons(); GameInteractor::Instance->ExecuteHooks(); @@ -1587,7 +1587,7 @@ extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) { // Unloads a resource if an alternate version exists when alt assets are enabled // The resource is only removed from the internal cache to prevent it from used in the next resource lookup extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { - if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileAltExists((char*) resName)) { + if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileAltExists((char*) resName)) { ResourceMgr_UnloadResource((char*) resName); } } @@ -1938,7 +1938,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel pathStr = pathStr.substr(sOtr.length()); } - bool isAlt = CVarGetInteger("gAltAssets", 0); + bool isAlt = CVarGetInteger(CVAR_ALT_ASSETS, 0); if (isAlt) { pathStr = Ship::IResource::gAltAssetPrefix + pathStr; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 3a1b3e1f6..73cb58d97 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -65,21 +65,21 @@ private: uint32_t IsGameMasterQuest(); #endif -#define CVAR_RANDOMIZER_ENHANCEMENT(var) "gRandoEnhancements." var -#define CVAR_RANDOMIZER_SETTING(var) "gRandoSettings." var -#define CVAR_COSMETIC(var) "gCosmetics." var -#define CVAR_AUDIO(var) "gAudioEditor." var -#define CVAR_CHEAT(var) "gCheats." var -#define CVAR_ENHANCEMENT(var) "gEnhancements." var -#define CVAR_SETTING(var) "gSettings." var -#define CVAR_WINDOW(var) "gOpenWindows." var -#define CVAR_TRACKER(var) "gTrackers." var -#define CVAR_TRACKER_ITEM(var) CVAR_TRACKER("ItemTracker." var) -#define CVAR_TRACKER_CHECK(var) CVAR_TRACKER("CheckTracker." var) -#define CVAR_TRACKER_ENTRANCE(var) CVAR_TRACKER("EntranceTracker." var) -#define CVAR_DEVELOPER_TOOLS(var) "gDeveloperTools." var -#define CVAR_GENERAL(var) "gGeneral." var -#define CVAR_REMOTE(var) "gRemote." var +#define CVAR_RANDOMIZER_ENHANCEMENT(var) CVAR_PREFIX_RANDOMIZER_ENHANCEMENT "." var +#define CVAR_RANDOMIZER_SETTING(var) CVAR_PREFIX_RANDOMIZER_SETTING "." var +#define CVAR_COSMETIC(var) CVAR_PREFIX_COSMETIC "." var +#define CVAR_AUDIO(var) CVAR_PREFIX_AUDIO "." var +#define CVAR_CHEAT(var) CVAR_PREFIX_CHEAT "." var +#define CVAR_ENHANCEMENT(var) CVAR_PREFIX_ENHANCEMENT "." var +#define CVAR_SETTING(var) CVAR_PREFIX_SETTING "." var +#define CVAR_WINDOW(var) CVAR_PREFIX_WINDOW "." var +#define CVAR_TRACKER(var) CVAR_PREFIX_TRACKER "." var +#define CVAR_TRACKER_ITEM(var) CVAR_TRACKER(".ItemTracker." var) +#define CVAR_TRACKER_CHECK(var) CVAR_TRACKER(".CheckTracker." var) +#define CVAR_TRACKER_ENTRANCE(var) CVAR_TRACKER(".EntranceTracker." var) +#define CVAR_DEVELOPER_TOOLS(var) CVAR_PREFIX_DEVELOPER_TOOLS "." var +#define CVAR_GENERAL(var) CVAR_PREFIX_GENERAL "." var +#define CVAR_REMOTE(var) CVAR_PREFIX_REMOTE "." var #ifndef __cplusplus void InitOTR(void); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 0ac185706..e7eb998dd 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -139,7 +139,7 @@ namespace SohGui { void SetupGuiElements() { auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); - mSohMenuBar = std::make_shared("gOpenMenuBar", CVarGetInteger("gOpenMenuBar", 0)); + mSohMenuBar = std::make_shared(CVAR_MENU_BAR_OPEN, CVarGetInteger(CVAR_MENU_BAR_OPEN, 0)); gui->SetMenuBar(std::reinterpret_pointer_cast(mSohMenuBar)); if (gui->GetMenuBar() && !gui->GetMenuBar()->IsVisible()) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 6639f7a8a..fbcf2496a 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -231,7 +231,7 @@ void DrawSettingsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mInputEditorWindow) { - if (ImGui::Button(GetWindowButtonText("Controller Mapping", CVarGetInteger("gControllerConfigurationEnabled", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Controller Mapping", CVarGetInteger(CVAR_CONTROLLER_CONFIGURATION_WINDOW_OPEN, 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { mInputEditorWindow->ToggleVisibility(); } } @@ -239,7 +239,7 @@ void DrawSettingsMenu() { ImGui::PopStyleColor(1); ImGui::PopStyleVar(3); #ifndef __SWITCH__ - UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", "gControlNav"); + UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", CVAR_IMGUI_CONTROLLER_NAV); UIWidgets::Tooltip("Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: This will disable game inputs while the menubar is visible.\n\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); UIWidgets::PaddedSeparator(); #endif @@ -260,7 +260,7 @@ void DrawSettingsMenu() { ImGui::PopStyleColor(1); ImGui::PopStyleVar(3); - UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, true, true, false); + UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", CVAR_SIMULATED_INPUT_LAG, 0, 6, "", 0, true, true, false); UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later"); ImGui::EndMenu(); @@ -272,9 +272,9 @@ void DrawSettingsMenu() { #ifndef __APPLE__ const bool disabled_resolutionSlider = CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && CVarGetInteger("gAdvancedResolution.Enabled", 0); - if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f %%", "##IMul", "gInternalResolution", 0.5f, + if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f %%", "##IMul", CVAR_INTERNAL_RESOLUTION, 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { - Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat("gInternalResolution", 1)); + Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat(CVAR_INTERNAL_RESOLUTION, 1)); } UIWidgets::Tooltip("Resolution scale. Multiplies output resolution by this value, on each axis relative to window size.\n" "Lower values may improve performance.\n" @@ -305,9 +305,9 @@ void DrawSettingsMenu() { #ifndef __WIIU__ if (UIWidgets::PaddedEnhancementSliderInt( - (CVarGetInteger("gMSAAValue", 1) == 1) ? "Anti-aliasing (MSAA): Off" : "Anti-aliasing (MSAA): %d", - "##IMSAA", "gMSAAValue", 1, 8, "", 1, true, true, false)) { - Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger("gMSAAValue", 1)); + (CVarGetInteger(CVAR_MSAA_VALUE, 1) == 1) ? "Anti-aliasing (MSAA): Off" : "Anti-aliasing (MSAA): %d", + "##IMSAA", CVAR_MSAA_VALUE, 1, 8, "", 1, true, true, false)) { + Ship::Context::GetInstance()->GetWindow()->SetMsaaLevel(CVarGetInteger(CVAR_MSAA_VALUE, 1)); } UIWidgets::Tooltip("Activates MSAA (multi-sample anti-aliasing) from 2x up to 8x, to smooth the edges of rendered geometry.\n" "Higher sample count will result in smoother edges on models, but may reduce performance.\n\n" @@ -479,22 +479,22 @@ void DrawSettingsMenu() { } if (Ship::Context::GetInstance()->GetWindow()->CanDisableVerticalSync()) { - UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", "gVsyncEnabled", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable Vsync", CVAR_VSYNC_ENABLED, true, false); UIWidgets::Tooltip("Activate vertical sync, to prevent screen tearing."); } if (Ship::Context::GetInstance()->GetWindow()->SupportsWindowedFullscreen()) { - UIWidgets::PaddedEnhancementCheckbox("Windowed fullscreen", "gSdlWindowedFullscreen", true, false); + UIWidgets::PaddedEnhancementCheckbox("Windowed fullscreen", CVAR_SDL_WINDOWED_FULLSCREEN, true, false); } if (Ship::Context::GetInstance()->GetWindow()->GetGui()->SupportsViewports()) { - UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows (Needs reload)", "gEnableMultiViewports", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows (Needs reload)", CVAR_ENABLE_MULTI_VIEWPORTS, true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect."); } // If more filters are added to LUS, make sure to add them to the filters list here ImGui::Text("Texture Filtering (Needs reload)"); - UIWidgets::EnhancementCombobox("gTextureFilter", filters, FILTER_THREE_POINT); + UIWidgets::EnhancementCombobox(CVAR_TEXTURE_FILTER, filters, FILTER_THREE_POINT); UIWidgets::Tooltip("Texture filtering, aka texture smoothing. Requires a reload to take effect.\n\n" "Three-Point: Replicates real N64 texture filtering.\n" "Bilinear: If Three-Point causes poor performance, try this.\n" @@ -1059,10 +1059,10 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Graphics")) { if (ImGui::BeginMenu("Mods")) { - if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", CVAR_ALT_ASSETS, false, false)) { // The checkbox will flip the alt asset CVar, but we instead want it to change at the end of the game frame // We toggle it back while setting the flag to update the CVar later - CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); + CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); ToggleAltAssetsAtEndOfFrame = true; } UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not."); @@ -1147,7 +1147,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", CVAR_ENHANCEMENT("ScaleAdultEquimentAsChild"), true, false); UIWidgets::Tooltip("Scales all of the Adult Equipment, as well and moving some a bit, to fit on Child Link Better. May not work properly with some mods."); } - UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); + UIWidgets::PaddedEnhancementCheckbox("N64 Mode", CVAR_LOW_RES_MODE, true, false); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", CVAR_ENHANCEMENT("DrawLineupTick"), true, false); UIWidgets::Tooltip("Displays a tick in the top center of the screen to help with glitch line-ups in SoH, as traditional UI based line-ups do not work outside of 4:3"); @@ -1680,14 +1680,14 @@ void DrawDeveloperToolsMenu() { ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); if (mStatsWindow) { - if (ImGui::Button(GetWindowButtonText("Stats", CVarGetInteger("gStatsEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Stats", CVarGetInteger(CVAR_STATS_WINDOW_OPEN, 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mStatsWindow->ToggleVisibility(); } UIWidgets::Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); } UIWidgets::Spacer(0); if (mConsoleWindow) { - if (ImGui::Button(GetWindowButtonText("Console", CVarGetInteger("gConsoleEnabled", 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + if (ImGui::Button(GetWindowButtonText("Console", CVarGetInteger(CVAR_CONSOLE_WINDOW_OPEN, 0)).c_str(), ImVec2(-1.0f, 0.0f))) { mConsoleWindow->ToggleVisibility(); } UIWidgets::Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index 994505dd6..b3d137c1f 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -52,7 +52,7 @@ namespace SOH { conf->Erase("Game.Patches Archive"); } if (CVarGetInteger("gDirtPathFix", 0) != 0) { - CVarSetInteger("gZFightingMode", CVarGetInteger("gDirtPathFix", 0)); + CVarSetInteger(CVAR_Z_FIGHTING_MODE, CVarGetInteger("gDirtPathFix", 0)); CVarClear("gDirtPathFix"); } if (CVarGetInteger("gRandomizedEnemies", 0) != 0) { diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 8abce78db..8ac676c55 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -65,7 +65,7 @@ void SkeletonPatcher::ClearSkeletons() } void SkeletonPatcher::UpdateSkeletons() { - bool isHD = CVarGetInteger("gAltAssets", 0); + bool isHD = CVarGetInteger(CVAR_ALT_ASSETS, 0); for (auto skel : skeletons) { Skeleton* newSkel = (Skeleton*)Ship::Context::GetInstance()->GetResourceManager() diff --git a/soh/src/code/game.c b/soh/src/code/game.c index 5fca89dbd..8d97177fd 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -467,7 +467,7 @@ void GameState_Destroy(GameState* gameState) { // Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system. ResourceMgr_ClearSkeletons(); - if (CVarGetInteger("gAltAssets", 0)) { + if (CVarGetInteger(CVAR_ALT_ASSETS, 0)) { ResourceUnloadDirectory("alt/*"); gfx_texture_cache_clear(); } diff --git a/soh/src/code/gfxprint.c b/soh/src/code/gfxprint.c index 8a0dbead4..9caad46a8 100644 --- a/soh/src/code/gfxprint.c +++ b/soh/src/code/gfxprint.c @@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt; // https://github.com/HarbourMasters/Shipwright/issues/2762 typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t; font_texture_t GfxPrint_TextureToUse() { - if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { + if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { // If we have alt assets enabled, and we have alt prefixed font texture, use that return otrAlt; } else if (ResourceMgr_FileExists(rGfxPrintFontData)) { From fd9cd9c5ebf611ed1c3f42c6406182c0534c8099 Mon Sep 17 00:00:00 2001 From: Archez Date: Wed, 1 May 2024 16:41:17 -0400 Subject: [PATCH 207/300] Fix: add workaround for boost versions >=1.84.0 (#4098) --- .../container_hash/detail/hash_range_32.hpp | 15 ++++++++++-- .../boost_custom/container_hash/hash_32.hpp | 24 +++++++++++++++---- .../boost_custom/container_hash/version.hpp | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp index 7430152ab..cfa0a2a2d 100644 --- a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp +++ b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp @@ -46,10 +46,18 @@ template<> struct is_char_type: public boost::true_type {}; #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_SAME std::is_same +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_SAME is_same +#endif + template -inline typename boost::enable_if_< +inline typename BOOST_ENABLE_IF< is_char_type::value_type>::value && - is_same::iterator_category, std::random_access_iterator_tag>::value, + BOOST_IS_SAME::iterator_category, std::random_access_iterator_tag>::value, std::size_t>::type hash_range_32( uint32_t seed, It first, It last ) { @@ -114,4 +122,7 @@ std::size_t>::type } // namespace hash_detail } // namespace boost +#undef BOOST_ENABLE_IF +#undef BOOST_IS_SAME + #endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP diff --git a/soh/include/boost_custom/container_hash/hash_32.hpp b/soh/include/boost_custom/container_hash/hash_32.hpp index 4b955c43a..eaf459a34 100644 --- a/soh/include/boost_custom/container_hash/hash_32.hpp +++ b/soh/include/boost_custom/container_hash/hash_32.hpp @@ -23,6 +23,18 @@ #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_INTEGRAL hash_detail::is_integral +#define BOOST_IS_UNSIGNED is_unsigned +#define BOOST_MAKE_UNSIGNED make_unsigned +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_INTEGRAL boost::is_integral +#define BOOST_IS_UNSIGNED boost::is_unsigned +#define BOOST_MAKE_UNSIGNED boost::make_unsigned +#endif + namespace boost { @@ -36,7 +48,7 @@ namespace boost { template sizeof(uint32_t)), - bool is_unsigned = boost::is_unsigned::value, + bool is_unsigned = BOOST_IS_UNSIGNED::value, std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT, std::size_t type_bits = sizeof(T) * CHAR_BIT> struct hash_integral_impl_32; @@ -53,7 +65,7 @@ namespace boost { static uint32_t fn( T v ) { - typedef typename boost::make_unsigned::type U; + typedef typename BOOST_MAKE_UNSIGNED::type U; if( v >= 0 ) { @@ -97,7 +109,7 @@ namespace boost } // namespace hash_detail template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T v ) { return hash_detail::hash_integral_impl_32::fn( v ); @@ -106,7 +118,7 @@ namespace boost // contiguous ranges (string, vector, array) #if BOOST_VERSION_HAS_HASH_RANGE template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T const& v ) { return boost::hash_range_32( v.data(), v.data() + v.size() ); @@ -168,5 +180,9 @@ namespace boost } // namespace boost #undef BOOST_HASH_CHAR_TRAITS +#undef BOOST_ENABLE_IF +#undef BOOST_IS_INTEGRAL +#undef BOOST_IS_UNSIGNED +#undef BOOST_MAKE_UNSIGNED #endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP diff --git a/soh/include/boost_custom/container_hash/version.hpp b/soh/include/boost_custom/container_hash/version.hpp index 22ad6634c..3863b507c 100644 --- a/soh/include/boost_custom/container_hash/version.hpp +++ b/soh/include/boost_custom/container_hash/version.hpp @@ -6,4 +6,6 @@ #define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81) +#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84) + #endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP From 345cef9b781c3b029c300c2b2c684bbb55e41ef2 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 1 May 2024 22:47:40 -0400 Subject: [PATCH 208/300] detangle zapdutils (#4096) --- OTRExporter | 2 +- ZAPDTR | 2 +- libultraship | 2 +- soh/CMakeLists.txt | 10 ---------- soh/soh/Enhancements/audio/AudioCollection.cpp | 2 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 2 +- soh/soh/Enhancements/controls/SohInputEditorWindow.cpp | 2 +- soh/soh/Enhancements/debugconsole.cpp | 2 +- soh/soh/Extractor/Extract.cpp | 2 +- soh/soh/OTRGlobals.cpp | 2 +- soh/soh/z_message_OTR.cpp | 2 +- soh/soh/z_play_otr.cpp | 2 +- soh/soh/z_scene_otr.cpp | 2 +- 13 files changed, 12 insertions(+), 22 deletions(-) diff --git a/OTRExporter b/OTRExporter index 8815dd98f..c1e30dad1 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 8815dd98f25d5f4c7a80f162e9ee1ec0a3f7dd4e +Subproject commit c1e30dad1b333a6fb19a6b00b680d17e6f7d773a diff --git a/ZAPDTR b/ZAPDTR index 9f9d0be3c..222cb8a23 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit 9f9d0be3c914354ecabab3695581f1123c13ac20 +Subproject commit 222cb8a23bd0fa8b901b1654ac5d6cc2ecb25a2e diff --git a/libultraship b/libultraship index fd603a40e..986d03712 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit fd603a40e0c847092d142d77f144ec44c386f323 +Subproject commit 986d037126f13d83bc35daa15a115c714a6fb2b3 diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index a32c0ac4f..f8ee476b8 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -92,10 +92,6 @@ if (NOT TARGET libultraship) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../libultraship ${CMAKE_BINARY_DIR}/libultraship) endif() -if (NOT TARGET ZAPDUtils) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils ${CMAKE_BINARY_DIR}/ZAPDUtils) -endif() - if (NOT TARGET ZAPDLib) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD) endif() @@ -390,7 +386,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic/Fast3D/U64/PR ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/src/graphic - ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD/resource/type ${SDL2-INCLUDE} ${SDL2-NET-INCLUDE} @@ -666,7 +661,6 @@ endif() # Dependencies ################################################################################ add_dependencies(${PROJECT_NAME} - ZAPDUtils libultraship ) if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS") @@ -680,7 +674,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" - "ZAPDUtils;" "ZAPDLib;" "glu32;" "SDL2::SDL2;" @@ -695,7 +688,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32") set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" - "ZAPDUtils;" "ZAPDLib;" "glu32;" "SDL2::SDL2;" @@ -713,7 +705,6 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch") find_package(Threads REQUIRED) set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" - "ZAPDUtils;" SDL2::SDL2 -lglad Threads::Threads @@ -735,7 +726,6 @@ else() find_package(Threads REQUIRED) set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" - "ZAPDUtils;" "ZAPDLib;" SDL2::SDL2 "$<$:SDL2_net::SDL2_net>" diff --git a/soh/soh/Enhancements/audio/AudioCollection.cpp b/soh/soh/Enhancements/audio/AudioCollection.cpp index 8f9c01d0a..dadcbf2ac 100644 --- a/soh/soh/Enhancements/audio/AudioCollection.cpp +++ b/soh/soh/Enhancements/audio/AudioCollection.cpp @@ -2,7 +2,7 @@ #include "sequence.h" #include "sfx.h" #include -#include +#include #include #include #include diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index f33f73b3d..3b0c2bb12 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -9,7 +9,7 @@ #include #include "../randomizer/3drando/random.hpp" #include "../../OTRGlobals.h" -#include +#include #include "../../UIWidgets.hpp" #include "AudioCollection.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index be71c7de1..f5acca70b 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1,5 +1,5 @@ #include "SohInputEditorWindow.h" -#include +#include #include "soh/OTRGlobals.h" #include "../../UIWidgets.hpp" #include "z64.h" diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 470785f7b..ad51f1e4b 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -13,7 +13,7 @@ #define Path _Path #define PATH_HACK -#include +#include #include #include diff --git a/soh/soh/Extractor/Extract.cpp b/soh/soh/Extractor/Extract.cpp index b08783763..673afc8a6 100644 --- a/soh/soh/Extractor/Extract.cpp +++ b/soh/soh/Extractor/Extract.cpp @@ -6,7 +6,7 @@ #endif #include "Extract.h" #include "portable-file-dialogs.h" -#include +#include #include "variables.h" #ifdef unix diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 744db9561..4f54e4e80 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -47,7 +47,7 @@ #include "z64.h" #include "macros.h" #include "Fonts.h" -#include +#include #include "Enhancements/custom-message/CustomMessageManager.h" #include "Enhancements/presets.h" #include "util.h" diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 49e1e91c4..9136d916f 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -1,7 +1,7 @@ #include "OTRGlobals.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "global.h" #include "vt.h" #include "soh/resource/type/Text.h" diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index ff485664d..237b48ef3 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -1,7 +1,7 @@ #include "OTRGlobals.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "global.h" #include "vt.h" diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 6c5ba67df..0aa92e0ec 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -1,7 +1,7 @@ #include "OTRGlobals.h" #include #include "soh/resource/type/Scene.h" -#include +#include #include "global.h" #include "vt.h" #include "soh/resource/type/CollisionHeader.h" From bcf5a0c307c71e58bec8deda90605ef720d6055c Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 2 May 2024 00:14:36 -0400 Subject: [PATCH 209/300] support lus factories no longer being registered in `RegisterGlobalResourceFactories` (#4099) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libultraship b/libultraship index 986d03712..33ede2652 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 986d037126f13d83bc35daa15a115c714a6fb2b3 +Subproject commit 33ede265298930577193c51ca1f2a0b291744ea3 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4f54e4e80..4149ee461 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -92,6 +92,12 @@ GameInteractorSail* GameInteractorSail::Instance; #include // Resource Types/Factories +#include "resource/type/Array.h" +#include "resource/type/Blob.h" +#include "resource/type/DisplayList.h" +#include "resource/type/Matrix.h" +#include "resource/type/Texture.h" +#include "resource/type/Vertex.h" #include "soh/resource/type/SohResourceType.h" #include "soh/resource/type/Animation.h" #include "soh/resource/type/AudioSample.h" @@ -105,6 +111,12 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/type/Skeleton.h" #include "soh/resource/type/SkeletonLimb.h" #include "soh/resource/type/Text.h" +#include "resource/factory/ArrayFactory.h" +#include "resource/factory/BlobFactory.h" +#include "resource/factory/DisplayListFactory.h" +#include "resource/factory/MatrixFactory.h" +#include "resource/factory/TextureFactory.h" +#include "resource/factory/VertexFactory.h" #include "soh/resource/importer/AnimationFactory.h" #include "soh/resource/importer/AudioSampleFactory.h" #include "soh/resource/importer/AudioSequenceFactory.h" @@ -331,6 +343,15 @@ OTRGlobals::OTRGlobals() { SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); auto loader = context->GetResourceManager()->GetResourceLoader(); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Texture", static_cast(LUS::ResourceType::Texture), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Texture", static_cast(LUS::ResourceType::Texture), 1); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Vertex", static_cast(LUS::ResourceType::Vertex), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "Vertex", static_cast(LUS::ResourceType::Vertex), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Matrix", static_cast(LUS::ResourceType::Matrix), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Array", static_cast(LUS::ResourceType::Array), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Blob", static_cast(LUS::ResourceType::Blob), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Animation", static_cast(SOH::ResourceType::SOH_Animation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast(SOH::ResourceType::SOH_PlayerAnimation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? From 725670d9984b23a5254a28dbfdbf54d68364e1a4 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 2 May 2024 14:43:52 -0400 Subject: [PATCH 210/300] support lus strhash64 change (#4102) --- OTRExporter | 2 +- libultraship | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OTRExporter b/OTRExporter index c1e30dad1..3cea9ee7c 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit c1e30dad1b333a6fb19a6b00b680d17e6f7d773a +Subproject commit 3cea9ee7c017d842aa4d9ceeb8d3ffbf29c6effb diff --git a/libultraship b/libultraship index 33ede2652..0a4500455 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 33ede265298930577193c51ca1f2a0b291744ea3 +Subproject commit 0a45004554c0917c771300957a7cd87271516965 From e02e4ead02e30b1c01bfebcaf14f403e4f3c921c Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 3 May 2024 11:07:07 -0400 Subject: [PATCH 211/300] support lus fetching stb (#4105) --- ZAPDTR | 2 +- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ZAPDTR b/ZAPDTR index 222cb8a23..f38a9c92e 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit 222cb8a23bd0fa8b901b1654ac5d6cc2ecb25a2e +Subproject commit f38a9c92eb99368c0607acf356d5651ebdc96f51 diff --git a/libultraship b/libultraship index 0a4500455..f55d3910e 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 0a45004554c0917c771300957a7cd87271516965 +Subproject commit f55d3910e7ba29f6973512c15cde21d2a0b2e292 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4149ee461..86d96afbd 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -22,7 +22,6 @@ #include #endif #include -#include #define DRMP3_IMPLEMENTATION #include #define DRWAV_IMPLEMENTATION From b6fc54ad8b70421f2fe1792024b77c26a88882ff Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 3 May 2024 12:55:38 -0400 Subject: [PATCH 212/300] support lus `dr_libs` removal (#4108) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libultraship b/libultraship index f55d3910e..7d71a2906 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit f55d3910e7ba29f6973512c15cde21d2a0b2e292 +Subproject commit 7d71a290657a2d3b09a83e8b33025e807f4fb38e diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 86d96afbd..2dd324fe8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -22,10 +22,6 @@ #include #endif #include -#define DRMP3_IMPLEMENTATION -#include -#define DRWAV_IMPLEMENTATION -#include #include #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include "Enhancements/controls/SohInputEditorWindow.h" From de715da1842ac3df36badacc9b66b50f7e850565 Mon Sep 17 00:00:00 2001 From: Archez Date: Sat, 4 May 2024 17:49:36 -0400 Subject: [PATCH 213/300] explicitly include unordered_map header (#122) --- soh/soh/Enhancements/game-interactor/GameInteractor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 17b6198b3..e0b1c1ce1 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -420,6 +420,7 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state); #ifdef __cplusplus #include +#include #include #include #include From e71839ed8f90a902679f2533fde78d44e3000e6a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 4 May 2024 17:50:19 -0400 Subject: [PATCH 214/300] Conversion of Nabooru Quick Death to VB hook (#120) * Nabooru quick death conversion * Fix brackets, not sure exactly how this was working before. --- .../game-interactor/GameInteractor.h | 1 + .../Enhancements/timesaver_hook_handlers.cpp | 24 +++++++++++++++++++ soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c | 20 +--------------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index e0b1c1ce1..84126099f 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -387,6 +387,7 @@ typedef enum { /*** Quick Boss Deaths ***/ // Vanilla condition: true GI_VB_PHANTOM_GANON_DEATH_SCENE, + GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, } GIVanillaBehavior; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 52e14ab8c..642eae7cc 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -25,6 +25,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" #include +#include #include extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -746,6 +747,29 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case GI_VB_NABOORU_KNUCKLE_DEATH_SCENE: { + EnIk* ik = static_cast(opt); + if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO)) { + // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor + if ((ik->actor.colChkInfo.health <= 10)) { + s32 i; + Vec3f pos; + Vec3f sp7C = { 0.0f, 0.5f, 0.0f }; + int flameAmount = 100; + + for (i = flameAmount; i >= 0; i--) { + pos.x = ik->actor.world.pos.x + Rand_CenteredFloat(120.0f); + pos.z = ik->actor.world.pos.z + Rand_CenteredFloat(120.0f); + pos.y = ik->actor.world.pos.y + 20.0f + Rand_CenteredFloat(120.0f); + EffectSsDeadDb_Spawn(gPlayState, &pos, &sp7C, &sp7C, 100, 0, 255, 255, 255, 255, 0, 0, 255, 1, 9, + true); + } + Actor_Kill(&ik->actor); + } + *should = false; + } + break; + } } } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index aaf0e0342..5f1634237 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -1439,28 +1439,10 @@ void func_80A781CC(Actor* thisx, PlayState* play) { if (!Play_InCsMode(play)) { this->actor.update = EnIk_Update; this->actor.draw = EnIk_Draw; - // Don't initiate nabooru defeat CS in rando - if (!(IS_RANDO)) { + if (GameInteractor_Should(GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, true, this)) { Cutscene_SetSegment(play, gSpiritBossNabooruKnuckleDefeatCs); gSaveContext.cutsceneTrigger = 1; Actor_SetScale(&this->actor, 0.01f); - } else { - // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor - if ((this->actor.colChkInfo.health <= 10)) { - s32 i; - Vec3f pos; - Vec3f sp7C = { 0.0f, 0.5f, 0.0f }; - int flameAmount = 100; - - for (i = flameAmount; i >= 0; i--) { - pos.x = this->actor.world.pos.x + Rand_CenteredFloat(120.0f); - pos.z = this->actor.world.pos.z + Rand_CenteredFloat(120.0f); - pos.y = this->actor.world.pos.y + 20.0f + Rand_CenteredFloat(120.0f); - EffectSsDeadDb_Spawn(play, &pos, &sp7C, &sp7C, 100, 0, 255, 255, 255, 255, 0, 0, 255, 1, 9, - true); - } - Actor_Kill(&this->actor); - } } Flags_SetEventChkInf(EVENTCHKINF_FINISHED_NABOORU_BATTLE); func_80A7735C(this, play); From 6443a986d9751b87a0b4e82c15f82a9971f88201 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 5 May 2024 12:14:55 -0700 Subject: [PATCH 215/300] Final Step of CVar macro/sectionalizing (#4107) * p * Missed the prefix renames. * More missed ones. * Mostly finished cleanup. Removed a few CVars and some related functionality. * Bit more (prepping non-existent title card color editing). * Resolve gCrowdControl. * Final cleanup. * Universal constant, not acceleration... * Preset CVars. --- soh/soh/Enhancements/bootcommands.c | 15 +- soh/soh/Enhancements/controls/InputViewer.cpp | 136 +-- soh/soh/Enhancements/controls/InputViewer.h | 2 + .../controls/SohInputEditorWindow.cpp | 122 +-- .../cosmetics/CosmeticsEditor.cpp | 157 +-- .../cosmetics/authenticGfxPatches.cpp | 4 +- soh/soh/Enhancements/debugger/actorViewer.cpp | 9 +- soh/soh/Enhancements/debugger/colViewer.cpp | 129 ++- .../Enhancements/debugger/debugSaveEditor.cpp | 2 +- soh/soh/Enhancements/debugger/valueViewer.cpp | 5 +- .../GameInteractor_RawAction.cpp | 20 +- soh/soh/Enhancements/gameplaystats.cpp | 28 +- soh/soh/Enhancements/gameplaystats.h | 2 +- soh/soh/Enhancements/mods.cpp | 16 +- soh/soh/Enhancements/nametag.cpp | 2 +- soh/soh/Enhancements/presets.cpp | 2 +- soh/soh/Enhancements/presets.h | 88 +- .../randomizer/3drando/rando_main.cpp | 7 +- .../Enhancements/randomizer/randomizer.cpp | 14 +- .../randomizer/randomizer_check_tracker.cpp | 6 +- .../resolution-editor/ResolutionEditor.cpp | 101 +- soh/soh/Enhancements/tts/tts.cpp | 40 +- soh/soh/OTRGlobals.cpp | 36 +- soh/soh/SaveManager.cpp | 4 +- soh/soh/SohGui.cpp | 2 +- soh/soh/SohMenuBar.cpp | 60 +- soh/soh/UIWidgets.cpp | 8 +- soh/src/code/audioMgr.c | 8 +- soh/src/code/audio_playback.c | 4 +- soh/src/code/audio_synthesis.c | 2 +- soh/src/code/code_800EC960.c | 24 +- soh/src/code/game.c | 2 +- soh/src/code/gfxprint.c | 4 +- soh/src/code/graph.c | 2 +- soh/src/code/padmgr.c | 4 +- soh/src/code/z_actor.c | 16 +- soh/src/code/z_camera.c | 32 +- soh/src/code/z_en_item00.c | 3 +- soh/src/code/z_kaleido_setup.c | 10 +- soh/src/code/z_lib.c | 2 +- soh/src/code/z_lifemeter.c | 60 +- soh/src/code/z_map_exp.c | 174 ++-- soh/src/code/z_map_mark.c | 38 +- soh/src/code/z_message_PAL.c | 2 +- soh/src/code/z_parameter.c | 894 +++++++++--------- soh/src/code/z_play.c | 26 +- soh/src/code/z_player_lib.c | 14 +- soh/src/code/z_room.c | 5 +- soh/src/code/z_sram.c | 4 +- soh/src/code/z_view.c | 4 +- .../actors/ovl_Arms_Hook/z_arms_hook.c | 2 +- .../ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c | 5 +- .../z_bg_spot06_objects.c | 2 +- .../actors/ovl_En_Blkobj/z_en_blkobj.c | 8 +- .../actors/ovl_En_Bom_Chu/z_en_bom_chu.c | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 2 +- .../actors/ovl_En_Clear_Tag/z_en_clear_tag.c | 2 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 6 +- .../overlays/actors/ovl_En_Horse/z_en_horse.c | 2 +- soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c | 9 +- soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c | 4 +- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 20 +- .../actors/ovl_En_Partner/z_en_partner.c | 4 +- soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c | 4 +- .../actors/ovl_En_Torch2/z_en_torch2.c | 4 +- .../overlays/actors/ovl_Fishing/z_fishing.c | 2 +- .../actors/ovl_Magic_Dark/z_magic_dark.c | 6 +- .../actors/ovl_Magic_Fire/z_magic_fire.c | 6 +- .../actors/ovl_player_actor/z_player.c | 144 +-- .../ovl_Effect_Ss_Extra/z_eff_ss_extra.c | 2 +- .../ovl_file_choose/z_file_choose.c | 63 +- .../ovl_file_choose/z_file_copy_erase.c | 10 +- .../ovl_file_choose/z_file_nameset_PAL.c | 10 +- .../overlays/gamestates/ovl_select/z_select.c | 30 +- .../overlays/gamestates/ovl_title/z_title.c | 2 +- .../ovl_kaleido_scope/z_kaleido_collect.c | 2 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 10 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 144 +-- .../ovl_kaleido_scope/z_kaleido_map_PAL.c | 8 +- .../misc/ovl_kaleido_scope/z_kaleido_prompt.c | 2 +- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 22 +- .../misc/ovl_kaleido_scope/z_lmap_mark.c | 2 +- 82 files changed, 1435 insertions(+), 1457 deletions(-) diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index be3a766dc..16ad651fc 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -9,6 +9,7 @@ #include #include #include +#include "soh/OTRGlobals.h" uint8_t gLoadFileSelect = 0, gSkipLogoTest = 0; @@ -21,13 +22,13 @@ static BootCommand sCommands[] = { { "--skiplogo", BootCommands_Command_SkipLogo void BootCommands_Init() { // Clears vars to prevent randomizer menu from being disabled - CVarClear("gRandoGenerating"); // Clear when a crash happened during rando seed generation - CVarClear("gNewSeedGenerated"); - CVarClear("gOnFileSelectNameEntry"); // Clear when soh is killed on the file name entry page - CVarClear("gBetterDebugWarpScreenMQMode"); - CVarClear("gBetterDebugWarpScreenMQModeScene"); - CVarClear("gCheatEasyPauseBufferLastInputs"); - CVarClear("gCheatEasyPauseBufferTimer"); + CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation + CVarClear(CVAR_GENERAL("NewSeedGenerated")); + CVarClear(CVAR_GENERAL("OnFileSelectNameEntry")); // Clear when soh is killed on the file name entry page + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQMode")); + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene")); + CVarClear(CVAR_GENERAL("CheatEasyPauseBufferLastInputs")); + CVarClear(CVAR_GENERAL("CheatEasyPauseBufferTimer")); #if defined(__SWITCH__) || defined(__WIIU__) CVarRegisterInteger(CVAR_IMGUI_CONTROLLER_NAV, 1); // always enable controller nav on switch/wii u #endif diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index c9b85c607..93727b5fa 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -126,12 +126,12 @@ void InputViewer::DrawElement() { ImVec2 size = ImGui::GetContentRegionAvail(); #ifdef __WIIU__ - const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f) * 2.0f; + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f) * 2.0f; #else - const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f); + const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); #endif - const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0); - const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED); + const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); + const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); @@ -139,10 +139,10 @@ void InputViewer::DrawElement() { ImGui::SetNextWindowSize(ImVec2( scaledBGSize.x + 20, scaledBGSize.y + - (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f) + 20)); + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + 20)); ImGui::SetNextWindowContentSize( ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * - CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f))); + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); ImGui::SetNextWindowPos( ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), ImGuiCond_FirstUseEver); @@ -156,7 +156,7 @@ void InputViewer::DrawElement() { ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoFocusOnAppearing; - if (!CVarGetInteger("gInputViewer.EnableDragging", 1)) { + if (!CVarGetInteger(CVAR_INPUT_VIEWER("EnableDragging"), 1)) { windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; } @@ -164,7 +164,7 @@ void InputViewer::DrawElement() { ImGui::SetCursorPos(ImVec2(10, 10)); const ImVec2 aPos = ImGui::GetCursorPos(); - if (CVarGetInteger("gInputViewer.ShowBackground", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("ShowBackground"), 1)) { ImGui::SetNextItemAllowOverlap(); // Background ImGui::Image( @@ -173,59 +173,59 @@ void InputViewer::DrawElement() { } // A/B - if (CVarGetInteger("gInputViewer.BBtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.ABtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode); } // C buttons - if (CVarGetInteger("gInputViewer.CUp", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.CLeft", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.CRight", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.CDown", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode); } // L/R/Z - if (CVarGetInteger("gInputViewer.LBtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.RBtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode); } - if (CVarGetInteger("gInputViewer.ZBtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode); } // Start - if (CVarGetInteger("gInputViewer.StartBtn", 1)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, @@ -233,7 +233,7 @@ void InputViewer::DrawElement() { } // Dpad - if (CVarGetInteger("gInputViewer.Dpad", 0)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, @@ -256,8 +256,8 @@ void InputViewer::DrawElement() { // Analog Stick const int analogOutlineMode = - CVarGetInteger("gInputViewer.AnalogStick.OutlineMode", STICK_MODE_ALWAYS_SHOWN); - const float maxStickDistance = CVarGetInteger("gInputViewer.AnalogStick.Movement", 12); + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); + const float maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { ImGui::SetNextItemAllowOverlap(); @@ -267,7 +267,7 @@ void InputViewer::DrawElement() { scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } const int analogStickMode = - CVarGetInteger("gInputViewer.AnalogStick.VisibilityMode", STICK_MODE_ALWAYS_SHOWN); + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { ImGui::SetNextItemAllowOverlap(); @@ -279,9 +279,9 @@ void InputViewer::DrawElement() { } // Right Stick - const float maxRightStickDistance = CVarGetInteger("gInputViewer.RightStick.Movement", 7); + const float maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); const int rightOutlineMode = - CVarGetInteger("gInputViewer.RightStick.OutlineMode", STICK_MODE_ALWAYS_HIDDEN); + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { ImGui::SetNextItemAllowOverlap(); @@ -291,7 +291,7 @@ void InputViewer::DrawElement() { scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); } const int rightStickMode = - CVarGetInteger("gInputViewer.RightStick.VisibilityMode", STICK_MODE_ALWAYS_HIDDEN); + CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { ImGui::SetNextItemAllowOverlap(); @@ -304,36 +304,36 @@ void InputViewer::DrawElement() { // Analog stick angle text if (showAnalogAngles) { - ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger("gInputViewer.AnalogAngles.Offset", 0) * scale, + ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, scaledBGSize.y + aPos.y + 10)); // Scale font with input viewer scale float oldFontScale = ImGui::GetFont()->Scale; - ImGui::GetFont()->Scale *= scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f); + ImGui::GetFont()->Scale *= scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f); ImGui::PushFont(ImGui::GetFont()); // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; // ESS range - const int range1Min = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Min", 8); - const int range1Max = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Max", 27); + const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); + const int range1Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Max"), 27); // Walking speed range - const int range2Min = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Min", 27); - const int range2Max = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Max", 62); + const int range2Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Min"), 27); + const int range2Max = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Max"), 62); // Push color based on angle ranges - if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0) && + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { ImGui::PushStyleColor( ImGuiCol_Text, - color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)))); - } else if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0) && + color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), vec2Color(range1Color)))); + } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) && (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { ImGui::PushStyleColor( ImGuiCol_Text, - color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)))); + color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), vec2Color(range2Color)))); } else { - ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor("gInputViewer.AnalogAngles.TextColor", + ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), vec2Color(textColor)))); } @@ -364,60 +364,60 @@ void InputViewerSettingsWindow::DrawElement() { if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) { // gInputViewer.Scale - UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", "gInputViewer.Scale", 0.1f, 5.0f, "", + UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", CVAR_INPUT_VIEWER("Scale"), 0.1f, 5.0f, "", 1.0f, false, true); UIWidgets::Tooltip("Sets the on screen size of the input viewer"); // gInputViewer.EnableDragging - UIWidgets::EnhancementCheckbox("Enable Dragging", "gInputViewer.EnableDragging", false, "", + UIWidgets::EnhancementCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); UIWidgets::PaddedSeparator(true, true); // gInputViewer.ShowBackground - UIWidgets::EnhancementCheckbox("Show Background Layer", "gInputViewer.ShowBackground", false, "", + UIWidgets::EnhancementCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); UIWidgets::PaddedSeparator(true, true); if (ImGui::CollapsingHeader("Buttons")) { // gInputViewer.ABtn - UIWidgets::EnhancementCheckbox("Show A-Button Layers", "gInputViewer.ABtn", false, "", + UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.BBtn - UIWidgets::EnhancementCheckbox("Show B-Button Layers", "gInputViewer.BBtn", false, "", + UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.CUp - UIWidgets::EnhancementCheckbox("Show C-Up Layers", "gInputViewer.CUp", false, "", + UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.CRight - UIWidgets::EnhancementCheckbox("Show C-Right Layers", "gInputViewer.CRight", false, "", + UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.CDown - UIWidgets::EnhancementCheckbox("Show C-Down Layers", "gInputViewer.CDown", false, "", + UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.CLeft - UIWidgets::EnhancementCheckbox("Show C-Left Layers", "gInputViewer.CLeft", false, "", + UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.LBtn - UIWidgets::EnhancementCheckbox("Show L-Button Layers", "gInputViewer.LBtn", false, "", + UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.RBtn - UIWidgets::EnhancementCheckbox("Show R-Button Layers", "gInputViewer.RBtn", false, "", + UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.ZBtn - UIWidgets::EnhancementCheckbox("Show Z-Button Layers", "gInputViewer.ZBtn", false, "", + UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.StartBtn - UIWidgets::EnhancementCheckbox("Show Start Button Layers", "gInputViewer.StartBtn", false, "", + UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); // gInputViewer.Dpad - UIWidgets::EnhancementCheckbox("Show D-Pad Layers", "gInputViewer.Dpad", false, "", + UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "", UIWidgets::CheckboxGraphics::Checkmark, false); // gInputViewer.ButtonOutlineMode UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false); - UIWidgets::EnhancementCombobox("gInputViewer.ButtonOutlineMode", buttonOutlineOptions, + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, BUTTON_OUTLINE_NOT_PRESSED); UIWidgets::Tooltip( "Sets the desired visibility behavior for the button outline/background layers. Useful for " @@ -429,21 +429,21 @@ void InputViewerSettingsWindow::DrawElement() { if (ImGui::CollapsingHeader("Analog Stick")) { // gInputViewer.AnalogStick.VisibilityMode UIWidgets::PaddedText("Analog Stick Visibility", true, false); - UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.VisibilityMode", stickModeOptions, + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions, STICK_MODE_ALWAYS_SHOWN); UIWidgets::Tooltip( "Determines the conditions under which the moving layer of the analog stick texture is visible."); // gInputViewer.AnalogStick.OutlineMode UIWidgets::PaddedText("Analog Stick Outline/Background Visibility", true, false); - UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.OutlineMode", stickModeOptions, + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions, STICK_MODE_ALWAYS_SHOWN); UIWidgets::Tooltip( "Determines the conditions under which the analog stick outline/background texture is visible."); // gInputViewer.AnalogStick.Movement UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement", - "gInputViewer.AnalogStick.Movement", 0, 200, "", 12, true); + CVAR_INPUT_VIEWER("AnalogStick.Movement"), 0, 200, "", 12, true); UIWidgets::Tooltip( "Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers."); UIWidgets::PaddedSeparator(true, true); @@ -452,21 +452,21 @@ void InputViewerSettingsWindow::DrawElement() { if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { // gInputViewer.RightStick.VisibilityMode UIWidgets::PaddedText("Right Stick Visibility", true, false); - UIWidgets::EnhancementCombobox("gInputViewer.RightStick.VisibilityMode", stickModeOptions, + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions, STICK_MODE_HIDDEN_IN_DEADZONE); UIWidgets::Tooltip( "Determines the conditions under which the moving layer of the right stick texture is visible."); // gInputViewer.RightStick.OutlineMode UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false); - UIWidgets::EnhancementCombobox("gInputViewer.RightStick.OutlineMode", stickModeOptions, + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions, STICK_MODE_HIDDEN_IN_DEADZONE); UIWidgets::Tooltip( "Determines the conditions under which the right stick outline/background texture is visible."); // gInputViewer.RightStick.Movement UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement", - "gInputViewer.RightStick.Movement", 0, 200, "", 7, true); + CVAR_INPUT_VIEWER("RightStick.Movement"), 0, 200, "", 7, true); UIWidgets::Tooltip( "Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."); UIWidgets::PaddedSeparator(true, true); @@ -474,42 +474,42 @@ void InputViewerSettingsWindow::DrawElement() { if (ImGui::CollapsingHeader("Analog Angle Values")) { // gAnalogAngles - UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", "gInputViewer.AnalogAngles.Enabled"); + UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled")); UIWidgets::Tooltip("Displays analog stick angle values in the input viewer"); - if (CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) { // gInputViewer.AnalogAngles.TextColor if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) { - CVarSetColor("gInputViewer.AnalogAngles.TextColor", vec2Color(textColor)); + CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), vec2Color(textColor)); } // gAnalogAngleScale UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale", - "gInputViewer.AnalogAngles.Scale", 0.1f, 5.0f, "", 1.0f, true, true); + CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 0.1f, 5.0f, "", 1.0f, true, true); // gInputViewer.AnalogAngles.Offset UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset", - "gInputViewer.AnalogAngles.Offset", 0, 400, "", 0, true); + CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0, 400, "", 0, true); UIWidgets::PaddedSeparator(true, true); // gInputViewer.AnalogAngles.Range1.Enabled - UIWidgets::EnhancementCheckbox("Highlight ESS Position", "gInputViewer.AnalogAngles.Range1.Enabled"); + UIWidgets::EnhancementCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled")); UIWidgets::Tooltip( "Highlights the angle value text when the analog stick is in ESS position (on flat ground)"); - if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) { // gInputViewer.AnalogAngles.Range1.Color if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) { - CVarSetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)); + CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), vec2Color(range1Color)); } } UIWidgets::PaddedSeparator(true, true); // gInputViewer.AnalogAngles.Range2.Enabled UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles", - "gInputViewer.AnalogAngles.Range2.Enabled"); + CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled")); UIWidgets::Tooltip("Highlights the angle value text when the analog stick is at an angle that would " "produce a walking speed (on flat ground)\n\n" "Useful for 1.0 Empty Jumpslash Quick Put Away"); - if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0)) { + if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) { // gInputViewer.AnalogAngles.Range2.Color if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) { - CVarSetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)); + CVarSetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), vec2Color(range2Color)); } } } diff --git a/soh/soh/Enhancements/controls/InputViewer.h b/soh/soh/Enhancements/controls/InputViewer.h index 4d528ead4..3e1e9c987 100644 --- a/soh/soh/Enhancements/controls/InputViewer.h +++ b/soh/soh/Enhancements/controls/InputViewer.h @@ -2,6 +2,8 @@ #include +#define CVAR_INPUT_VIEWER(var) "gInputViewer." var + typedef enum { BUTTON_OUTLINE_ALWAYS_SHOWN, BUTTON_OUTLINE_NOT_PRESSED, diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index f5acca70b..667d96c18 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1070,15 +1070,15 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { "Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom" }; UIWidgets::PaddedText("Source"); - UIWidgets::EnhancementCombobox("gLedColorSource", ledSources, LED_SOURCE_TUNIC_ORIGINAL); + UIWidgets::EnhancementCombobox(CVAR_SETTING("LEDColorSource"), ledSources, LED_SOURCE_TUNIC_ORIGINAL); UIWidgets::Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " "health < 40%. Green otherwise.\n\n" "Tunics: colors will mirror currently equipped tunic, whether original or the current " "values in Cosmetics Editor.\n\n" "Custom: single, solid color"); - if (CVarGetInteger("gLedColorSource", 1) == LED_SOURCE_CUSTOM) { + if (CVarGetInteger(CVAR_SETTING("LEDColorSource"), 1) == LED_SOURCE_CUSTOM) { UIWidgets::Spacer(3); - auto port1Color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); + auto port1Color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 }); ImVec4 colorVec = { port1Color.r / 255.0f, port1Color.g / 255.0f, port1Color.b / 255.0f, 1.0f }; if (ImGui::ColorEdit3("", (float*)&colorVec, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) { @@ -1087,18 +1087,18 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) { color.g = colorVec.y * 255.0; color.b = colorVec.z * 255.0; - CVarSetColor24("gLedPort1Color", color); + CVarSetColor24(CVAR_SETTING("LEDPort1Color"), color); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); ImGui::Text("Custom Color"); } - UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", "gLedBrightness", 0.0f, + UIWidgets::PaddedEnhancementSliderFloat("Brightness: %.1f %%", "##LED_Brightness", CVAR_SETTING("LEDBrightness"), 0.0f, 1.0f, "", 1.0f, true, true); UIWidgets::Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."); UIWidgets::PaddedEnhancementCheckbox( - "Critical Health Override", "gLedCriticalOverride", true, true, - CVarGetInteger("gLedColorSource", LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, + "Critical Health Override", CVAR_SETTING("LEDCriticalOverride"), true, true, + CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, "Override redundant for health source.", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Shows red color when health is critical, otherwise displays according to color source."); } @@ -1478,14 +1478,14 @@ void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) { } // Ocarina button maps -static CustomButtonMap ocarinaD5 = {"D5", "gOcarinaD5BtnMap", BTN_CUP}; -static CustomButtonMap ocarinaB4 = {"B4", "gOcarinaB4BtnMap", BTN_CLEFT}; -static CustomButtonMap ocarinaA4 = {"A4", "gOcarinaA4BtnMap", BTN_CRIGHT}; -static CustomButtonMap ocarinaF4 = {"F4", "gOcarinaF4BtnMap", BTN_CDOWN}; -static CustomButtonMap ocarinaD4 = {"D4", "gOcarinaD4BtnMap", BTN_A}; -static CustomButtonMap ocarinaSongDisable = {"Disable songs", "gOcarinaDisableBtnMap", BTN_L}; -static CustomButtonMap ocarinaSharp = {"Pitch up", "gOcarinaSharpBtnMap", BTN_R}; -static CustomButtonMap ocarinaFlat = {"Pitch down", "gOcarinaFlatBtnMap", BTN_Z}; +static CustomButtonMap ocarinaD5 = {"D5", CVAR_SETTING("CustomOcarina.D5Button"), BTN_CUP}; +static CustomButtonMap ocarinaB4 = {"B4", CVAR_SETTING("CustomOcarina.B4Button"), BTN_CLEFT}; +static CustomButtonMap ocarinaA4 = {"A4", CVAR_SETTING("CustomOcarina.A4Button"), BTN_CRIGHT}; +static CustomButtonMap ocarinaF4 = {"F4", CVAR_SETTING("CustomOcarina.F4Button"), BTN_CDOWN}; +static CustomButtonMap ocarinaD4 = {"D4", CVAR_SETTING("CustomOcarina.D4Button"), BTN_A}; +static CustomButtonMap ocarinaSongDisable = {"Disable songs", CVAR_SETTING("CustomOcarina.DisableButton"), BTN_L}; +static CustomButtonMap ocarinaSharp = {"Pitch up", CVAR_SETTING("CustomOcarina.SharpButton"), BTN_R}; +static CustomButtonMap ocarinaFlat = {"Pitch down", CVAR_SETTING("CustomOcarina.FlatButton"), BTN_Z}; // Draw a button mapping setting consisting of a padded label and button dropdown. // excludedButtons indicates which buttons are unavailable to choose from. @@ -1534,13 +1534,13 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); + UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", CVAR_SETTING("CustomOcarina.Enabled")); - if (CVarGetInteger("gCustomOcarinaControls", 0) == 1) { + if (CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0) == 1) { if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { float labelWidth; N64ButtonMask disableMask = BTN_B; - if (CVarGetInteger("gDpadOcarina", 0)) { + if (CVarGetInteger(CVAR_SETTING("OcarinaControl.Dpad"), 0)) { disableMask |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } @@ -1583,9 +1583,9 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); TableHelper::InitHeader(false); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); + UIWidgets::EnhancementCheckbox("Play with D-pad", CVAR_SETTING("OcarinaControl.Dpad")); TableHelper::NextCol(); - UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); + UIWidgets::EnhancementCheckbox("Play with camera stick", CVAR_SETTING("OcarinaControl.RStick")); UIWidgets::Spacer(0); ImGui::EndTable(); } @@ -1598,35 +1598,35 @@ void SohInputEditorWindow::DrawCameraControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); + UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim")); UIWidgets::Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"); - if (CVarGetInteger("gRightStickAiming", 0)) { - UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", "gMoveWhileFirstPerson"); + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { + UIWidgets::PaddedEnhancementCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson")); UIWidgets::Tooltip("Changes the left stick to move the player while in first person mode"); } - UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", "gInvertAimingXAxis"); + UIWidgets::PaddedEnhancementCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis")); UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", "gInvertAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", "gInvertShieldAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Inverts the Shield Aiming Y Axis"); - UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", "gInvertShieldAimingXAxis"); + UIWidgets::PaddedEnhancementCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis")); UIWidgets::Tooltip("Inverts the Shield Aiming X Axis"); - UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", "gInvertZAimingYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::PaddedEnhancementCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"); - UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", "gDisableAutoCenterViewFirstPerson"); + UIWidgets::PaddedEnhancementCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView")); UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); - if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", "gEnableFirstPersonSensitivity", true, false)) { - if (!CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { - CVarClear("gFirstPersonCameraSensitivityX"); - CVarClear("gFirstPersonCameraSensitivityY"); + if (UIWidgets::PaddedEnhancementCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), true, false)) { + if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { + CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X")); + CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y")); } } - if (CVarGetInteger("gEnableFirstPersonSensitivity", 0)) { + if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { UIWidgets::EnhancementSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", "##FirstPersonSensitivity Horizontal", - "gFirstPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true); + CVAR_SETTING("FirstPersonCameraSensitivity.X"), 0.01f, 5.0f, "", 1.0f, true); UIWidgets::EnhancementSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", "##FirstPersonSensitivity Vertical", - "gFirstPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true); + CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 0.01f, 5.0f, "", 1.0f, true); } UIWidgets::Spacer(0); Ship::GuiWindow::EndGroupPanel(0); @@ -1636,22 +1636,22 @@ void SohInputEditorWindow::DrawCameraControlPanel() { ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera"); - UIWidgets::Tooltip("Enables free camera control\nNote: You must remap C buttons off of the right stick in the " + UIWidgets::PaddedEnhancementCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled")); + UIWidgets::Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " "controller config menu, and map the camera stick to the right stick."); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); - UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera"); - UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); - UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free camera"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis")); + UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free look"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free look"); UIWidgets::Spacer(0); UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", "##ThirdPersonSensitivity Horizontal", - "gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true); + CVAR_SETTING("FreeLook.CameraSensitivity.X"), 0.01f, 5.0f, "", 1.0f, true, true, false, true); UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", "##ThirdPersonSensitivity Vertical", - "gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true); + CVAR_SETTING("FreeLook.CameraSensitivity.Y"), 0.01f, 5.0f, "", 1.0f, true, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist", - "gFreeCameraDistMax", 100, 900, "", 185, true, false, true); + CVAR_SETTING("FreeLook.MaxCameraDistance"), 100, 900, "", 185, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed", - "gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true); + CVAR_SETTING("FreeLook.TransitionSpeed"), 0, 900, "", 25, true, false, true); Ship::GuiWindow::EndGroupPanel(0); } @@ -1659,13 +1659,13 @@ void SohInputEditorWindow::DrawDpadControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", "gDpadPause"); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause")); UIWidgets::Tooltip("Navigate Pause with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate\n" - "To make the cursor only move a single space no matter how long a direction is held, manually set gDpadHoldChange to 0"); - UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", "gDpadText"); + "To make the cursor only move a single space no matter how long a direction is held, manually set gSettings.DpadHoldChange to 0"); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText")); UIWidgets::Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad\n" - "To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gDpadHoldChange to 0"); - UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); + "To make the cursor only move a single space during name entry no matter how long a direction is held, manually set gSettings.DpadHoldChange to 0"); + UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", CVAR_SETTING("DpadEquips")); UIWidgets::Tooltip("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate"); Ship::GuiWindow::EndGroupPanel(0); } @@ -1676,31 +1676,31 @@ void SohInputEditorWindow::DrawMiscControlPanel() { Ship::GuiWindow::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail()); UIWidgets::PaddedText("Allow the cursor to be on any slot"); static const char* cursorOnAnySlot[3] = { "Only in Rando", "Always", "Never" }; - UIWidgets::EnhancementCombobox("gPauseAnyCursor", cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY); + UIWidgets::EnhancementCombobox(CVAR_SETTING("PauseAnyCursor"), cursorOnAnySlot, PAUSE_ANY_CURSOR_RANDO_ONLY); UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select " "certain items."); UIWidgets::Spacer(0); ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", "gEnableWalkModify", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), true, false); UIWidgets::Tooltip("Hold the assigned button to change the maximum walking or swimming speed"); - if (CVarGetInteger("gEnableWalkModify", 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) { UIWidgets::Spacer(5); Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", "gWalkSpeedToggle", true, false); + UIWidgets::PaddedEnhancementCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"), true, false); Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", "gWalkModifierDoesntChangeJump", true, false); - UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", "gWalkModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"), true, false); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 1: %.0f %%", "##WalkMod1", CVAR_SETTING("WalkModifier.Mapping1"), 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Walk Modifier 2: %.0f %%", "##WalkMod2", CVAR_SETTING("WalkModifier.Mapping2"), 0.0f, 5.0f, "", 1.0f, true, true, false, true); Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); - UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", "gSwimModifierOne", 0.0f, 5.0f, "", 1.0f, true, true, false, true); - UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", "gSwimModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 1: %.0f %%", "##SwimMod1", CVAR_SETTING("WalkModifier.SwimMapping1"), 0.0f, 5.0f, "", 1.0f, true, true, false, true); + UIWidgets::PaddedEnhancementSliderFloat("Swim Modifier 2: %.0f %%", "##SwimMod2", CVAR_SETTING("WalkModifier.SwimMapping2"), 0.0f, 5.0f, "", 1.0f, true, true, false, true); Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0); } ImGui::EndDisabled(); UIWidgets::Spacer(0); - UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL"); + UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", CVAR_SETTING("NaviOnL")); UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); Ship::GuiWindow::EndGroupPanel(0); } diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 51eabd08d..b932d24cc 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -229,24 +229,25 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), - COSMETIC_OPTION("Hud.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), - COSMETIC_OPTION("Hud.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), - COSMETIC_OPTION("Hud.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Hud.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), - COSMETIC_OPTION("Hud.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Hud.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Hud.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Hud.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), - COSMETIC_OPTION("Hud.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), - COSMETIC_OPTION("Hud.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("Hud.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), + COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), + COSMETIC_OPTION("HUD.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), + COSMETIC_OPTION("HUD.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("HUD.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), + // Todo (Cosmetics): re-implement title card colors COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), @@ -298,12 +299,12 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), - // COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gDF_Col - // COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gDF_Env + // COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement // COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Replace gNL_Diamond_Col / gNL_Orb_Col - // COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Replace gNL_Diamond_Env / gNL_Orb_Env + // COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), + // COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), @@ -350,11 +351,11 @@ static std::map cosmeticOptions = { }; static const char* MarginCvarList[] { - CVAR_COSMETIC("Hearts"), CVAR_COSMETIC("HeartsCount"), CVAR_COSMETIC("MagicBar"), CVAR_COSMETIC("VisualSoA"), CVAR_COSMETIC("BButton"), CVAR_COSMETIC("AButton"), CVAR_COSMETIC("StartButton"), - CVAR_COSMETIC("CUpButton"), CVAR_COSMETIC("CDownButton"), CVAR_COSMETIC("CLeftButton"), CVAR_COSMETIC("CRightButton"), CVAR_COSMETIC("Dpad"), CVAR_COSMETIC("Minimap"), - CVAR_COSMETIC("SmallKey"), CVAR_COSMETIC("Rupees"), CVAR_COSMETIC("Carrots"), CVAR_COSMETIC("Timers"), CVAR_COSMETIC("ArcheryScore"), CVAR_COSMETIC("TitleCard.Map"), CVAR_COSMETIC("TitleCard.Boss"), CVAR_COSMETIC("IGT") + CVAR_COSMETIC("HUD.Hearts"), CVAR_COSMETIC("HUD.HeartsCount"), CVAR_COSMETIC("HUD.MagicBar"), CVAR_COSMETIC("HUD.VisualSoA"), CVAR_COSMETIC("HUD.BButton"), CVAR_COSMETIC("HUD.AButton"), CVAR_COSMETIC("HUD.StartButton"), + CVAR_COSMETIC("HUD.CUpButton"), CVAR_COSMETIC("HUD.CDownButton"), CVAR_COSMETIC("HUD.CLeftButton"), CVAR_COSMETIC("HUD.CRightButton"), CVAR_COSMETIC("HUD.Dpad"), CVAR_COSMETIC("HUD.Minimap"), + CVAR_COSMETIC("HUD.SmallKey"), CVAR_COSMETIC("HUD.Rupees"), CVAR_COSMETIC("HUD.Carrots"), CVAR_COSMETIC("HUD.Timers"), CVAR_COSMETIC("HUD.ArcheryScore"), CVAR_COSMETIC("HUD.TitleCard.Map"), CVAR_COSMETIC("HUD.TitleCard.Boss"), CVAR_COSMETIC("HUD.IGT") }; -static const char* MarginCvarNonAnchor[]{ CVAR_COSMETIC("Carrots"), CVAR_COSMETIC("Timers"), CVAR_COSMETIC("ArcheryScore"), CVAR_COSMETIC("TitleCard.Map"),CVAR_COSMETIC("TitleCard.Boss") }; +static const char* MarginCvarNonAnchor[]{ CVAR_COSMETIC("HUD.Carrots"), CVAR_COSMETIC("HUD.Timers"), CVAR_COSMETIC("HUD.ArcheryScore"), CVAR_COSMETIC("HUD.TitleCard.Map"),CVAR_COSMETIC("HUD.TitleCard.Boss") }; ImVec4 GetRandomValue(int MaximumPossible){ ImVec4 NewColor; @@ -1205,10 +1206,10 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); Table_InitHeader(); - UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); - UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0); - UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0); - UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", CVAR_COSMETIC("HUD.Margin.T"), (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", CVAR_COSMETIC("HUD.Margin.L"), -25, ImGui::GetWindowViewport()->Size.x, "", 0); + UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", CVAR_COSMETIC("HUD.Margin.R"), (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", CVAR_COSMETIC("HUD.Margin.B"), (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); SetMarginAll("All margins on",true); UIWidgets::Tooltip("Set most of the elements to use margins\nSome elements with default position will not be affected\nElements without Anchor or Hidden will not be turned on"); ImGui::SameLine(); @@ -1224,11 +1225,11 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableHeartsCounts", 1, FlagsTable)) { ImGui::TableSetupColumn("Hearts counts settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Hearts counts", CVAR_COSMETIC("Hearts")); - DrawPositionsRadioBoxes(CVAR_COSMETIC("HeartsCount")); - DrawPositionSlider(CVAR_COSMETIC("HeartsCount"),-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x); - DrawScaleSlider(CVAR_COSMETIC("HeartsCount"),0.7f); - UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", CVAR_COSMETIC("Hearts.LineLength"), 0, 20, "", 10); + DrawUseMarginsSlider("Hearts counts", CVAR_COSMETIC("HUD.Hearts")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.HeartsCount")); + DrawPositionSlider(CVAR_COSMETIC("HUD.HeartsCount"),-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x); + DrawScaleSlider(CVAR_COSMETIC("HUD.HeartsCount"),0.7f); + UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", CVAR_COSMETIC("HUD.Hearts.LineLength"), 0, 20, "", 10); UIWidgets::Tooltip("This will set the length of a row of hearts. Set to 0 for unlimited length."); ImGui::NewLine(); ImGui::EndTable(); @@ -1238,12 +1239,12 @@ void Draw_Placements(){ if (ImGui::BeginTable("tablemmpos", 1, FlagsTable)) { ImGui::TableSetupColumn("Magic meter settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Magic meter", CVAR_COSMETIC("MagicBar")); - DrawPositionsRadioBoxes(CVAR_COSMETIC("MagicBar")); - UIWidgets::EnhancementRadioButton("Anchor to life bar", CVAR_COSMETIC("MagicBar.PosType"), 5); + DrawUseMarginsSlider("Magic meter", CVAR_COSMETIC("HUD.MagicBar")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.MagicBar")); + UIWidgets::EnhancementRadioButton("Anchor to life bar", CVAR_COSMETIC("HUD.MagicBar.PosType"), 5); UIWidgets::Tooltip("This will make your elements follow the bottom of the life meter"); - DrawPositionSlider(CVAR_COSMETIC("MagicBar"), 0, ImGui::GetWindowViewport()->Size.y/2, -5, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider(CVAR_COSMETIC("MagicBar"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.MagicBar"), 0, ImGui::GetWindowViewport()->Size.y/2, -5, ImGui::GetWindowViewport()->Size.x/2); + DrawScaleSlider(CVAR_COSMETIC("HUD.MagicBar"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } @@ -1252,76 +1253,76 @@ void Draw_Placements(){ if (ImGui::BeginTable("tabledvisualstoneofagony", 1, FlagsTable)) { ImGui::TableSetupColumn("Visual stone of agony settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("Visual stone of agony", CVAR_COSMETIC("VisualSoA")); - DrawPositionsRadioBoxes(CVAR_COSMETIC("VisualSoA")); + DrawUseMarginsSlider("Visual stone of agony", CVAR_COSMETIC("HUD.VisualSoA")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.VisualSoA")); s16 Min_X_VSOA = 0; s16 Max_X_VSOA = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"),0) == 2){ + if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"),0) == 2){ Max_X_VSOA = 290; - } else if(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"),0) == 4){ + } else if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"),0) == 4){ Min_X_VSOA = (ImGui::GetWindowViewport()->Size.x/2)*-1; } - DrawPositionSlider(CVAR_COSMETIC("VisualSoA"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_VSOA, Max_X_VSOA); - DrawScaleSlider(CVAR_COSMETIC("VisualSoA"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.VisualSoA"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_VSOA, Max_X_VSOA); + DrawScaleSlider(CVAR_COSMETIC("HUD.VisualSoA"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", CVAR_COSMETIC("BButton"), 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", CVAR_COSMETIC("AButton"), -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", CVAR_COSMETIC("StartButton"), 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); - C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", CVAR_COSMETIC("CUpButton"), CVAR_COSMETIC("CUpButton.PosType"), 0.5f); - C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", CVAR_COSMETIC("CDownButton"), CVAR_COSMETIC("CDownButton.PosType"), 0.87f); - C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", CVAR_COSMETIC("CLeftButton"), CVAR_COSMETIC("CLeftButton.PosType"), 0.87f); - C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", CVAR_COSMETIC("CRightButton"), CVAR_COSMETIC("CRightButton.PosType"), 0.87f); - if (CVarGetInteger("gDpadEquips",0) && ImGui::CollapsingHeader("DPad items position")) { + Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", CVAR_COSMETIC("HUD.BButton"), 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", CVAR_COSMETIC("HUD.AButton"), -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); + Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", CVAR_COSMETIC("HUD.StartButton"), 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); + C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", CVAR_COSMETIC("HUD.CUpButton"), CVAR_COSMETIC("HUD.CUpButton.PosType"), 0.5f); + C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", CVAR_COSMETIC("HUD.CDownButton"), CVAR_COSMETIC("HUD.CDownButton.PosType"), 0.87f); + C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", CVAR_COSMETIC("HUD.CLeftButton"), CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0.87f); + C_Button_Dropdown("C Button Right position", "tablecrbtn", "C Button Right settings", "C Button Right", CVAR_COSMETIC("HUD.CRightButton"), CVAR_COSMETIC("HUD.CRightButton.PosType"), 0.87f); + if (CVarGetInteger(CVAR_SETTING("DpadEquips"),0) && ImGui::CollapsingHeader("DPad items position")) { if (ImGui::BeginTable("tabledpaditems", 1, FlagsTable)) { ImGui::TableSetupColumn("DPad items settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - DrawUseMarginsSlider("DPad items", CVAR_COSMETIC("Dpad")); - DrawPositionsRadioBoxes(CVAR_COSMETIC("Dpad")); + DrawUseMarginsSlider("DPad items", CVAR_COSMETIC("HUD.Dpad")); + DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.Dpad")); s16 Min_X_Dpad = 0; s16 Max_X_Dpad = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger("gDPadPosType",0) == 2){ + if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"),0) == 2){ Max_X_Dpad = 290; - } else if(CVarGetInteger("gDPadPosType",0) == 4){ + } else if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"),0) == 4){ Min_X_Dpad = (ImGui::GetWindowViewport()->Size.x/2)*-1; } - DrawPositionSlider(CVAR_COSMETIC("Dpad"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_Dpad, Max_X_Dpad); - DrawScaleSlider(CVAR_COSMETIC("Dpad"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.Dpad"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_Dpad, Max_X_Dpad); + DrawScaleSlider(CVAR_COSMETIC("HUD.Dpad"),1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", CVAR_COSMETIC("Minimap"), (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", CVAR_COSMETIC("SmallKey"), 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", CVAR_COSMETIC("Rupees"), -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", CVAR_COSMETIC("Carrots"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); - Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", CVAR_COSMETIC("Timers"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", CVAR_COSMETIC("ArcheryScore"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", CVAR_COSMETIC("TitleCard.Map"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", CVAR_COSMETIC("TitleCard.Boss"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", CVAR_COSMETIC("IGT"), 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); + Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", CVAR_COSMETIC("HUD.Minimap"), (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", CVAR_COSMETIC("HUD.SmallKey"), 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", CVAR_COSMETIC("HUD.Rupees"), -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); + Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", CVAR_COSMETIC("HUD.Carrots"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); + Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", CVAR_COSMETIC("HUD.Timers"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", CVAR_COSMETIC("HUD.ArcheryScore"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); + Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", CVAR_COSMETIC("HUD.TitleCard.Map"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", CVAR_COSMETIC("HUD.TitleCard.Boss"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); + Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", CVAR_COSMETIC("HUD.IGT"), 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); if (ImGui::CollapsingHeader("Enemy Health Bar position")) { if (ImGui::BeginTable("enemyhealthbar", 1, FlagsTable)) { ImGui::TableSetupColumn("Enemy Health Bar settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); - std::string posTypeCVar = CVAR_COSMETIC("HUD.EnemyHealthBarPosType"); + std::string posTypeCVar = CVAR_COSMETIC("HUD.EnemyHealthBar.PosType"); UIWidgets::EnhancementRadioButton("Anchor to Enemy", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_ACTOR); UIWidgets::Tooltip("This will use enemy on screen position"); UIWidgets::EnhancementRadioButton("Anchor to the top", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_TOP); UIWidgets::Tooltip("This will make your elements follow the top edge of your game window"); UIWidgets::EnhancementRadioButton("Anchor to the bottom", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_BOTTOM); UIWidgets::Tooltip("This will make your elements follow the bottom edge of your game window"); - DrawPositionSlider(CVAR_COSMETIC("HUD.EnemyHealthBar"), -SCREEN_HEIGHT, SCREEN_HEIGHT, -ImGui::GetWindowViewport()->Size.x / 2, ImGui::GetWindowViewport()->Size.x / 2); - if (UIWidgets::EnhancementSliderInt("Health Bar Width: %d", "##EnemyHealthBarWidth", CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value"), 32, 128, "", 64)) { - CVarSetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed"), 1); + DrawPositionSlider(CVAR_COSMETIC("HUD.EnemyHealthBar."), -SCREEN_HEIGHT, SCREEN_HEIGHT, -ImGui::GetWindowViewport()->Size.x / 2, ImGui::GetWindowViewport()->Size.x / 2); + if (UIWidgets::EnhancementSliderInt("Health Bar Width: %d", "##EnemyHealthBarWidth", CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Value"), 32, 128, "", 64)) { + CVarSetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Changed"), 1); } UIWidgets::Tooltip("This will change the width of the health bar"); ImGui::SameLine(); if (ImGui::Button("Reset##EnemyHealthBarWidth")) { - CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value")); - CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed")); + CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Value")); + CVarClear(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Changed")); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::NewLine(); @@ -1346,8 +1347,8 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { } void DrawSillyTab() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - if (CVarGetInteger("gLetItSnow", 0)) { - if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + if (UIWidgets::EnhancementCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"))) { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } @@ -1380,7 +1381,7 @@ void DrawSillyTab() { Reset_Option_Single("Reset##BunnyHood_EarSpread", CVAR_COSMETIC("BunnyHood.EarSpread")); UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength"), 0.0f, 1000.0f, "", 0.0f, false); Reset_Option_Single("Reset##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength")); - UIWidgets::EnhancementCheckbox("Unfix Goron Spin", "gUnfixGoronSpin"); + UIWidgets::EnhancementCheckbox("Unfix Goron Spin", CVAR_COSMETIC("UnfixGoronSpin")); UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", CVAR_COSMETIC("Fairies.Size"), 0.25f, 5.0f, "", 1.0f, false); Reset_Option_Single("Reset##Fairies_Size", CVAR_COSMETIC("Fairies.Size")); UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", CVAR_COSMETIC("N64Logo.SpinSpeed"), 0.25f, 5.0f, "", 1.0f, false); diff --git a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp index 310517299..f31eedd2c 100644 --- a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp +++ b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp @@ -223,7 +223,7 @@ void PatchMirroredSoldOutGI() { G_TX_NOMIRROR | G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD), }; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { if (mirroredSoldOutVtx == nullptr) { // Copy the original vertices that we want to modify (4 at the beginning of the resource) mirroredSoldOutVtx = (Vtx*)malloc(sizeof(Vtx) * 4); @@ -270,7 +270,7 @@ void PatchMirroredSunSongEtching() { G_TX_NOMIRROR | G_TX_CLAMP, 7, 5, G_TX_NOLOD, G_TX_NOLOD) }; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { if (mirroredSunSongVtx == nullptr) { // Copy the original vertices that we want to modify (4 at the beginning of the resource) mirroredSunSongVtx = (Vtx*)malloc(sizeof(Vtx) * 4); diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index e2b45a419..3e4d271a8 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "soh/OTRGlobals.h" extern "C" { #include @@ -887,7 +888,7 @@ std::vector GetActorsWithDescriptionContainingString(std::string s) { } void ActorViewer_AddTagForActor(Actor* actor) { - int val = CVarGetInteger("gDebugActorViewerNameTags", ACTORVIEWER_NAMETAGS_NONE); + int val = CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), ACTORVIEWER_NAMETAGS_NONE); auto entry = ActorDB::Instance->RetrieveEntry(actor->id); std::string tag; @@ -1129,10 +1130,10 @@ void ActorViewerWindow::DrawElement() { newActor.params = 0; } - UIWidgets::EnhancementCheckbox("Advanced mode", "gActorViewerAdvancedParams"); + UIWidgets::EnhancementCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams")); UIWidgets::InsertHelpHoverText("Changes the actor specific param menus with a direct input"); - if (CVarGetInteger("gActorViewerAdvancedParams", 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) { ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one); } else if (std::find(noParamsActors.begin(), noParamsActors.end(), newActor.id) == noParamsActors.end()) { CreateActorSpecificData(); @@ -1214,7 +1215,7 @@ void ActorViewerWindow::DrawElement() { UIWidgets::Spacer(0); ImGui::Text("Actor Name Tags"); - if (UIWidgets::EnhancementCombobox("gDebugActorViewerNameTags", nameTagOptions, ACTORVIEWER_NAMETAGS_NONE)) { + if (UIWidgets::EnhancementCombobox(CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions, ACTORVIEWER_NAMETAGS_NONE)) { NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG); ActorViewer_AddTagForAllActors(); } diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index 135dcb0f0..159e27128 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "soh/OTRGlobals.h" extern "C" { #include @@ -57,17 +58,17 @@ void ColViewerWindow::DrawElement() { ImGui::End(); return; } - UIWidgets::EnhancementCheckbox("Enabled", "gColViewerEnabled"); + UIWidgets::EnhancementCheckbox("Enabled", CVAR_DEVELOPER_TOOLS("ColViewer.Enabled")); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Scene", "gColViewerScene", ColRenderSettingNames, COLVIEW_DISABLED); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Bg Actors", "gColViewerBgActors", ColRenderSettingNames, COLVIEW_DISABLED); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Col Check", "gColViewerColCheck", ColRenderSettingNames, COLVIEW_DISABLED); - UIWidgets::LabeledRightAlignedEnhancementCombobox("Waterbox", "gColViewerWaterbox", ColRenderSettingNames, COLVIEW_DISABLED); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Scene", CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), ColRenderSettingNames, COLVIEW_DISABLED); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Bg Actors", CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), ColRenderSettingNames, COLVIEW_DISABLED); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Col Check", CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), ColRenderSettingNames, COLVIEW_DISABLED); + UIWidgets::LabeledRightAlignedEnhancementCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, COLVIEW_DISABLED); - UIWidgets::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); + UIWidgets::EnhancementCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal")); UIWidgets::InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " "with the scene geometry, but can cause other artifacts."); - UIWidgets::EnhancementCheckbox("Shaded", "gColViewerShaded"); + UIWidgets::EnhancementCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded")); UIWidgets::InsertHelpHoverText("Applies the scene's shading to the collision display."); // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() @@ -75,20 +76,20 @@ void ColViewerWindow::DrawElement() { if (ImGui::TreeNode("Colors")) { UIWidgets::InsertHelpHoverText(colorHelpText); - UIWidgets::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); - UIWidgets::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), + UIWidgets::EnhancementColor("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), scene_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), hookshot_col, ImVec4(128, 128, 255, 255), false); - UIWidgets::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); - UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", + UIWidgets::EnhancementColor("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), entrance_col, ImVec4(0, 255, 0, 255), false); + UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), specialSurface_col, ImVec4(192, 255, 192, 255), false); - UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", + UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), interactable_col, ImVec4(192, 0, 192, 255), false); - UIWidgets::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); - UIWidgets::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); - UIWidgets::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); - UIWidgets::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); - UIWidgets::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); - UIWidgets::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), slope_col, ImVec4(255, 255, 128, 255), false); + UIWidgets::EnhancementColor("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), void_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), oc_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), ac_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), at_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), waterbox_col, ImVec4(0, 0, 255, 255), false); ImGui::TreePop(); } else { @@ -308,7 +309,7 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { alpha = 0xFF; } - if (CVarGetInteger("gColViewerDecal", 0) != 0) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), 0) != 0) { rm |= ZMODE_DEC; } else if (setting == ColRenderSetting::Transparent) { rm |= ZMODE_XLU; @@ -320,7 +321,7 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { gfx.push_back(gsDPSetCycleType(G_CYC_1CYCLE)); gfx.push_back(gsDPSetRenderMode(rm | blc1, rm | blc2)); - if (CVarGetInteger("gColViewerShaded", 0) != 0) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"), 0) != 0) { gfx.push_back(gsDPSetCombineMode(G_CC_MODULATERGB_PRIM_ENVA, G_CC_MODULATERGB_PRIM_ENVA)); gfx.push_back(gsSPLoadGeometryMode(G_CULL_BACK | G_ZBUFFER | G_LIGHTING)); } else { @@ -333,16 +334,13 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { // Draws a dynapoly structure (scenes or Bg Actors) void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { - uint32_t colorR = CVarGetInteger("gColViewerColorNormalR", 255); - uint32_t colorG = CVarGetInteger("gColViewerColorNormalG", 255); - uint32_t colorB = CVarGetInteger("gColViewerColorNormalB", 255); - uint32_t colorA = 255; + Color_RGBA8 color = {255, 255, 255, 255}; - uint32_t lastColorR = colorR; - uint32_t lastColorG = colorG; - uint32_t lastColorB = colorB; + uint32_t lastColorR = color.r; + uint32_t lastColorG = color.g; + uint32_t lastColorB = color.b; - dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA)); + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); // This keeps track of if we have processed a poly, but not drawn it yet so we can batch them. // This saves several hundred commands in larger scenes @@ -352,49 +350,35 @@ void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { CollisionPoly* poly = &col->polyList[i]; if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) { - colorR = CVarGetInteger("gColViewerColorHookshotR", 128); - colorG = CVarGetInteger("gColViewerColorHookshotG", 128); - colorB = CVarGetInteger("gColViewerColorHookshotB", 255); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }); } else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) { - colorR = CVarGetInteger("gColViewerColorInteractableR", 192); - colorG = CVarGetInteger("gColViewerColorInteractableG", 0); - colorB = CVarGetInteger("gColViewerColorInteractableB", 192); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), {192, 0, 192, 255}); } else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) { - colorR = CVarGetInteger("gColViewerColorVoidR", 255); - colorG = CVarGetInteger("gColViewerColorVoidG", 0); - colorB = CVarGetInteger("gColViewerColorVoidB", 0); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }); } else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) || func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x05) { - colorR = CVarGetInteger("gColViewerColorEntranceR", 0); - colorG = CVarGetInteger("gColViewerColorEntranceG", 255); - colorB = CVarGetInteger("gColViewerColorEntranceB", 0); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }); } else if (func_80041D4C(&gPlayState->colCtx, poly, bgId) != 0 || SurfaceType_IsWallDamage(&gPlayState->colCtx, poly, bgId)) { - colorR = CVarGetInteger("gColViewerColorSpecialSurfaceR", 192); - colorG = CVarGetInteger("gColViewerColorSpecialSurfaceG", 255); - colorB = CVarGetInteger("gColViewerColorSpecialSurfaceB", 192); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }); } else if (SurfaceType_GetSlope(&gPlayState->colCtx, poly, bgId) == 0x01) { - colorR = CVarGetInteger("gColViewerColorSlopeR", 255); - colorG = CVarGetInteger("gColViewerColorSlopeG", 255); - colorB = CVarGetInteger("gColViewerColorSlopeB", 128); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }); } else { - colorR = CVarGetInteger("gColViewerColorNormalR", 255); - colorG = CVarGetInteger("gColViewerColorNormalG", 255); - colorB = CVarGetInteger("gColViewerColorNormalB", 255); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }); } - if (colorR != lastColorR || colorG != lastColorG || colorB != lastColorB) { + if (color.r != lastColorR || color.g != lastColorG || color.b != lastColorB) { // Color changed, flush previous poly if (previousPoly) { dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0)); dl.push_back(gsSP1Triangle(0, 1, 2, 0)); previousPoly = false; } - dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA)); + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } - lastColorR = colorR; - lastColorG = colorG; - lastColorB = colorB; + lastColorR = color.r; + lastColorG = color.g; + lastColorB = color.b; Vec3s* va = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIA)]; Vec3s* vb = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIB)]; @@ -428,9 +412,9 @@ void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { // Draws the scene void DrawSceneCollision() { - ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger("gColViewerScene", COLVIEW_DISABLED); + ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED); - if (showSceneColSetting == ColRenderSetting::Disabled || !CVarGetInteger("gColViewerEnabled", 0)) { + if (showSceneColSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { return; } @@ -443,8 +427,8 @@ void DrawSceneCollision() { // Draws all Bg Actors void DrawBgActorCollision() { - ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger("gColViewerBgActors", COLVIEW_DISABLED); - if (showBgActorSetting == ColRenderSetting::Disabled || !CVarGetInteger("gColViewerEnabled", 0)) { + ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED); + if (showBgActorSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { return; } @@ -568,8 +552,8 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { // Draws all Col Check objects void DrawColCheckCollision() { - ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger("gColViewerColCheck", COLVIEW_DISABLED); - if (showColCheckSetting == ColRenderSetting::Disabled || !CVarGetInteger("gColViewerEnabled", 0)) { + ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED); + if (showColCheckSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { return; } @@ -578,15 +562,14 @@ void DrawColCheckCollision() { dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); CollisionCheckContext& col = gPlayState->colChkCtx; - - dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorOCR", 255), CVarGetInteger("gColViewerColorOCG", 255), - CVarGetInteger("gColViewerColorOCB", 255), 255)); + Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }); + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); DrawColCheckList(dl, col.colOC, col.colOCCount); - dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorACR", 0), CVarGetInteger("gColViewerColorACG", 0), - CVarGetInteger("gColViewerColorACB", 255), 255)); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }); + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); DrawColCheckList(dl, col.colAC, col.colACCount); - dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorATR", 255), CVarGetInteger("gColViewerColorATG", 0), - CVarGetInteger("gColViewerColorATB", 0), 255)); + color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 0, 0, 255, 255 }); + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); DrawColCheckList(dl, col.colAT, col.colATCount); } @@ -621,8 +604,8 @@ extern "C" f32 zdWaterBoxMinY; // Draws all waterboxes void DrawWaterboxList() { - ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger("gColViewerWaterbox", COLVIEW_DISABLED); - if (showWaterboxSetting == ColRenderSetting::Disabled || !CVarGetInteger("gColViewerEnabled", 0)) { + ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED); + if (showWaterboxSetting == ColRenderSetting::Disabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { return; } @@ -630,9 +613,9 @@ void DrawWaterboxList() { InitGfx(dl, showWaterboxSetting); dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); - dl.push_back(gsDPSetPrimColor(0, 0, CVarGetInteger("gColViewerColorWaterboxR", 0), - CVarGetInteger("gColViewerColorWaterboxG", 0), - CVarGetInteger("gColViewerColorWaterboxB", 255), 255)); + Color_RGBA8 color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }); + + dl.push_back(gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); CollisionHeader* col = gPlayState->colCtx.colHeader; for (int32_t waterboxIndex = 0; waterboxIndex < col->numWaterBoxes; waterboxIndex++) { @@ -693,7 +676,7 @@ extern "C" void DrawColViewer() { OPEN_DISPS(gPlayState->state.gfxCtx); - uint8_t mirroredWorld = CVarGetInteger("gMirroredWorld", 0); + uint8_t mirroredWorld = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0); // Col viewer needs inverted culling in mirror mode for both OPA and XLU buffers if (mirroredWorld) { gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index f7b85251c..216e0e12f 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1705,7 +1705,7 @@ void DrawPlayerTab() { ImGui::SameLine(); ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL); - if (CVarGetInteger("gDpadEquips", 0)) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0)) { ImGui::NewLine(); ImGui::Text("Current D-pad Equips"); ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); // Two spaces at the end for aligning, not elegant but it's working diff --git a/soh/soh/Enhancements/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp index 14a571dac..97bf85164 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.cpp +++ b/soh/soh/Enhancements/debugger/valueViewer.cpp @@ -1,5 +1,6 @@ #include "valueViewer.h" #include "../../UIWidgets.hpp" +#include "soh/OTRGlobals.h" extern "C" { #include @@ -107,7 +108,7 @@ void ValueViewerWindow::DrawElement() { return; } - UIWidgets::PaddedEnhancementCheckbox("Enable Printing", "gValueViewer.EnablePrinting"); + UIWidgets::PaddedEnhancementCheckbox("Enable Printing", CVAR_DEVELOPER_TOOLS("ValueViewerEnablePrinting")); ImGui::BeginGroup(); static int selectedElement = -1; @@ -187,7 +188,7 @@ void ValueViewerWindow::DrawElement() { } ImGui::BeginGroup(); - if (CVarGetInteger("gValueViewer.EnablePrinting", 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ValueViewerEnablePrinting"), 0)) { ImGui::Checkbox(("Print##" + std::string(element.name)).c_str(), &element.isPrinted); if (element.isPrinted) { char* prefix = (char*)element.prefix.c_str(); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index cf098bda3..5e61f704d 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -353,19 +353,19 @@ void GameInteractor::RawAction::SetTimeOfDay(uint32_t time) { } void GameInteractor::RawAction::SetCollisionViewer(bool active) { - CVarSetInteger("gColViewerEnabled", active); - CVarSetInteger("gColViewerDecal", active); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), active); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), active); if (active) { - CVarSetInteger("gColViewerScene", COLVIEW_TRANSPARENT); - CVarSetInteger("gColViewerBgActors", COLVIEW_TRANSPARENT); - CVarSetInteger("gColViewerColCheck", COLVIEW_TRANSPARENT); - CVarSetInteger("gColViewerWaterbox", COLVIEW_TRANSPARENT); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_TRANSPARENT); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_TRANSPARENT); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_TRANSPARENT); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_TRANSPARENT); } else { - CVarSetInteger("gColViewerScene", COLVIEW_DISABLED); - CVarSetInteger("gColViewerBgActors", COLVIEW_DISABLED); - CVarSetInteger("gColViewerColCheck", COLVIEW_DISABLED); - CVarSetInteger("gColViewerWaterbox", COLVIEW_DISABLED); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED); + CVarSetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED); } } diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index fa35edfb6..61eb88a6f 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -388,7 +388,7 @@ void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color } bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b) { - return CVarGetInteger("gGameplayStats.TimestampsReverse", 0) ? a.time > b.time : a.time < b.time; + return CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time; } const char* ResolveSceneID(int sceneID, int roomID){ @@ -443,13 +443,13 @@ void DrawGameplayStatsHeader() { } else { GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.sohStats.gameComplete ? COLOR_GREEN : COLOR_WHITE); } - if (CVarGetInteger("gGameplayStats.ShowAdditionalTimers", 0)) { // !Only display total game time + if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), 0)) { // !Only display total game time GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.sohStats.playTimer / 2), COLOR_GREY); GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.sohStats.pauseTimer / 3), COLOR_GREY); GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.sohStats.sceneTimer / 2), COLOR_LIGHT_BLUE); GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.sohStats.roomTimer / 2), COLOR_LIGHT_BLUE); } - if (gPlayState != NULL && CVarGetInteger("gGameplayStats.ShowDebugInfo", 0)) { // && display debug info + if (gPlayState != NULL && CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"), 0)) { // && display debug info GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW); GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex), COLOR_YELLOW); GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex), COLOR_YELLOW); @@ -567,13 +567,13 @@ void DrawGameplayStatsBreakdownTab() { for (int i = 0; i < gSaveContext.sohStats.tsIdx; i++) { std::string sceneName = ResolveSceneID(gSaveContext.sohStats.sceneTimestamps[i].scene, gSaveContext.sohStats.sceneTimestamps[i].room); std::string name; - if (CVarGetInteger("gGameplayStats.RoomBreakdown", 0) && gSaveContext.sohStats.sceneTimestamps[i].scene != SCENE_GROTTOS) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.sohStats.sceneTimestamps[i].scene != SCENE_GROTTOS) { name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.sohStats.sceneTimestamps[i].room); } else { name = sceneName; } strcpy(sceneTimestampDisplay[i].name, name.c_str()); - sceneTimestampDisplay[i].time = CVarGetInteger("gGameplayStats.RoomBreakdown", 0) ? + sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) ? gSaveContext.sohStats.sceneTimestamps[i].roomTime : gSaveContext.sohStats.sceneTimestamps[i].sceneTime; sceneTimestampDisplay[i].color = COLOR_GREY; sceneTimestampDisplay[i].isRoom = gSaveContext.sohStats.sceneTimestamps[i].isRoom; @@ -584,13 +584,13 @@ void DrawGameplayStatsBreakdownTab() { ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); for (int i = 0; i < gSaveContext.sohStats.tsIdx; i++) { TimestampInfo tsInfo = sceneTimestampDisplay[i]; - bool canShow = !tsInfo.isRoom || CVarGetInteger("gGameplayStats.RoomBreakdown", 0); + bool canShow = !tsInfo.isRoom || CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0); if (tsInfo.time > 0 && strnlen(tsInfo.name, 40) > 1 && canShow) { GameplayStatsRow(tsInfo.name, formatTimestampGameplayStat(tsInfo.time), tsInfo.color); } } std::string toPass; - if (CVarGetInteger("gGameplayStats.RoomBreakdown", 0) && gSaveContext.sohStats.sceneNum != SCENE_GROTTOS) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.sohStats.sceneNum != SCENE_GROTTOS) { toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.sohStats.sceneNum, gSaveContext.sohStats.roomNum), gSaveContext.sohStats.roomNum); } else { toPass = ResolveSceneID(gSaveContext.sohStats.sceneNum, gSaveContext.sohStats.roomNum); @@ -601,21 +601,21 @@ void DrawGameplayStatsBreakdownTab() { } void DrawGameplayStatsOptionsTab() { - UIWidgets::PaddedEnhancementCheckbox("Show in-game total timer", "gGameplayStats.ShowIngameTimer", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show in-game total timer", CVAR_ENHANCEMENT("GameplayStats.ShowIngameTimer"), true, false); UIWidgets::InsertHelpHoverText("Keep track of the timer as an in-game HUD element. The position of the timer can be changed in the Cosmetics Editor."); - UIWidgets::PaddedEnhancementCheckbox("Show latest timestamps on top", "gGameplayStats.TimestampsReverse", true, false); - UIWidgets::PaddedEnhancementCheckbox("Room Breakdown", "gGameplayStats.RoomBreakdown", true, false); + UIWidgets::PaddedEnhancementCheckbox("Show latest timestamps on top", CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Room Breakdown", CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), true, false); ImGui::SameLine(); UIWidgets::InsertHelpHoverText("Allows a more in-depth perspective of time spent in a certain map."); - UIWidgets::PaddedEnhancementCheckbox("RTA Timing on new files", "gGameplayStats.RTATiming", true, false); + UIWidgets::PaddedEnhancementCheckbox("RTA Timing on new files", CVAR_ENHANCEMENT("GameplayStats.RTATiming"), true, false); ImGui::SameLine(); UIWidgets::InsertHelpHoverText( "Timestamps are relative to starting timestamp rather than in game time, usually necessary for races/speedruns.\n\n" "Starting timestamp is on first non-c-up input after intro cutscene.\n\n" "NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT" ); - UIWidgets::PaddedEnhancementCheckbox("Show additional detail timers", "gGameplayStats.ShowAdditionalTimers", true, false); - UIWidgets::PaddedEnhancementCheckbox("Show Debug Info", "gGameplayStats.ShowDebugInfo"); + UIWidgets::PaddedEnhancementCheckbox("Show additional detail timers", CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Show Debug Info", CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo")); } void GameplayStatsWindow::DrawElement() { @@ -657,7 +657,7 @@ void InitStats(bool isDebug) { for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys); dungeon++) { gSaveContext.sohStats.dungeonKeys[dungeon] = isDebug ? 8 : 0; } - gSaveContext.sohStats.rtaTiming = CVarGetInteger("gGameplayStats.RTATiming", 0); + gSaveContext.sohStats.rtaTiming = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RTATiming"), 0); gSaveContext.sohStats.fileCreatedAt = 0; gSaveContext.sohStats.playTimer = 0; gSaveContext.sohStats.pauseTimer = 0; diff --git a/soh/soh/Enhancements/gameplaystats.h b/soh/soh/Enhancements/gameplaystats.h index 8772dd37f..528da33f9 100644 --- a/soh/soh/Enhancements/gameplaystats.h +++ b/soh/soh/Enhancements/gameplaystats.h @@ -12,7 +12,7 @@ (!gSaveContext.sohStats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.sohStats.fileCreatedAt) / 100)) :\ (gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_GANON])) :\ (gSaveContext.sohStats.playTimer / 2 + gSaveContext.sohStats.pauseTimer / 3)) -#define CURRENT_MODE_TIMER (CVarGetInteger("gGameplayStats.RoomBreakdown", 0) ?\ +#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) ?\ gSaveContext.sohStats.roomTimer :\ gSaveContext.sohStats.sceneTimer) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 8ddd59cef..9a3988e39 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -196,14 +196,14 @@ void RegisterUnrestrictedItems() { void RegisterFreezeTime() { GameInteractor::Instance->RegisterGameHook([]() { if (CVarGetInteger(CVAR_CHEAT("FreezeTime"), 0) != 0) { - if (CVarGetInteger("gPrevTime", -1) == -1) { - CVarSetInteger("gPrevTime", gSaveContext.dayTime); + if (CVarGetInteger(CVAR_GENERAL("PrevTime"), -1) == -1) { + CVarSetInteger(CVAR_GENERAL("PrevTime"), gSaveContext.dayTime); } - int32_t prevTime = CVarGetInteger("gPrevTime", gSaveContext.dayTime); + int32_t prevTime = CVarGetInteger(CVAR_GENERAL("PrevTime"), gSaveContext.dayTime); gSaveContext.dayTime = prevTime; } else { - CVarClear("gPrevTime"); + CVarClear(CVAR_GENERAL("PrevTime")); } }); } @@ -272,11 +272,11 @@ void RegisterOcarinaTimeTravel() { !nearbyOcarinaSpot && !nearbyFrogs) { if (IS_RANDO) { - CVarSetInteger("gSwitchTimeline", 1); + CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 1); } else if (!IS_RANDO && !nearbyDoorOfTime) { // This check is made for when Link is learning the Song Of Time in a vanilla save file that load a // Temple of Time scene where the only object present is the Door of Time - CVarSetInteger("gSwitchTimeline", 1); + CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 1); } ReloadSceneTogglingLinkAge(); } @@ -699,10 +699,10 @@ void UpdateMirrorModeState(int32_t sceneNum) { ((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror))) ) { nextMirroredWorld = true; - CVarSetInteger("gMirroredWorld", 1); + CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1); } else { nextMirroredWorld = false; - CVarClear("gMirroredWorld"); + CVarClear(CVAR_ENHANCEMENT("MirroredWorld")); } if (prevMirroredWorld != nextMirroredWorld) { diff --git a/soh/soh/Enhancements/nametag.cpp b/soh/soh/Enhancements/nametag.cpp index 0d4ce2a0c..2adc3fffb 100644 --- a/soh/soh/Enhancements/nametag.cpp +++ b/soh/soh/Enhancements/nametag.cpp @@ -91,7 +91,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) { // Set position, billboard effect, scale (with mirror mode), then center nametag Matrix_Translate(nameTag->actor->world.pos.x, posY, nameTag->actor->world.pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), -scale, 1.0f, MTXMODE_APPLY); + Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), -scale, 1.0f, MTXMODE_APPLY); Matrix_Translate(-(float)nameTag->width / 2, -nameTag->height, 0, MTXMODE_APPLY); Matrix_ToMtx(nameTag->mtx, (char*)__FILE__, __LINE__); diff --git a/soh/soh/Enhancements/presets.cpp b/soh/soh/Enhancements/presets.cpp index ea51502e3..57bfd689c 100644 --- a/soh/soh/Enhancements/presets.cpp +++ b/soh/soh/Enhancements/presets.cpp @@ -40,7 +40,7 @@ void applyPreset(std::vector entries) { } void DrawPresetSelector(PresetType presetTypeId) { - const std::string presetTypeCvar = "gPreset" + std::to_string(presetTypeId); + const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId); const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId); const uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0); const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 1392691df..aea4bb1fd 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -60,18 +60,18 @@ void applyPreset(std::vector entries); // TODO: Ideally everything below this point will come from one/many JSON files const std::vector enhancementsCvars = { - "gDpadPause", - "gDpadText", - "gDpadOcarina", - "gRStickOcarina", - "gDpadEquips", - "gPauseAnyCursor", + CVAR_SETTING("DPadOnPause"), + CVAR_SETTING("DpadInText"), + CVAR_SETTING("OcarinaControl.Dpad"), + CVAR_SETTING("OcarinaControl.RStick"), + CVAR_SETTING("DpadEquips"), + CVAR_SETTING("PauseAnyCursor"), CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), - "gNaviOnL", - "gInvertXAxis", - "gInvertYAxis", - "gRightStickAiming", - "gDisableAutoCenterViewFirstPerson", + CVAR_SETTING("NaviOnL"), + CVAR_SETTING("FreeLook.InvertXAxis"), + CVAR_SETTING("FreeLook.InvertYAxis"), + CVAR_SETTING("Controls.RightStickAim"), + CVAR_SETTING("DisableFirstPersonAutoCenterView"), CVAR_ENHANCEMENT("TextSpeed"), CVAR_ENHANCEMENT("MweepSpeed"), CVAR_ENHANCEMENT("ForgeTime"), @@ -152,7 +152,6 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("PauseLiveLinkRotation"), CVAR_ENHANCEMENT("PauseLiveLink"), CVAR_ENHANCEMENT("MinFrameCount"), - "gN64Mode", CVAR_ENHANCEMENT("NewDrops"), CVAR_ENHANCEMENT("DisableBlackBars"), CVAR_ENHANCEMENT("DynamicWalletIcon"), @@ -240,7 +239,7 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("RandomizedEnemySizes"), CVAR_ENHANCEMENT("RandomizedEnemies"), CVAR_ENHANCEMENT("MirroredWorldMode"), - "gMirroredWorld", + CVAR_ENHANCEMENT("MirroredWorld"), CVAR_ENHANCEMENT("HyperEnemies"), CVAR_ENHANCEMENT("HookshotableReticle"), CVAR_ENHANCEMENT("HideBunnyHood"), @@ -287,12 +286,12 @@ const std::vector cheatCvars = { CVAR_WINDOW("CollisionViewer"), CVAR_WINDOW("DLViewer"), CVAR_WINDOW("SaveEditor"), - "gEnableWalkModify", - "gWalkSpeedToggle", - "gWalkModifierOne", - "gWalkModifierTwo", - "gSwimModifierOne", - "gSwimModifierTwo", + CVAR_SETTING("WalkModifier.Enabled"), + CVAR_SETTING("WalkModifier.SpeedToggle"), + CVAR_SETTING("WalkModifier.Mapping1"), + CVAR_SETTING("WalkModifier.Mapping2"), + CVAR_SETTING("WalkModifier.SwimMapping1"), + CVAR_SETTING("WalkModifier.SwimMapping2"), CVAR_ENHANCEMENT("GoronPot"), CVAR_ENHANCEMENT("DampeWin"), CVAR_ENHANCEMENT("CustomizeShootingGallery"), @@ -317,7 +316,7 @@ const std::vector cheatCvars = { CVAR_CHEAT("EasyInputBuffer"), CVAR_CHEAT("NoRestrictItems"), CVAR_CHEAT("FreezeTime"), - "gPrevTime", + CVAR_GENERAL("PrevTime"), CVAR_CHEAT("DropsDontDie"), CVAR_CHEAT("FireproofDekuShield"), CVAR_CHEAT("ShieldTwoHanded"), @@ -329,19 +328,17 @@ const std::vector cheatCvars = { CVAR_CHEAT("EnableBetaQuest"), CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), CVAR_GENERAL("SwitchAge"), - "gSwitchTimeline", + CVAR_GENERAL("SwitchTimeline"), CVAR_CHEAT("NoRedeadFreeze"), CVAR_CHEAT("NoKeeseGuayTarget"), CVAR_CHEAT("BombTimerMultiplier"), CVAR_CHEAT("NoFishDespawn"), CVAR_CHEAT("NoBugsDespawn"), - "gWalkModifierDoesntChangeJump", + CVAR_SETTING("WalkModifier.DoesntChangeJump"), CVAR_STATS_WINDOW_OPEN, CVAR_CHEAT("SaveStatesEnabled"), CVAR_CHEAT("SaveStatePromise"), CVAR_DEVELOPER_TOOLS("RegEditEnabled"), - "gPreset0", - "gPreset1", CVAR_CHEAT("DekuStick"), CVAR_DEVELOPER_TOOLS("DebugWarpScreenTranslation"), CVAR_DEVELOPER_TOOLS("DebugSaveFileMode"), @@ -493,17 +490,17 @@ const std::vector randomizerCvars = { const std::vector vanillaPlusPresetEntries = { // D-pad Support in text and file select - PRESET_ENTRY_S32("gDpadText", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadInText"), 1), // Play Ocarina with D-pad - PRESET_ENTRY_S32("gDpadOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.Dpad"), 1), // Play Ocarina with Right Stick - PRESET_ENTRY_S32("gRStickOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.RStick"), 1), // D-pad as Equip Items - PRESET_ENTRY_S32("gDpadEquips", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadEquips"), 1), // Prevent Dropped Ocarina Inputs PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming - PRESET_ENTRY_S32("gRightStickAiming", 1), + PRESET_ENTRY_S32(CVAR_SETTING("Controls.RightStickAim"), 1), // Text Speed (1 to 5) PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), @@ -564,17 +561,17 @@ const std::vector vanillaPlusPresetEntries = { const std::vector enhancedPresetEntries = { // D-pad Support in text and file select - PRESET_ENTRY_S32("gDpadText", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadInText"), 1), // Play Ocarina with D-pad - PRESET_ENTRY_S32("gDpadOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.Dpad"), 1), // Play Ocarina with Right Stick - PRESET_ENTRY_S32("gRStickOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.RStick"), 1), // D-pad as Equip Items - PRESET_ENTRY_S32("gDpadEquips", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadEquips"), 1), // Prevent Dropped Ocarina Inputs PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming - PRESET_ENTRY_S32("gRightStickAiming", 1), + PRESET_ENTRY_S32(CVAR_SETTING("Controls.RightStickAim"), 1), // Text Speed (1 to 5) PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), @@ -693,17 +690,17 @@ const std::vector enhancedPresetEntries = { const std::vector randomizerPresetEntries = { // D-pad Support in text and file select - PRESET_ENTRY_S32("gDpadText", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadInText"), 1), // Play Ocarina with D-pad - PRESET_ENTRY_S32("gDpadOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.Dpad"), 1), // Play Ocarina with Right Stick - PRESET_ENTRY_S32("gRStickOcarina", 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.RStick"), 1), // D-pad as Equip Items - PRESET_ENTRY_S32("gDpadEquips", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadEquips"), 1), // Prevent Dropped Ocarina Inputs PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), // Right Stick Aiming - PRESET_ENTRY_S32("gRightStickAiming", 1), + PRESET_ENTRY_S32(CVAR_SETTING("Controls.RightStickAim"), 1), // Text Speed (1 to 5) PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5), @@ -867,10 +864,10 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastChests"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastDrops"), 1), - PRESET_ENTRY_S32("gDpadText", 1), - PRESET_ENTRY_S32("gDpadOcarina", 1), - PRESET_ENTRY_S32("gRStickOcarina", 1), - PRESET_ENTRY_S32("gDpadEquips", 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadInText"), 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.Dpad"), 1), + PRESET_ENTRY_S32(CVAR_SETTING("OcarinaControl.RStick"), 1), + PRESET_ENTRY_S32(CVAR_SETTING("DpadEquips"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MarketSneak"), 1), @@ -886,7 +883,7 @@ const std::vector spockRacePresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), - PRESET_ENTRY_S32("gPauseAnyCursor", 1), + PRESET_ENTRY_S32(CVAR_SETTING("PauseAnyCursor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MaskSelect"), 1), @@ -969,7 +966,6 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 1), - PRESET_ENTRY_S32("gHideBuildInfo", 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1), @@ -979,7 +975,7 @@ const std::vector spockRaceNoLogicPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MweepSpeed"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoForcedNavi"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), - PRESET_ENTRY_S32("gPauseAnyCursor", 1), + PRESET_ENTRY_S32(CVAR_SETTING("PauseAnyCursor"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("30GSHint"), 1), diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index e53caeef2..6f342535b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "soh/OTRGlobals.h" void RandoMain::GenerateRando(std::unordered_map cvarSettings, std::set excludedLocations, std::set enabledTricks, std::string seedString) { @@ -16,14 +17,14 @@ void RandoMain::GenerateRando(std::unordered_map cvarS LocationTable_Init(); // std::string settingsFileName = "./randomizer/latest_settings.json"; - // CVarSetString("gLoadedPreset", settingsFileName.c_str()); + // CVarSetString(CVAR_RANDOMIZER_SETTING("LoadedPreset"), settingsFileName.c_str()); std::string fileName = Ship::Context::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, enabledTricks, seedString).c_str()); - CVarSetString("gSpoilerLog", fileName.c_str()); + CVarSetString(CVAR_GENERAL("SpoilerLog"), fileName.c_str()); CVarSave(); CVarLoad(); - CVarSetInteger("gNewSeedGenerated", 1); + CVarSetInteger(CVAR_GENERAL("NewSeedGenerated"), 1); } std::array* RandoMain::GetFullItemTable() { diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 187e50eab..f5c522ddc 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2827,7 +2827,7 @@ RandomizerCheck Randomizer::GetCheckFromRandomizerInf(RandomizerInf randomizerIn std::thread randoThread; void GenerateRandomizerImgui(std::string seed = "") { - CVarSetInteger("gRandoGenerating", 1); + CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1); CVarSave(); std::unordered_map cvarSettings; @@ -2945,7 +2945,7 @@ void GenerateRandomizerImgui(std::string seed = "") { // RANDOTODO implement chest minigame shuffle with keysanity cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME] = false; - cvarSettings[RSK_LANGUAGE] = CVarGetInteger("gLanguages", 0); + cvarSettings[RSK_LANGUAGE] = CVarGetInteger(CVAR_SETTING("Languages"), 0); cvarSettings[RSK_CUCCO_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7); cvarSettings[RSK_BIG_POE_COUNT] = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 10); @@ -3052,7 +3052,7 @@ void GenerateRandomizerImgui(std::string seed = "") { RandoMain::GenerateRando(cvarSettings, excludedLocations, enabledTricks, seed); - CVarSetInteger("gRandoGenerating", 0); + CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 0); CVarSave(); CVarLoad(); @@ -3060,7 +3060,7 @@ void GenerateRandomizerImgui(std::string seed = "") { } bool GenerateRandomizer(std::string seed /*= ""*/) { - if (CVarGetInteger("gRandoGenerating", 0) == 0) { + if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) == 0) { randoThread = std::thread(&GenerateRandomizerImgui, seed); return true; } @@ -3144,7 +3144,7 @@ void RandomizerSettingsWindow::DrawElement() { return; } - bool disableEditingRandoSettings = CVarGetInteger("gRandoGenerating", 0) || CVarGetInteger("gOnFileSelectNameEntry", 0); + bool disableEditingRandoSettings = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0); if (disableEditingRandoSettings) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } @@ -3182,12 +3182,12 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::Spacer(0); if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { - std::string spoilerfilepath = CVarGetString("gSpoilerLog", ""); + std::string spoilerfilepath = CVarGetString(CVAR_GENERAL("SpoilerLog"), ""); ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str()); } // RANDOTODO settings presets - // std::string presetfilepath = CVarGetString("gLoadedPreset", ""); + // std::string presetfilepath = CVarGetString(CVAR_RANDOMIZER_SETTING("LoadedPreset"), ""); // ImGui::Text("Settings File: %s", presetfilepath.c_str()); UIWidgets::PaddedSeparator(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 20b5c333d..4ca8c7993 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1068,7 +1068,7 @@ void CheckTrackerWindow::DrawElement() { } bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { - bool shouldHideFilteredAreas = CVarGetInteger("gTrackers.CheckTracker.HideFilteredAreas", 1); + bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); if (!shouldHideFilteredAreas) { return false; } @@ -1640,7 +1640,7 @@ void CheckTrackerSettingsWindow::DrawElement() { // Filtering settings UIWidgets::PaddedSeparator(); - UIWidgets::EnhancementCheckbox("Filter Empty Areas", "gTrackers.CheckTracker.HideFilteredAreas", false, "", UIWidgets::CheckboxGraphics::Checkmark, true); + UIWidgets::EnhancementCheckbox("Filter Empty Areas", CVAR_TRACKER_CHECK("HideFilteredAreas"), false, "", UIWidgets::CheckboxGraphics::Checkmark, true); UIWidgets::Tooltip("If enabled, will hide area headers that have no locations matching filter"); ImGui::TableNextColumn(); @@ -1650,7 +1650,7 @@ void CheckTrackerSettingsWindow::DrawElement() { CheckTracker::ImGuiDrawTwoColorPickerSection("Unchecked", CVAR_TRACKER_CHECK("Unchecked.MainColor"), CVAR_TRACKER_CHECK("Unchecked.ExtraColor"), Color_Unchecked_Main, Color_Unchecked_Extra, Color_Main_Default, Color_Unchecked_Extra_Default, CVAR_TRACKER_CHECK("Unchecked.Hide"), "Checks you have not interacted with at all."); CheckTracker::ImGuiDrawTwoColorPickerSection("Skipped", CVAR_TRACKER_CHECK("Skipped.MainColor"), CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Main, Color_Skipped_Extra, Color_Main_Default, Color_Skipped_Extra_Default, CVAR_TRACKER_CHECK("Skipped.Hide"), ""); CheckTracker::ImGuiDrawTwoColorPickerSection("Seen", CVAR_TRACKER_CHECK("Seen.MainColor"), CVAR_TRACKER_CHECK("Seen.ExtraColor"), Color_Seen_Main, Color_Seen_Extra, Color_Main_Default, Color_Seen_Extra_Default, CVAR_TRACKER_CHECK("Seen.Hide"), "Used for shops. Shows item names for shop slots when walking in, and prices when highlighting them in buy mode."); - CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, "gCheckTrackerScummedHide", "Checks you collect, but then reload before saving so you no longer have them."); + CheckTracker::ImGuiDrawTwoColorPickerSection("Scummed", CVAR_TRACKER_CHECK("Scummed.MainColor"), CVAR_TRACKER_CHECK("Scummed.ExtraColor"), Color_Scummed_Main, Color_Scummed_Extra, Color_Main_Default, Color_Scummed_Extra_Default, CVAR_TRACKER_CHECK("Scummed.Hide"), "Checks you collect, but then reload before saving so you no longer have them."); //CheckTracker::ImGuiDrawTwoColorPickerSection("Hinted (WIP)", CVAR_TRACKER_CHECK("Hinted.MainColor"), CVAR_TRACKER_CHECK("Hinted.ExtraColor"), Color_Hinted_Main, Color_Hinted_Extra, Color_Main_Default, Color_Hinted_Extra_Default, CVAR_TRACKER_CHECK("Hinted.Hide"), ""); CheckTracker::ImGuiDrawTwoColorPickerSection("Collected", CVAR_TRACKER_CHECK("Collected.MainColor"), CVAR_TRACKER_CHECK("Collected.ExtraColor"), Color_Collected_Main, Color_Collected_Extra, Color_Main_Default, Color_Collected_Extra_Default, CVAR_TRACKER_CHECK("Collected.Hide"), "Checks you have collected without saving or reloading yet."); CheckTracker::ImGuiDrawTwoColorPickerSection("Saved", CVAR_TRACKER_CHECK("Saved.MainColor"), CVAR_TRACKER_CHECK("Saved.ExtraColor"), Color_Saved_Main, Color_Saved_Extra, Color_Main_Default, Color_Saved_Extra_Default, CVAR_TRACKER_CHECK("Saved.Hide"), "Checks that you saved the game while having collected."); diff --git a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp index b522879cb..f7eea0873 100644 --- a/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp +++ b/soh/soh/Enhancements/resolution-editor/ResolutionEditor.cpp @@ -4,8 +4,9 @@ #include #include +#include "soh/OTRGlobals.h" -/* Console Variables are grouped under gAdvancedResolution. (e.g. "gAdvancedResolution.Enabled") +/* Console Variables are grouped under gAdvancedResolution. (e.g. CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled") The following cvars are used in Libultraship and can be edited here: - Enabled - Turns Advanced Resolution Mode on. @@ -83,25 +84,25 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Letting it go below 1 in this Editor will even allow for checking if screen bounds are being exceeded. if (default_maxIntegerScaleFactor < integerScale_maximumBounds) { max_integerScaleFactor = - integerScale_maximumBounds + CVarGetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0); + integerScale_maximumBounds + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0); } // Combo List defaults - static int item_aspectRatio = CVarGetInteger("gAdvancedResolution.UIComboItem.AspectRatio", 3); - static int item_pixelCount = CVarGetInteger("gAdvancedResolution.UIComboItem.PixelCount", default_pixelCount); + static int item_aspectRatio = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", 3); + static int item_pixelCount = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", default_pixelCount); // Stored Values for non-UIWidgets elements static float aspectRatioX = - CVarGetFloat("gAdvancedResolution.AspectRatioX", aspectRatioPresetsX[item_aspectRatio]); + CVarGetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioPresetsX[item_aspectRatio]); static float aspectRatioY = - CVarGetFloat("gAdvancedResolution.AspectRatioY", aspectRatioPresetsY[item_aspectRatio]); + CVarGetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioPresetsY[item_aspectRatio]); static int verticalPixelCount = - CVarGetInteger("gAdvancedResolution.VerticalPixelCount", pixelCountPresets[item_pixelCount]); + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", pixelCountPresets[item_pixelCount]); // Additional settings static bool showHorizontalResField = false; static int horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX; // Disabling flags - const bool disabled_everything = !CVarGetInteger("gAdvancedResolution.Enabled", 0); - const bool disabled_pixelCount = !CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0); + const bool disabled_everything = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0); + const bool disabled_pixelCount = !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0); #ifdef __APPLE__ // Display HiDPI warning. (Remove this once we can definitively say it's fixed.) @@ -112,8 +113,8 @@ void AdvancedResolutionSettingsWindow::DrawElement() { if (ImGui::CollapsingHeader("Original Settings", ImGuiTreeNodeFlags_DefaultOpen)) { // The original resolution slider (for convenience) - const bool disabled_resolutionSlider = (CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && - CVarGetInteger("gAdvancedResolution.Enabled", 0)) || + const bool disabled_resolutionSlider = (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0) && + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0)) || CVarGetInteger(CVAR_LOW_RES_MODE, 0); if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f%%", "##IMul", CVAR_INTERNAL_RESOLUTION, 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { @@ -140,7 +141,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); // Activator - UIWidgets::PaddedEnhancementCheckbox("Enable advanced settings.", "gAdvancedResolution.Enabled", false, false, + UIWidgets::PaddedEnhancementCheckbox("Enable advanced settings.", CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); // Error/Warning display if (!CVarGetInteger(CVAR_LOW_RES_MODE, 0)) { @@ -185,9 +186,9 @@ void AdvancedResolutionSettingsWindow::DrawElement() { horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX; } - CVarSetFloat("gAdvancedResolution.AspectRatioX", aspectRatioX); - CVarSetFloat("gAdvancedResolution.AspectRatioY", aspectRatioY); - CVarSetInteger("gAdvancedResolution.UIComboItem.AspectRatio", item_aspectRatio); + CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioX); + CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioY); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", item_aspectRatio); CVarSave(); } // Hide aspect ratio input fields if using one of the presets. @@ -217,7 +218,7 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Vertical Resolution UIWidgets::PaddedEnhancementCheckbox("Set fixed vertical resolution (disables Resolution slider)", - "gAdvancedResolution.VerticalResolutionToggle", true, false, + CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", true, false, disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip( "Override the resolution scale slider and use the settings below, irrespective of window size."); @@ -233,8 +234,8 @@ void AdvancedResolutionSettingsWindow::DrawElement() { horizontalPixelCount = (verticalPixelCount / aspectRatioY) * aspectRatioX; } - CVarSetInteger("gAdvancedResolution.VerticalPixelCount", verticalPixelCount); - CVarSetInteger("gAdvancedResolution.UIComboItem.PixelCount", item_pixelCount); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", verticalPixelCount); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", item_pixelCount); CVarSave(); } // Horizontal Resolution, if visibility is enabled for it. @@ -290,43 +291,43 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Integer scaling settings group (Pixel-perfect Mode) static const ImGuiTreeNodeFlags IntegerScalingResolvedImGuiFlag = - CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0) ? ImGuiTreeNodeFlags_DefaultOpen + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) ? ImGuiTreeNodeFlags_DefaultOpen : ImGuiTreeNodeFlags_None; if (ImGui::CollapsingHeader("Integer Scaling Settings", IntegerScalingResolvedImGuiFlag)) { const bool disabled_pixelPerfectMode = - !CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0) || disabled_everything; + !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || disabled_everything; // Pixel-perfect Mode - UIWidgets::PaddedEnhancementCheckbox("Pixel-perfect Mode", "gAdvancedResolution.PixelPerfectMode", true, + UIWidgets::PaddedEnhancementCheckbox("Pixel-perfect Mode", CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", true, true, disabled_pixelCount || disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("Don't scale image to fill window."); - if (disabled_pixelCount && CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0)) { - CVarSetInteger("gAdvancedResolution.PixelPerfectMode", 0); + if (disabled_pixelCount && CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0)) { + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0); CVarSave(); } // Integer Scaling UIWidgets::EnhancementSliderInt( - "Integer scale factor: %d", "##ARSIntScale", "gAdvancedResolution.IntegerScale.Factor", 1, + "Integer scale factor: %d", "##ARSIntScale", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", 1, max_integerScaleFactor, "%d", 1, true, - disabled_pixelPerfectMode || CVarGetInteger("gAdvancedResolution.IntegerScale.FitAutomatically", 0)); + disabled_pixelPerfectMode || CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0)); UIWidgets::Tooltip("Integer scales the image. Only available in pixel-perfect mode."); // Display warning if size is being clamped or if framebuffer is larger than viewport. if (!disabled_pixelPerfectMode && - (CVarGetInteger("gAdvancedResolution.IntegerScale.NeverExceedBounds", 1) && - CVarGetInteger("gAdvancedResolution.IntegerScale.Factor", 1) > integerScale_maximumBounds)) { + (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds", 1) && + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", 1) > integerScale_maximumBounds)) { ImGui::SameLine(); ImGui::TextColored(messageColor[MESSAGE_WARNING], ICON_FA_EXCLAMATION_TRIANGLE " Window exceeded."); } UIWidgets::PaddedEnhancementCheckbox( - "Automatically scale image to fit viewport", "gAdvancedResolution.IntegerScale.FitAutomatically", true, + "Automatically scale image to fit viewport", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", true, true, disabled_pixelPerfectMode, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("Automatically sets scale factor to fit window. Only available in pixel-perfect mode."); - if (CVarGetInteger("gAdvancedResolution.IntegerScale.FitAutomatically", 0)) { + if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0)) { // This is just here to update the value shown on the slider. // The function in LUS to handle this setting will ignore IntegerScaleFactor while active. - CVarSetInteger("gAdvancedResolution.IntegerScale.Factor", integerScale_maximumBounds); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.Factor", integerScale_maximumBounds); // CVarSave(); } } // End of integer scaling settings @@ -344,19 +345,19 @@ void AdvancedResolutionSettingsWindow::DrawElement() { UIWidgets::PaddedEnhancementCheckbox("Disable aspect correction and stretch the output image.\n" "(Might be useful for 4:3 televisions!)\n" "Not available in Pixel Perfect Mode.", - "gAdvancedResolution.IgnoreAspectCorrection", false, true, - CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0) || + CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", false, true, + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false); #else - if (CVarGetInteger("gAdvancedResolution.IgnoreAspectCorrection", 0)) { + if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", 0)) { // This setting is intentionally not exposed on PC platforms, // but may be accidentally activated for varying reasons. // Having this button should hopefully prevent support headaches. ImGui::TextColored(messageColor[MESSAGE_QUESTION], ICON_FA_QUESTION_CIRCLE " If the image is stretched and you don't know why, click this."); if (ImGui::Button("Click to reenable aspect correction.")) { - CVarSetInteger("gAdvancedResolution.IgnoreAspectCorrection", 0); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IgnoreAspectCorrection", 0); CVarSave(); } UIWidgets::Spacer(2); @@ -386,12 +387,12 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Integer Scaling - Never Exceed Bounds. const bool disabled_neverExceedBounds = - !CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0) || - CVarGetInteger("gAdvancedResolution.IntegerScale.FitAutomatically", 0) || disabled_everything; + !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.FitAutomatically", 0) || disabled_everything; const bool checkbox_neverExceedBounds = UIWidgets::PaddedEnhancementCheckbox("Prevent integer scaling from exceeding screen bounds.\n" "(Makes screen bounds take priority over specified factor.)", - "gAdvancedResolution.IntegerScale.NeverExceedBounds", + CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds", true, false, disabled_neverExceedBounds, "", UIWidgets::CheckboxGraphics::Cross, true); UIWidgets::Tooltip( @@ -403,22 +404,22 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Initialise the (currently unused) "Exceed Bounds By" cvar if it's been changed. if (checkbox_neverExceedBounds && - CVarGetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0)) { - CVarSetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0); + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) { + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0); CVarSave(); } // Integer Scaling - Exceed Bounds By 1x/Offset. // A popular feature in some retro frontends/upscalers, sometimes called "crop overscan" or "1080p 5x". /* - UIWidgets::PaddedEnhancementCheckbox("Allow integer scale factor to go +1 above maximum screen bounds.", "gAdvancedResolution.IntegerScale.ExceedBoundsBy", false, false, !CVarGetInteger("gAdvancedResolution.PixelPerfectMode", 0) || disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Allow integer scale factor to go +1 above maximum screen bounds.", CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", false, false, !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".PixelPerfectMode", 0) || disabled_everything, "", UIWidgets::CheckboxGraphics::Cross, false); */ // It does actually function as expected, but exceeding the bottom of the screen shows a scroll bar. // I've ended up commenting this one out because of the scroll bar, and for simplicity. // Display an info message about the scroll bar. - if (!CVarGetInteger("gAdvancedResolution.IntegerScale.NeverExceedBounds", 1) || - CVarGetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0)) { + if (!CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.NeverExceedBounds", 1) || + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) { if (disabled_neverExceedBounds) { // Dim this help text accordingly UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } @@ -431,9 +432,9 @@ void AdvancedResolutionSettingsWindow::DrawElement() { // Another support helper button, to disable the unused "Exceed Bounds By" cvar. // (Remove this button if uncommenting the checkbox.) - if (CVarGetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0)) { + if (CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0)) { if (ImGui::Button("Click to reset a console variable that may be causing this.")) { - CVarSetInteger("gAdvancedResolution.IntegerScale.ExceedBoundsBy", 0); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".IntegerScale.ExceedBoundsBy", 0); CVarSave(); } } @@ -451,13 +452,13 @@ void AdvancedResolutionSettingsWindow::DrawElement() { if (aspectRatioX < 0.0f) { aspectRatioX = 0.0f; } - CVarSetFloat("gAdvancedResolution.AspectRatioX", aspectRatioX); + CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioX", aspectRatioX); } if (update[UPDATE_aspectRatioY]) { if (aspectRatioY < 0.0f) { aspectRatioY = 0.0f; } - CVarSetFloat("gAdvancedResolution.AspectRatioY", aspectRatioY); + CVarSetFloat(CVAR_PREFIX_ADVANCED_RESOLUTION ".AspectRatioY", aspectRatioY); } if (update[UPDATE_verticalPixelCount]) { // There's a upper and lower clamp on the Libultraship side too, @@ -468,10 +469,10 @@ void AdvancedResolutionSettingsWindow::DrawElement() { if (verticalPixelCount > maxVerticalPixelCount) { verticalPixelCount = maxVerticalPixelCount; } - CVarSetInteger("gAdvancedResolution.VerticalPixelCount", verticalPixelCount); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalPixelCount", verticalPixelCount); } - CVarSetInteger("gAdvancedResolution.UIComboItem.AspectRatio", item_aspectRatio); - CVarSetInteger("gAdvancedResolution.UIComboItem.PixelCount", item_pixelCount); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.AspectRatio", item_aspectRatio); + CVarSetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".UIComboItem.PixelCount", item_pixelCount); CVarSave(); } } @@ -484,7 +485,7 @@ void AdvancedResolutionSettingsWindow::UpdateElement() { bool AdvancedResolutionSettingsWindow::IsDroppingFrames() { // a rather imprecise way of checking for frame drops. // but it's mostly there to inform the player of large drops. - const short targetFPS = CVarGetInteger("gInterpolationFPS", 20); + const short targetFPS = CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20); const float threshold = targetFPS / 20.0f + 4.1f; return ImGui::GetIO().Framerate < targetFPS - threshold; } diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index abdcda0ee..593706dd6 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -92,7 +92,7 @@ std::string GetParameritizedText(std::string key, TextBank bank, const char* arg } const char* GetLanguageCode() { - switch (CVarGetInteger("gLanguages", 0)) { + switch (CVarGetInteger(CVAR_SETTING("Languages"), 0)) { case LANGUAGE_FRA: return "fr-FR"; break; @@ -116,7 +116,7 @@ static std::string titleCardText; void RegisterOnSceneInitHook() { GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; titleCardText = NameForSceneId(sceneNum); }); @@ -124,7 +124,7 @@ void RegisterOnSceneInitHook() { void RegisterOnPresentTitleCardHook() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; SpeechSynthesizer::Instance->Speak(titleCardText.c_str(), GetLanguageCode()); }); @@ -134,7 +134,7 @@ void RegisterOnPresentTitleCardHook() { void RegisterOnInterfaceUpdateHook() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; static uint32_t prevTimer = 0; static char ttsAnnounceBuf[32]; @@ -193,7 +193,7 @@ void RegisterOnInterfaceUpdateHook() { void RegisterOnKaleidoscopeUpdateHook() { GameInteractor::Instance->RegisterGameHook([](int16_t inDungeonScene) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; static int16_t prevCursorIndex = 0; static uint16_t prevCursorSpecialPos = 0; @@ -550,14 +550,14 @@ void RegisterOnKaleidoscopeUpdateHook() { void RegisterOnUpdateMainMenuSelection() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; auto translation = GetParameritizedText("file1", TEXT_BANK_FILECHOOSE, nullptr); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_MAIN_FILE_1: { @@ -596,7 +596,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_CONFIRM_YES: { @@ -615,7 +615,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_COPY_FILE_1: { @@ -644,7 +644,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_CONFIRM_YES: { @@ -663,7 +663,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_ERASE_FILE_1: { @@ -692,7 +692,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint16_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_BTN_CONFIRM_YES: { @@ -711,7 +711,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_AUDIO_STEREO: { @@ -740,7 +740,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case FS_TARGET_SWITCH: { @@ -759,7 +759,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (optionIndex) { case LANGUAGE_ENG: { @@ -783,7 +783,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint8_t questIndex) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; switch (questIndex) { case QUEST_NORMAL: { @@ -812,7 +812,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](uint8_t optionIndex, uint8_t optionValue) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; auto optionName = BossRush_GetSettingName(optionIndex, gSaveContext.language); auto optionValueName = BossRush_GetSettingChoiceName(optionIndex, optionValue, gSaveContext.language); @@ -821,7 +821,7 @@ void RegisterOnUpdateMainMenuSelection() { }); GameInteractor::Instance->RegisterGameHook([](int16_t charCode) { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; char charVal[2]; std::string translation; @@ -958,7 +958,7 @@ std::string Message_TTS_Decode(uint8_t* sourceBuf, uint16_t startOfset, uint16_t void RegisterOnDialogMessageHook() { GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger("gA11yTTS", 0)) return; + if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) return; MessageContext *msgCtx = &gPlayState->msgCtx; @@ -1030,7 +1030,7 @@ void RegisterOnDialogMessageHook() { void InitTTSBank() { std::string languageSuffix = "_eng.json"; - switch (CVarGetInteger("gLanguages", 0)) { + switch (CVarGetInteger(CVAR_SETTING("Languages"), 0)) { case LANGUAGE_FRA: languageSuffix = "_fra.json"; break; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2dd324fe8..0a0b83d4a 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -432,7 +432,7 @@ OTRGlobals::~OTRGlobals() { } void OTRGlobals::ScaleImGui() { - float scale = imguiScaleOptionToValue[CVarGetInteger("gImGuiScale", defaultImGuiScale)]; + float scale = imguiScaleOptionToValue[CVarGetInteger(CVAR_SETTING("ImGuiScale"), defaultImGuiScale)]; float newScale = scale / previousImGuiScale; ImGui::GetStyle().ScaleAllSizes(newScale); ImGui::GetIO().FontGlobalScale = scale; @@ -467,14 +467,14 @@ bool OTRGlobals::HasOriginal() { uint32_t OTRGlobals::GetInterpolationFPS() { if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { - return CVarGetInteger("gInterpolationFPS", 20); + return CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20); } - if (CVarGetInteger("gMatchRefreshRate", 0)) { + if (CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0)) { return Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); } - return std::min(Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(), CVarGetInteger("gInterpolationFPS", 20)); + return std::min(Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(), CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20)); } struct ExtensionEntry { @@ -1153,17 +1153,17 @@ extern "C" void InitOTR() { InitMods(); ActorDB::AddBuiltInCustomActors(); // #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer - CVarClear("gRandomizerNewFileDropped"); - CVarClear("gRandomizerDroppedFile"); + CVarClear(CVAR_GENERAL("RandomizerNewFileDropped")); + CVarClear(CVAR_GENERAL("RandomizerDroppedFile")); // #endregion GameInteractor::Instance->RegisterGameHook(SoH_ProcessDroppedFiles); time_t now = time(NULL); tm *tm_now = localtime(&now); if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) { - CVarRegisterInteger("gLetItSnow", 1); + CVarRegisterInteger(CVAR_GENERAL("LetItSnow"), 1); } else { - CVarClear("gLetItSnow"); + CVarClear(CVAR_GENERAL("LetItSnow")); } srand(now); @@ -1335,7 +1335,7 @@ extern "C" void Graph_StartFrame() { #if defined(_WIN32) || defined(__APPLE__) case KbScancode::LUS_KB_F9: { // Toggle TTS - CVarSetInteger("gA11yTTS", !CVarGetInteger("gA11yTTS", 0)); + CVarSetInteger(CVAR_SETTING("A11yTTS"), !CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)); break; } #endif @@ -1405,7 +1405,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps); - int threshold = CVarGetInteger("gExtraLatencyThreshold", 80); + int threshold = CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80); OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); RunCommands(commands, mtx_replacements); @@ -1502,7 +1502,7 @@ extern "C" uint32_t ResourceMgr_GetGameRegion(int index) { uint32_t IsSceneMasterQuest(s16 sceneNum) { uint32_t value = 0; - uint8_t mqMode = CVarGetInteger("gBetterDebugWarpScreenMQMode", WARP_MODE_OVERRIDE_OFF); + uint8_t mqMode = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQMode"), WARP_MODE_OVERRIDE_OFF); if (mqMode == WARP_MODE_OVERRIDE_MQ_AS_VANILLA) { return 1; } else if (mqMode == WARP_MODE_OVERRIDE_VANILLA_AS_MQ) { @@ -2131,11 +2131,11 @@ extern "C" uint32_t OTRGetCurrentHeight() { } Color_RGB8 GetColorForControllerLED() { - auto brightness = CVarGetFloat("gLedBrightness", 1.0f) / 1.0f; + auto brightness = CVarGetFloat(CVAR_SETTING("LEDBrightness"), 1.0f) / 1.0f; Color_RGB8 color = { 0, 0, 0 }; if (brightness > 0.0f) { - LEDColorSource source = static_cast(CVarGetInteger("gLedColorSource", LED_SOURCE_TUNIC_ORIGINAL)); - bool criticalOverride = CVarGetInteger("gLedCriticalOverride", 1); + LEDColorSource source = static_cast(CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL)); + bool criticalOverride = CVarGetInteger(CVAR_SETTING("LEDCriticalOverride"), 1); if (gPlayState && (source == LED_SOURCE_TUNIC_ORIGINAL || source == LED_SOURCE_TUNIC_COSMETICS)) { switch (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC)) { case EQUIP_VALUE_TUNIC_KOKIRI: @@ -2202,7 +2202,7 @@ Color_RGB8 GetColorForControllerLED() { } } if (source == LED_SOURCE_CUSTOM) { - color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); + color = CVarGetColor24(CVAR_SETTING("LEDPort1Color"), { 255, 255, 255 }); } if (gPlayState && (criticalOverride || source == LED_SOURCE_HEALTH)) { if (HealthMeter_IsCritical()) { @@ -2462,7 +2462,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if (player->getItemEntry.getItemId == RG_ICE_TRAP) { u16 iceTrapTextId = Random(0, NUM_ICE_TRAP_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::IceTrapRandoMessageTableID, iceTrapTextId); - if (CVarGetInteger("gLetItSnow", 0)) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::IceTrapRandoMessageTableID, NUM_ICE_TRAP_MESSAGES + 1); } } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { @@ -2724,8 +2724,8 @@ void SoH_ProcessDroppedFiles(std::string filePath) { // #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer if (configJson.contains("version") && configJson.contains("finalSeed")) { - CVarSetString("gRandomizerDroppedFile", filePath.c_str()); - CVarSetInteger("gRandomizerNewFileDropped", 1); + CVarSetString(CVAR_GENERAL("RandomizerDroppedFile"), filePath.c_str()); + CVarSetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 1); return; } // #endregion diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 484a9e1b1..0a96f9f19 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1166,7 +1166,7 @@ int SaveManager::GetSaveSectionID(std::string& sectionName) { void SaveManager::CreateDefaultGlobal() { gSaveContext.audioSetting = 0; gSaveContext.zTargetSetting = 0; - gSaveContext.language = CVarGetInteger("gLanguages", LANGUAGE_ENG); + gSaveContext.language = CVarGetInteger(CVAR_SETTING("Languages"), LANGUAGE_ENG); SaveGlobal(); } @@ -2546,7 +2546,7 @@ void SaveManager::ConvertFromUnversioned() { gSaveContext.zTargetSetting = data[SRAM_HEADER_ZTARGET] & 1; gSaveContext.language = data[SRAM_HEADER_LANGUAGE]; if (gSaveContext.language >= LANGUAGE_MAX) { - gSaveContext.language = CVarGetInteger("gLanguages", LANGUAGE_ENG); + gSaveContext.language = CVarGetInteger(CVAR_SETTING("Languages"), LANGUAGE_ENG); } SaveGlobal(); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index e7eb998dd..7fde4f351 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -201,7 +201,7 @@ namespace SohGui { gui->AddGuiWindow(mRandomizerSettingsWindow); mAdvancedResolutionSettingsWindow = std::make_shared(CVAR_WINDOW("AdvancedResolutionEditor"), "Advanced Resolution Settings"); gui->AddGuiWindow(mAdvancedResolutionSettingsWindow); - mModalWindow = std::make_shared("gOpenWindows.modalWindowEnabled", "Modal Window"); + mModalWindow = std::make_shared(CVAR_WINDOW("ModalWindow"), "Modal Window"); gui->AddGuiWindow(mModalWindow); mModalWindow->Show(); } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index fbcf2496a..b847988dc 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -182,18 +182,18 @@ void DrawSettingsMenu() { if (ImGui::BeginMenu("Settings")) { if (ImGui::BeginMenu("Audio")) { - UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %.1f %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true); - if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %.1f %%", "##Main_Music_Vol", "gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); + UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %.1f %%", "##Master_Vol", CVAR_SETTING("Volume.Master"), 0.0f, 1.0f, "", 1.0f, true, true, false, true); + if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %.1f %%", "##Main_Music_Vol", CVAR_SETTING("Volume.MainMusic"), 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat(CVAR_SETTING("Volume.MainMusic"), 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %.1f %%", "##Sub_Music_Vol", "gSubMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); + if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %.1f %%", "##Sub_Music_Vol", CVAR_SETTING("Volume.SubMusic"), 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat(CVAR_SETTING("Volume.SubMusic"), 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %.1f %%", "##Sound_Effect_Vol", "gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); + if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %.1f %%", "##Sound_Effect_Vol", CVAR_SETTING("Volume.SFX"), 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat(CVAR_SETTING("Volume.SFX"), 1.0f)); } - if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %.1f %%", "##Fanfare_Vol", "gFanfareVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { - Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); + if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %.1f %%", "##Fanfare_Vol", CVAR_SETTING("Volume.Fanfare"), 0.0f, 1.0f, "", 1.0f, true, true, false, true)) { + Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat(CVAR_SETTING("Volume.Fanfare"), 1.0f)); } static std::unordered_map audioBackendNames = { @@ -270,8 +270,8 @@ void DrawSettingsMenu() { if (ImGui::BeginMenu("Graphics")) { #ifndef __APPLE__ - const bool disabled_resolutionSlider = CVarGetInteger("gAdvancedResolution.VerticalResolutionToggle", 0) && - CVarGetInteger("gAdvancedResolution.Enabled", 0); + const bool disabled_resolutionSlider = CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0) && + CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".Enabled", 0); if (UIWidgets::EnhancementSliderFloat("Internal Resolution: %.1f %%", "##IMul", CVAR_INTERNAL_RESOLUTION, 0.5f, 2.0f, "", 1.0f, true, true, disabled_resolutionSlider)) { Ship::Context::GetInstance()->GetWindow()->SetResolutionMultiplier(CVarGetFloat(CVAR_INTERNAL_RESOLUTION, 1)); @@ -344,7 +344,7 @@ void DrawSettingsMenu() { fpsSlider = 3; } } - if (CVarGetInteger("gMatchRefreshRate", 0)) { + if (CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0)) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } @@ -366,7 +366,7 @@ void DrawSettingsMenu() { fpsSlider++; } - if (CVarGetInteger("gMatchRefreshRate", 0)) { + if (CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0)) { UIWidgets::ReEnableComponent(""); } if (fpsSlider > 3) { @@ -382,14 +382,14 @@ void DrawSettingsMenu() { } else if (fpsSlider == 3) { currentFps = 60; } - CVarSetInteger("gInterpolationFPS", currentFps); + CVarSetInteger(CVAR_SETTING("InterpolationFPS"), currentFps); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); #else bool matchingRefreshRate = - CVarGetInteger("gMatchRefreshRate", 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11; + CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11; UIWidgets::PaddedEnhancementSliderInt( (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps", - "##FPSInterpolation", "gInterpolationFPS", minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); + "##FPSInterpolation", CVAR_SETTING("InterpolationFPS"), minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); #endif if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { UIWidgets::Tooltip( @@ -411,18 +411,18 @@ void DrawSettingsMenu() { if (ImGui::Button("Match Frame Rate to Refresh Rate")) { int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); if (hz >= 20 && hz <= 360) { - CVarSetInteger("gInterpolationFPS", hz); + CVarSetInteger(CVAR_SETTING("InterpolationFPS"), hz); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } } else { - UIWidgets::PaddedEnhancementCheckbox("Match Frame Rate to Refresh Rate", "gMatchRefreshRate", true, false); + UIWidgets::PaddedEnhancementCheckbox("Match Frame Rate to Refresh Rate", CVAR_SETTING("MatchRefreshRate"), true, false); } UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate."); if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { - UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger("gExtraLatencyThreshold", 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", - "##ExtraLatencyThreshold", "gExtraLatencyThreshold", 0, 360, "", 80, true, true, false); + UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", + "##ExtraLatencyThreshold", CVAR_SETTING("ExtraLatencyThreshold"), 0, 360, "", 80, true, true, false); UIWidgets::Tooltip( "(For DirectX backend only)\n\n" "When Interpolation FPS (Frame Rate) setting is at least this threshold, add one frame of delay (e.g. 16.6 ms for 60 FPS) in order to avoid jitter." @@ -435,7 +435,7 @@ void DrawSettingsMenu() { ImGui::Text("ImGui Menu Scale"); ImGui::SameLine(); ImGui::TextColored({ 0.85f, 0.35f, 0.0f, 1.0f }, "(Experimental)"); - if (UIWidgets::EnhancementCombobox("gImGuiScale", imguiScaleOptions, 1)) { + if (UIWidgets::EnhancementCombobox(CVAR_SETTING("ImGuiScale"), imguiScaleOptions, 1)) { OTRGlobals::Instance->ScaleImGui(); } UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements."); @@ -511,14 +511,14 @@ void DrawSettingsMenu() { UIWidgets::Spacer(0); if (ImGui::BeginMenu("Languages")) { - UIWidgets::PaddedEnhancementCheckbox("Translate Title Screen", "gTitleScreenTranslation"); - if (UIWidgets::EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG)) { + UIWidgets::PaddedEnhancementCheckbox("Translate Title Screen", CVAR_SETTING("TitleScreenTranslation")); + if (UIWidgets::EnhancementRadioButton("English", CVAR_SETTING("Languages"), LANGUAGE_ENG)) { GameInteractor::Instance->ExecuteHooks(); } - if (UIWidgets::EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER)) { + if (UIWidgets::EnhancementRadioButton("German", CVAR_SETTING("Languages"), LANGUAGE_GER)) { GameInteractor::Instance->ExecuteHooks(); } - if (UIWidgets::EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA)) { + if (UIWidgets::EnhancementRadioButton("French", CVAR_SETTING("Languages"), LANGUAGE_FRA)) { GameInteractor::Instance->ExecuteHooks(); } ImGui::EndMenu(); @@ -528,10 +528,10 @@ void DrawSettingsMenu() { if (ImGui::BeginMenu("Accessibility")) { #if defined(_WIN32) || defined(__APPLE__) - UIWidgets::PaddedEnhancementCheckbox("Text to Speech", "gA11yTTS"); + UIWidgets::PaddedEnhancementCheckbox("Text to Speech", CVAR_SETTING("A11yTTS")); UIWidgets::Tooltip("Enables text to speech for in game dialog"); #endif - UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", "gA11yDisableIdleCam"); + UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", CVAR_SETTING("A11yDisableIdleCam")); UIWidgets::Tooltip("Disables the automatic re-centering of the camera when idle."); ImGui::EndMenu(); @@ -1763,7 +1763,8 @@ void DrawRemoteControlMenu() { ImGui::BeginDisabled(GameInteractor::Instance->isRemoteInteractorEnabled); ImGui::Text("Remote Interaction Scheme"); if (UIWidgets::EnhancementCombobox(CVAR_REMOTE("Scheme"), remoteOptions, GI_SCHEME_SAIL)) { - switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { + auto scheme = CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL); + switch (scheme) { case GI_SCHEME_SAIL: case GI_SCHEME_CROWD_CONTROL: CVarSetString(CVAR_REMOTE("IP"), "127.0.0.1"); @@ -1827,7 +1828,8 @@ void DrawRemoteControlMenu() { const char* buttonLabel = GameInteractor::Instance->isRemoteInteractorEnabled ? "Disable" : "Enable"; if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) { if (GameInteractor::Instance->isRemoteInteractorEnabled) { - CVarSetInteger(CVAR_REMOTE("Enabled"), 0); + CVarClear(CVAR_REMOTE("Enabled")); + CVarClear(CVAR_REMOTE("CrowdControl")); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); switch (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL)) { case GI_SCHEME_SAIL: diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index bd0843e96..d1bf0967a 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -486,14 +486,14 @@ namespace UIWidgets { bool EnhancementRadioButton(const char* text, const char* cvarName, int id) { /*Usage : - EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); + EnhancementRadioButton("My Visible Name",CVAR_GROUP("MyCVarName"), MyID); First arg is the visible name of the Radio button Second is the cvar name where MyID will be saved. Note: the CVar name should be the same to each Buddies. Example : - EnhancementRadioButton("English", "gLanguages", LANGUAGE_ENG); - EnhancementRadioButton("German", "gLanguages", LANGUAGE_GER); - EnhancementRadioButton("French", "gLanguages", LANGUAGE_FRA); + EnhancementRadioButton("English", CVAR_SETTING("Languages"), LANGUAGE_ENG); + EnhancementRadioButton("German", CVAR_SETTING("Languages"), LANGUAGE_GER); + EnhancementRadioButton("French", CVAR_SETTING("Languages"), LANGUAGE_FRA); */ std::string make_invisible = "##" + std::string(text) + std::string(cvarName); diff --git a/soh/src/code/audioMgr.c b/soh/src/code/audioMgr.c index d9b215d07..2a6752206 100644 --- a/soh/src/code/audioMgr.c +++ b/soh/src/code/audioMgr.c @@ -109,10 +109,10 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon Audio_InitSound(); osSendMesgPtr(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK); - Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f)); - Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f)); - Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f)); - Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat(CVAR_SETTING("Volume.MainMusic"), 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat(CVAR_SETTING("Volume.SubMusic"), 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat(CVAR_SETTING("Volume.Fanfare"), 1.0f)); + Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat(CVAR_SETTING("Volume.SFX"), 1.0f)); // Removed due to crash //IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74); diff --git a/soh/src/code/audio_playback.c b/soh/src/code/audio_playback.c index 66f236c43..39be0c3a7 100644 --- a/soh/src/code/audio_playback.c +++ b/soh/src/code/audio_playback.c @@ -94,7 +94,7 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { vel = 0.0f > vel ? 0.0f : vel; vel = 1.0f < vel ? 1.0f : vel; - float master_vol = CVarGetFloat("gGameMasterVolume", 1.0f); + float master_vol = CVarGetFloat(CVAR_SETTING("Volume.Master"), 1.0f); sub->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)) * master_vol; sub->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)) * master_vol; @@ -120,7 +120,7 @@ void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) } else { noteSubEu->bitField1.hasTwoParts = true; if (3.99996f < resamplingRateInput) { - if (CVarGetInteger("gExperimentalOctaveDrop", 0)) { + if (CVarGetInteger(CVAR_AUDIO("ExperimentalOctaveDrop"), 0)) { resamplingRate = resamplingRateInput * 0.25; } else { resamplingRate = 1.99998f; diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c index f2c526630..7044a48c4 100644 --- a/soh/src/code/audio_synthesis.c +++ b/soh/src/code/audio_synthesis.c @@ -653,7 +653,7 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat } updateIndex = aiBufLen * 2; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { aInterleave(cmd++, DMEM_TEMP, DMEM_RIGHT_CH, DMEM_LEFT_CH, updateIndex); } else { aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, updateIndex); diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index 95387b448..756dcaa89 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -1259,11 +1259,11 @@ void Audio_PlayFanfare_Rando(GetItemEntry getItem); // Function originally not called, so repurposing for control mapping void Audio_OcaUpdateBtnMap(bool customControls, bool dpad, bool rStick) { if (customControls) { - sOcarinaD5BtnMap = CVarGetInteger("gOcarinaD5BtnMap", BTN_CUP); - sOcarinaB4BtnMap = CVarGetInteger("gOcarinaB4BtnMap", BTN_CLEFT); - sOcarinaA4BtnMap = CVarGetInteger("gOcarinaA4BtnMap", BTN_CRIGHT); - sOcarinaF4BtnMap = CVarGetInteger("gOcarinaF4BtnMap", BTN_CDOWN); - sOcarinaD4BtnMap = CVarGetInteger("gOcarinaD4BtnMap", BTN_A); + sOcarinaD5BtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.D5Button"), BTN_CUP); + sOcarinaB4BtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.B4Button"), BTN_CLEFT); + sOcarinaA4BtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.A4Button"), BTN_CRIGHT); + sOcarinaF4BtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.F4Button"), BTN_CDOWN); + sOcarinaD4BtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.D4Button"), BTN_A); } else { sOcarinaD5BtnMap = BTN_CUP; sOcarinaB4BtnMap = BTN_CLEFT; @@ -1540,8 +1540,8 @@ void func_800ED200(void) { u8 k; u32 disableSongBtnMap; - if (CVarGetInteger("gCustomOcarinaControls", 0)) { - disableSongBtnMap = CVarGetInteger("gOcarinaDisableBtnMap", BTN_L); + if (CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) { + disableSongBtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.DisableButton"), BTN_L); } else { disableSongBtnMap = BTN_L; } @@ -1602,9 +1602,9 @@ void func_800ED200(void) { void func_800ED458(s32 arg0) { u32 phi_v1_2; - bool customControls = CVarGetInteger("gCustomOcarinaControls", 0); - bool dpad = CVarGetInteger("gDpadOcarina", 0); - bool rStick = CVarGetInteger("gRStickOcarina", 0); + bool customControls = CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0); + bool dpad = CVarGetInteger(CVAR_SETTING("OcarinaControl.Dpad"), 0); + bool rStick = CVarGetInteger(CVAR_SETTING("OcarinaControl.RStick"), 0); if (D_80130F3C != 0 && sOcarinaDropInputTimer != 0) { sOcarinaDropInputTimer--; @@ -1650,7 +1650,7 @@ void func_800ED458(s32 arg0) { u32 noteSharpBtnMap; if (customControls) { - noteSharpBtnMap = CVarGetInteger("gOcarinaSharpBtnMap", BTN_R); + noteSharpBtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.SharpButton"), BTN_R); } else { noteSharpBtnMap = BTN_R; } @@ -1661,7 +1661,7 @@ void func_800ED458(s32 arg0) { u32 noteFlatBtnMap; if (customControls) { - noteFlatBtnMap = CVarGetInteger("gOcarinaFlatBtnMap", BTN_Z); + noteFlatBtnMap = CVarGetInteger(CVAR_SETTING("CustomOcarina.FlatButton"), BTN_Z); } else { noteFlatBtnMap = BTN_Z; } diff --git a/soh/src/code/game.c b/soh/src/code/game.c index 8d97177fd..f0988c7c3 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -329,7 +329,7 @@ void GameState_Update(GameState* gameState) { func_800C49F4(gfxCtx); } - gSaveContext.language = CVarGetInteger("gLanguages", LANGUAGE_ENG); + gSaveContext.language = CVarGetInteger(CVAR_SETTING("Languages"), LANGUAGE_ENG); GameInteractor_ExecuteOnGameFrameUpdate(); gameState->frames++; diff --git a/soh/src/code/gfxprint.c b/soh/src/code/gfxprint.c index 9caad46a8..1717e46b3 100644 --- a/soh/src/code/gfxprint.c +++ b/soh/src/code/gfxprint.c @@ -214,7 +214,7 @@ void GfxPrint_SetColor(GfxPrint* this, u32 r, u32 g, u32 b, u32 a) { } void GfxPrint_SetPosPx(GfxPrint* this, s32 x, s32 y) { - this->posX = this->baseX + (x * 4) + CVarGetInteger("gGfxPrintCharStartOffset", 0); + this->posX = this->baseX + (x * 4) + CVarGetInteger(CVAR_DEVELOPER_TOOLS("GfxPrintChar.StartOffset"), 0); this->posY = this->baseY + (y * 4); } @@ -272,7 +272,7 @@ void GfxPrint_PrintCharImpl(GfxPrint* this, u8 c) { (u16)(c >> 3) * 256, 1 << 10, 1 << 10); } - this->posX += CVarGetInteger("gGfxPrintCharSpacing", 32); + this->posX += CVarGetInteger(CVAR_DEVELOPER_TOOLS("GfxPrintChar.Spacing"), 32); } void GfxPrint_PrintStringWithSize(GfxPrint* this, const void* buffer, u32 charSize, u32 charCount) { diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index d72a30277..f5d620e72 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -290,7 +290,7 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) { OPEN_DISPS(gfxCtx); - if (CVarGetInteger("gValueViewer.EnablePrinting", 0)) { + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ValueViewerEnablePrinting"), 0)) { Gfx* gfx; Gfx* polyOpa; GfxPrint printer; diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index 3315a9fe8..57dd2c6f7 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -287,8 +287,8 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) { // When 3 frames are left on easy pause buffer, re-apply the last held inputs to the prev inputs // to compute the pressed difference. This makes it so previously held inputs are continued as "held", // but new inputs when unpausing are "pressed" out of the pause menu. - if (CVarGetInteger("gCheatEasyPauseBufferTimer", 0) == 3) { - input->prev.button = CVarGetInteger("gCheatEasyPauseBufferLastInputs", 0); + if (CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0) == 3) { + input->prev.button = CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferLastInputs"), 0); } buttonDiff = input->prev.button ^ input->cur.button; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 4242b9ecc..9eac79559 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1082,10 +1082,10 @@ void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* void TitleCard_Update(PlayState* play, TitleCardContext* titleCtx) { const Color_RGB8 TitleCard_Colors_ori = {255,255,255}; Color_RGB8 TitleCard_Colors = {255,255,255}; - if (titleCtx->isBossCard && CVarGetInteger("gHudColors", 1) == 2) {//Bosses cards. - TitleCard_Colors = CVarGetColor24("gCCTC_B_U_Prim", TitleCard_Colors_ori); - } else if (!titleCtx->isBossCard && CVarGetInteger("gHudColors", 1) == 2) { - TitleCard_Colors = CVarGetColor24("gCCTC_OW_U_Prim", TitleCard_Colors_ori); + if (titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Boss.Changed"), 1) == 2) { + TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Boss.Value"), TitleCard_Colors_ori); + } else if (!titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Map.Changed"), 1) == 2) { + TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Map.Value"), TitleCard_Colors_ori); } else { TitleCard_Colors = TitleCard_Colors_ori; } @@ -1129,10 +1129,10 @@ void TitleCard_Draw(PlayState* play, TitleCardContext* titleCtx) { if (TitleCard_PosType_Checker != 0) { TitleCard_PosY = TitleCard_PosY_Modifier; if (TitleCard_PosType_Checker == 1) {//Anchor Left - if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger("gHUDMargin_L", 0)*-1;}; + if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0)*-1;}; TitleCard_PosX = OTRGetDimensionFromLeftEdge(TitleCard_PosX_Modifier+TitleCard_MarginX)-11; } else if (TitleCard_PosType_Checker == 2) {//Anchor Right - if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger("gHUDMargin_R", 0);}; + if (TitleCard_Margin_Checker != 0) {TitleCard_MarginX = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0);}; TitleCard_PosX = OTRGetDimensionFromRightEdge(TitleCard_PosX_Modifier+TitleCard_MarginX); } else if (TitleCard_PosType_Checker == 3) {//Anchor None TitleCard_PosX = TitleCard_PosX_Modifier; @@ -2214,7 +2214,7 @@ void Player_PlaySfx(Actor* actor, u16 sfxId) { if (actor->id != ACTOR_PLAYER || sfxId < NA_SE_VO_LI_SWORD_N || sfxId > NA_SE_VO_LI_ELECTRIC_SHOCK_LV_KID) { Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8); } else { - freqMultiplier = CVarGetFloat("gLinkVoiceFreqMultiplier", 1.0); + freqMultiplier = CVarGetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0); if (freqMultiplier <= 0) { freqMultiplier = 1; } @@ -2911,7 +2911,7 @@ s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { // #region SoH [Widescreen support] // Doors will cull quite noticeably on wider screens. For these actors the zone is increased f32 limit = 1.0f; - if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger("gIncreaseDoorUncullZones", 1)) { + if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger(CVAR_GENERAL("IncreaseDoorUncullZones"), 1)) { limit = 2.0f; } diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 03f8b4b7a..c9bd14ff0 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1485,12 +1485,12 @@ s32 Camera_Free(Camera* camera) { camera->animState = 0; - f32 newCamX = -D_8015BD7C->state.input[0].cur.right_stick_x * 10.0f * (CVarGetFloat("gThirdPersonCameraSensitivityX", 1.0f)); - f32 newCamY = D_8015BD7C->state.input[0].cur.right_stick_y * 10.0f * (CVarGetFloat("gThirdPersonCameraSensitivityY", 1.0f)); - bool invertXAxis = (CVarGetInteger("gInvertXAxis", 0) && !CVarGetInteger("gMirroredWorld", 0)) || (!CVarGetInteger("gInvertXAxis", 0) && CVarGetInteger("gMirroredWorld", 0)); + f32 newCamX = -D_8015BD7C->state.input[0].cur.right_stick_x * 10.0f * (CVarGetFloat(CVAR_SETTING("FreeLook.CameraSensitivity.X"), 1.0f)); + f32 newCamY = D_8015BD7C->state.input[0].cur.right_stick_y * 10.0f * (CVarGetFloat(CVAR_SETTING("FreeLook.CameraSensitivity.Y"), 1.0f)); + bool invertXAxis = (CVarGetInteger(CVAR_SETTING("FreeLook.InvertXAxis"), 0) && !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) || (!CVarGetInteger(CVAR_SETTING("FreeLook.InvertXAxis"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)); camera->play->camX += newCamX * (invertXAxis ? -1 : 1); - camera->play->camY += newCamY * (CVarGetInteger("gInvertYAxis", 1) ? 1 : -1); + camera->play->camY += newCamY * (CVarGetInteger(CVAR_SETTING("FreeLook.InvertYAxis"), 1) ? 1 : -1); if (camera->play->camY > 0x32A4) { camera->play->camY = 0x32A4; @@ -1499,8 +1499,8 @@ s32 Camera_Free(Camera* camera) { camera->play->camY = -0x228C; } - f32 distTarget = CVarGetInteger("gFreeCameraDistMax", para1->distTarget); - f32 speedScaler = CVarGetInteger("gFreeCameraTransitionSpeed", 25); + f32 distTarget = CVarGetInteger(CVAR_SETTING("FreeLook.MaxCameraDistance"), para1->distTarget); + f32 speedScaler = CVarGetInteger(CVAR_SETTING("FreeLook.TransitionSpeed"), 25); f32 distDiff = ABS(distTarget - camera->dist); if (distDiff > 0) camera->dist = Camera_LERPCeilF(distTarget, camera->dist, speedScaler / (distDiff + speedScaler), 0.0f); @@ -1524,7 +1524,7 @@ s32 Camera_Free(Camera* camera) { } s32 Camera_Normal1(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -1679,7 +1679,7 @@ s32 Camera_Normal1(Camera* camera) { if (anim->startSwingTimer <= 0) { // idle camera re-center - if (CVarGetInteger("gA11yDisableIdleCam", 0)) { + if (CVarGetInteger(CVAR_SETTING("A11yDisableIdleCam"), 0)) { return 1; } eyeAdjustment.pitch = atEyeNextGeo.pitch; @@ -1770,7 +1770,7 @@ s32 Camera_Normal1(Camera* camera) { } s32 Camera_Normal2(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -1941,7 +1941,7 @@ s32 Camera_Normal2(Camera* camera) { // riding epona s32 Camera_Normal3(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -2305,7 +2305,7 @@ s32 Camera_Parallel0(Camera* camera) { * Generic jump, jumping off ledges */ s32 Camera_Jump1(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -2455,7 +2455,7 @@ s32 Camera_Jump1(Camera* camera) { // Climbing ladders/vines s32 Camera_Jump2(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -2642,7 +2642,7 @@ s32 Camera_Jump2(Camera* camera) { // swimming s32 Camera_Jump3(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -3104,7 +3104,7 @@ s32 Camera_Battle3(Camera* camera) { * setting value. */ s32 Camera_Battle4(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -4639,7 +4639,7 @@ s32 Camera_Data4(Camera* camera) { * Hanging off of a ledge */ s32 Camera_Unique1(Camera* camera) { - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1) { Camera_Free(camera); return 1; } @@ -7890,7 +7890,7 @@ s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags) { } // Clear free look if an action is performed that would move the camera (targeting, first person, talking) - if (CVarGetInteger("gFreeCamera", 0) && SetCameraManual(camera) == 1 && + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && SetCameraManual(camera) == 1 && ((mode >= CAM_MODE_TARGET && mode <= CAM_MODE_BATTLE) || (mode >= CAM_MODE_FIRSTPERSON && mode <= CAM_MODE_CLIMBZ) || mode == CAM_MODE_HANGZ || mode == CAM_MODE_FOLLOWBOOMERANG)) { diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 7a2b9d3d8..db344d39e 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #define FLAGS 0 @@ -333,7 +334,7 @@ void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc) { void EnItem00_SetObjectDependency(EnItem00* this, PlayState* play, s16 objectIndex) { // Remove object dependency for Enemy Randomizer and Crowd Control to allow Like-likes to // drop equipment correctly in rooms where Like-likes normally don't spawn. - if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) { this->actor.objBankIndex = 0; } else { this->actor.objBankIndex = Object_GetIndex(&play->objectCtx, objectIndex); diff --git a/soh/src/code/z_kaleido_setup.c b/soh/src/code/z_kaleido_setup.c index e2feccf3c..3efbd6ade 100644 --- a/soh/src/code/z_kaleido_setup.c +++ b/soh/src/code/z_kaleido_setup.c @@ -19,12 +19,12 @@ void KaleidoSetup_Update(PlayState* play) { (play->sceneNum != SCENE_BOMBCHU_BOWLING_ALLEY || !Flags_GetSwitch(play, 0x38))) { u8 easyPauseBufferEnabled = CVarGetInteger(CVAR_CHEAT("EasyPauseBuffer"), 0); - u8 easyPauseBufferTimer = CVarGetInteger("gCheatEasyPauseBufferTimer", 0); + u8 easyPauseBufferTimer = CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0); // If start is not seen as pressed on the 2nd to last frame then we should end the easy frame advance flow if (easyPauseBufferEnabled && easyPauseBufferTimer == 2 && !CHECK_BTN_ALL(input->press.button, BTN_START)) { - CVarSetInteger("gCheatEasyPauseBufferTimer", 0); + CVarSetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0); } if (CHECK_BTN_ALL(input->cur.button, BTN_L) && CHECK_BTN_ALL(input->press.button, BTN_CUP)) { @@ -34,14 +34,14 @@ void KaleidoSetup_Update(PlayState* play) { } else if ((CHECK_BTN_ALL(input->press.button, BTN_START) && (!easyPauseBufferEnabled || !easyPauseBufferTimer)) || (easyPauseBufferEnabled && easyPauseBufferTimer == 1)) { // Force Kaleido open when easy pause buffer reaches 0 // Remember last held buttons for pause buffer cheat (minus start so easy frame advance works) - CVarSetInteger("gCheatEasyPauseBufferLastInputs", input->cur.button & ~(BTN_START)); + CVarSetInteger(CVAR_GENERAL("CheatEasyPauseBufferLastInputs"), input->cur.button & ~(BTN_START)); gSaveContext.unk_13EE = gSaveContext.unk_13EA; if (CHECK_BTN_ALL(input->cur.button, BTN_L)) - CVarSetInteger("gPauseTriforce", 1); + CVarSetInteger(CVAR_GENERAL("PauseTriforce"), 1); else - CVarSetInteger("gPauseTriforce", 0); + CVarSetInteger(CVAR_GENERAL("PauseTriforce"), 0); WREG(16) = -175; diff --git a/soh/src/code/z_lib.c b/soh/src/code/z_lib.c index 820256cbb..57f1312dd 100644 --- a/soh/src/code/z_lib.c +++ b/soh/src/code/z_lib.c @@ -201,7 +201,7 @@ void func_80077D10(f32* arg0, s16* arg1, Input* input) { f32 relX = input->rel.stick_x; f32 relY = input->rel.stick_y; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { relX = -input->rel.stick_x; } diff --git a/soh/src/code/z_lifemeter.c b/soh/src/code/z_lifemeter.c index da4c16a51..3cb9d4715 100644 --- a/soh/src/code/z_lifemeter.c +++ b/soh/src/code/z_lifemeter.c @@ -176,10 +176,10 @@ void HealthMeter_Update(PlayState* play) { s16 gFactor; s16 bFactor; - Top_LM_Margin = CVarGetInteger("gHUDMargin_T", 0); - Left_LM_Margin = CVarGetInteger("gHUDMargin_L", 0); - Right_LM_Margin = CVarGetInteger("gHUDMargin_R", 0); - Bottom_LM_Margin = CVarGetInteger("gHUDMargin_B", 0); + Top_LM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + Left_LM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + Right_LM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + Bottom_LM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); Color_RGB8 mainColor = {HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B}; if (CVarGetInteger(CVAR_COSMETIC("Consumable.Hearts.Changed"), 0)) { @@ -336,20 +336,20 @@ static void* sHeartDDTextures[] = { s16 getHealthMeterXOffset() { s16 X_Margins; - if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) + if (CVarGetInteger(CVAR_COSMETIC("HUD.Hearts.UseMargins"), 0) != 0) X_Margins = Left_LM_Margin; else X_Margins = 0; - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 1) {//Anchor Left - return OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 1) {//Anchor Left + return OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 2) {//Anchor Right X_Margins = Right_LM_Margin; - return OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 3) {//Anchor None - return CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+70.0f;; - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 4) {//Hidden + return OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 3) {//Anchor None + return CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+70.0f;; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 4) {//Hidden return -9999; } } else { @@ -359,15 +359,15 @@ s16 getHealthMeterXOffset() { s16 getHealthMeterYOffset() { s16 Y_Margins; - if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) + if (CVarGetInteger(CVAR_COSMETIC("HUD.Hearts.UseMargins"), 0) != 0) Y_Margins = (Top_LM_Margin*-1); else Y_Margins = 0; f32 HeartsScale = 0.7f; - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { - HeartsScale = CVarGetFloat(CVAR_COSMETIC("HeartsCount.Scale"), 0.7f); - return CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) != 0) { + HeartsScale = CVarGetFloat(CVAR_COSMETIC("HUD.HeartsCount.Scale"), 0.7f); + return CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); } else { return 0.0f+Y_Margins; } @@ -397,8 +397,8 @@ void HealthMeter_Draw(PlayState* play) { u8* curBgImgLoaded = NULL; s32 ddHeartCountMinusOne = gSaveContext.isDoubleDefenseAcquired ? totalHeartCount - 1 : -1; f32 HeartsScale = 0.7f; - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { - HeartsScale = CVarGetFloat(CVAR_COSMETIC("HeartsCount.Scale"), 0.7f); + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) != 0) { + HeartsScale = CVarGetFloat(CVAR_COSMETIC("HUD.HeartsCount.Scale"), 0.7f); } static u32 epoch = 0; epoch++; @@ -413,7 +413,7 @@ void HealthMeter_Draw(PlayState* play) { /* s16 X_Margins; s16 Y_Margins; - if (CVarGetInteger(CVAR_COSMETIC("Hearts.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Hearts.UseMargins"), 0) != 0) { X_Margins = Left_LM_Margin; Y_Margins = (Top_LM_Margin*-1); } else { @@ -422,16 +422,16 @@ void HealthMeter_Draw(PlayState* play) { } s16 PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins; s16 PosY_original = 0.0f+Y_Margins; - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) != 0) { - offsetY = CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); - if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 1) {//Anchor Left - offsetX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) != 0) { + offsetY = CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosY"), 0)+Y_Margins+(HeartsScale*15); + if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 1) {//Anchor Left + offsetX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 2) {//Anchor Right X_Margins = Right_LM_Margin; - offsetX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+X_Margins+70.0f); - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 3) {//Anchor None - offsetX = CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosX"), 0)+70.0f; - } else if (CVarGetInteger(CVAR_COSMETIC("HeartsCount.PosType"), 0) == 4) {//Hidden + offsetX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+X_Margins+70.0f); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 3) {//Anchor None + offsetX = CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosX"), 0)+70.0f; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.HeartsCount.PosType"), 0) == 4) {//Hidden offsetX = -9999; } } else { @@ -626,7 +626,7 @@ void HealthMeter_Draw(PlayState* play) { } offsetX += 10.0f; - s32 lineLength = CVarGetInteger(CVAR_COSMETIC("Hearts.LineLength"), 10); + s32 lineLength = CVarGetInteger(CVAR_COSMETIC("HUD.Hearts.LineLength"), 10); if (lineLength != 0 && (i+1)%lineLength == 0) { offsetX = PosX_anchor; offsetY += 10.0f; diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index abee561aa..6cf1dcc34 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -615,8 +615,8 @@ void Minimap_DrawCompassIcons(PlayState* play) { } s16 X_Margins_Minimap; s16 Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; Y_Margins_Minimap = Bottom_MM_Margin; } else { X_Margins_Minimap = 0; @@ -652,32 +652,32 @@ void Minimap_DrawCompassIcons(PlayState* play) { tempX = player->actor.world.pos.x; tempZ = player->actor.world.pos.z; - tempX /= R_COMPASS_SCALE_X * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + tempX /= R_COMPASS_SCALE_X * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); tempZ /= R_COMPASS_SCALE_Y; - s16 tempXOffset = R_COMPASS_OFFSET_X + (CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset : 0); - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + s16 tempXOffset = R_COMPASS_OFFSET_X + (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? mirrorOffset : 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None Matrix_Translate( - (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); } Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY); Matrix_RotateX(-1.6f, MTXMODE_APPLY); - tempX = ((0x7FFF - player->actor.shape.rot.y) / 0x400) * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + tempX = ((0x7FFF - player->actor.shape.rot.y) / 0x400) * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); Matrix_RotateY(tempX / 10.0f, MTXMODE_APPLY); gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); @@ -688,30 +688,30 @@ void Minimap_DrawCompassIcons(PlayState* play) { //Player map entry (red arrow) tempX = sPlayerInitialPosX; tempZ = sPlayerInitialPosZ; - tempX /= R_COMPASS_SCALE_X * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + tempX /= R_COMPASS_SCALE_X * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); tempZ /= R_COMPASS_SCALE_Y; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; Matrix_Translate( - OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10)) / 10.0f), - (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None + OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10)) / 10.0f), + (R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None Matrix_Translate( - (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)*10) / 10.0f), - (R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); + (tempXOffset + tempX + (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)*10) / 10.0f), + (R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); } Matrix_Scale(VREG(9) / 100.0f, VREG(9) / 100.0f, VREG(9) / 100.0f, MTXMODE_APPLY); Matrix_RotateX(VREG(52) / 10.0f, MTXMODE_APPLY); - Matrix_RotateY((sPlayerInitialDirection * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1)) / 10.0f, MTXMODE_APPLY); + Matrix_RotateY((sPlayerInitialDirection * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1)) / 10.0f, MTXMODE_APPLY); gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); @@ -735,15 +735,15 @@ void Minimap_Draw(PlayState* play) { // If any of these CVars are enabled, disable toggling the minimap with L, unless gEnableMapToggle is set bool enableMapToggle = - !(CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) || CVarGetInteger(CVAR_CHEAT("MoonJumpOnL"), 0) || CVarGetInteger("gTurboOnL", 0)) || - CVarGetInteger("gEnableMapToggle", 0); + !(CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0) || CVarGetInteger(CVAR_CHEAT("MoonJumpOnL"), 0)) || + CVarGetInteger(CVAR_DEVELOPER_TOOLS("EnableMapToggle"), 0); if (play->pauseCtx.state < 4) { //Minimap margins s16 X_Margins_Minimap; s16 Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 0) {X_Margins_Minimap = Right_MM_Margin;}; Y_Margins_Minimap = Bottom_MM_Margin; } else { X_Margins_Minimap = 0; @@ -761,7 +761,7 @@ void Minimap_Draw(PlayState* play) { case SCENE_SHADOW_TEMPLE: case SCENE_BOTTOM_OF_THE_WELL: case SCENE_ICE_CAVERN: - if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 4) { // Not Hidden + if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineLERP(OVERLAY_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0); @@ -769,28 +769,28 @@ void Minimap_Draw(PlayState* play) { if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha); - u8 mirrorMode = CVarGetInteger("gMirroredWorld", 0) ? G_TX_MIRROR : G_TX_NOMIRROR; + u8 mirrorMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_I, 96, 85, 0, mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + X_Margins_Minimap); s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - dgnMiniMapY = R_DGN_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)+Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - dgnMiniMapX = OTRGetDimensionFromLeftEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - dgnMiniMapX = OTRGetDimensionFromRightEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None - dgnMiniMapX = CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + dgnMiniMapY = R_DGN_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)+Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + dgnMiniMapX = OTRGetDimensionFromLeftEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + dgnMiniMapX = OTRGetDimensionFromRightEdge(R_DGN_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None + dgnMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } s32 sValue = 0; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary sValue = 96 << 5; } @@ -839,13 +839,13 @@ void Minimap_Draw(PlayState* play) { case SCENE_GORON_CITY: case SCENE_LON_LON_RANCH: case SCENE_OUTSIDE_GANONS_CASTLE: - if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 4) { // Not Hidden + if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha); - u8 mirrorMode = CVarGetInteger("gMirroredWorld", 0) ? G_TX_MIRROR : G_TX_NOMIRROR; + u8 mirrorMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_IA, gMapData->owMinimapWidth[mapIndex], gMapData->owMinimapHeight[mapIndex], 0, mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, @@ -853,21 +853,21 @@ void Minimap_Draw(PlayState* play) { s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + X_Margins_Minimap); s16 oWMiniMapY = R_OW_MINIMAP_Y + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - oWMiniMapY = R_OW_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)+Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - oWMiniMapX = OTRGetDimensionFromLeftEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - oWMiniMapX = OTRGetDimensionFromRightEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None - oWMiniMapX = CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + oWMiniMapY = R_OW_MINIMAP_Y+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)+Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + oWMiniMapX = OTRGetDimensionFromLeftEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + oWMiniMapX = OTRGetDimensionFromRightEdge(R_OW_MINIMAP_X+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None + oWMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } s32 sValue = 0; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary sValue = gMapData->owMinimapWidth[mapIndex] << 5; } @@ -890,7 +890,7 @@ void Minimap_Draw(PlayState* play) { // Then duplicate that and right-align the texture (extra 2 pixels are due to the texture being a 6px left-aligned in a 8px tex) s16 distFromCenter = (R_OW_MINIMAP_X + (gMapData->owMinimapWidth[mapIndex] / 2)) - (origX + (iconSize / 2)); s16 mirrorOffset = distFromCenter * 2 + (iconSize / 2) - 2; - s16 newX = origX + (CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset : 0); + s16 newX = origX + (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? mirrorOffset : 0); // The game authentically uses larger negative values for the entrance icon Y pos value. Normally only the first 12 bits // would be read when the final value is passed into `gSPTextureRectangle`, but our cosmetic hud placements requires using @@ -901,16 +901,16 @@ void Minimap_Draw(PlayState* play) { s16 entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap); s16 entranceY = newY + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - entranceY = newY + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0) + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) { // Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - entranceX = OTRGetRectDimensionFromLeftEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) { // Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) { // Anchor None - entranceX = newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + entranceY = newY + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) { // Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + entranceX = OTRGetRectDimensionFromLeftEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) { // Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) { // Anchor None + entranceX = newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } @@ -934,19 +934,19 @@ void Minimap_Draw(PlayState* play) { } } - s16 origX = CVarGetInteger("gMirroredWorld", 0) ? 256 : 270; + s16 origX = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 256 : 270; s16 entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap); s16 entranceY = 154 + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - entranceY = 154 + Y_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0); - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - entranceX = OTRGetRectDimensionFromLeftEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None - entranceX = origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + entranceY = 154 + Y_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; + entranceX = OTRGetRectDimensionFromLeftEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; + entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None + entranceX = origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } @@ -992,10 +992,10 @@ void Map_Update(PlayState* play) { s16 floor; s16 i; - Top_MM_Margin = CVarGetInteger("gHUDMargin_T", 0); - Left_MM_Margin = CVarGetInteger("gHUDMargin_L", 0); - Right_MM_Margin = CVarGetInteger("gHUDMargin_R", 0); - Bottom_MM_Margin = CVarGetInteger("gHUDMargin_B", 0); + Top_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + Left_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + Right_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + Bottom_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0)) { switch (play->sceneNum) { diff --git a/soh/src/code/z_map_mark.c b/soh/src/code/z_map_mark.c index c9d5d753f..df8ef4464 100644 --- a/soh/src/code/z_map_mark.c +++ b/soh/src/code/z_map_mark.c @@ -113,15 +113,15 @@ void MapMark_DrawForDungeon(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->minimapAlpha); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, interfaceCtx->minimapAlpha); - s32 Top_MC_Margin = CVarGetInteger("gHUDMargin_T", 0); - s32 Left_MC_Margin = CVarGetInteger("gHUDMargin_L", 0); - s32 Right_MC_Margin = CVarGetInteger("gHUDMargin_R", 0); - s32 Bottom_MC_Margin = CVarGetInteger("gHUDMargin_B", 0); + s32 Top_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + s32 Left_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + s32 Right_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + s32 Bottom_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); s32 X_Margins_Minimap_ic; s32 Y_Margins_Minimap_ic; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; Y_Margins_Minimap_ic = Bottom_MC_Margin; } else { X_Margins_Minimap_ic = 0; @@ -141,29 +141,29 @@ void MapMark_DrawForDungeon(PlayState* play) { // The original mark point X originates from the left edge of the map // For mirror mode, we compute the new mark point X by subtracting it from the right side of the // dungeon map and the textures width - s16 markPointX = CVarGetInteger("gMirroredWorld", 0) ? 96 - markPoint->x - width : markPoint->x; + s16 markPointX = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 96 - markPoint->x - width : markPoint->x; //Minimap chest / boss icon const s32 PosX_Minimap_ori = GREG(94) + OTRGetRectDimensionFromRightEdge(markPointX+X_Margins_Minimap_ic) + 204; const s32 PosY_Minimap_ori = GREG(95) + markPoint->y + Y_Margins_Minimap_ic + 140; - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) != 0) { - rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger(CVAR_COSMETIC("Minimap.PosY"), 0)); - if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Left_MC_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 0) { + rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Left_MC_Margin;}; if (play->sceneNum == SCENE_DEKU_TREE || play->sceneNum == SCENE_DODONGOS_CAVERN || play->sceneNum == SCENE_JABU_JABU || play->sceneNum == SCENE_FOREST_TEMPLE || play->sceneNum == SCENE_FIRE_TEMPLE || play->sceneNum == SCENE_WATER_TEMPLE || play->sceneNum == SCENE_SPIRIT_TEMPLE || play->sceneNum == SCENE_SHADOW_TEMPLE || play->sceneNum == SCENE_BOTTOM_OF_THE_WELL || play->sceneNum == SCENE_ICE_CAVERN) { - rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); + rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); } else { - rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); + rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); } - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; - rectLeft = OTRGetRectDimensionFromRightEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 3) {//Anchor None - rectLeft = markPointX+CVarGetInteger(CVAR_COSMETIC("Minimap.PosX"), 0)+204+X_Margins_Minimap_ic; - } else if (CVarGetInteger(CVAR_COSMETIC("Minimap.PosType"), 0) == 4) {//Hidden + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) {X_Margins_Minimap_ic = Right_MC_Margin;}; + rectLeft = OTRGetRectDimensionFromRightEdge(markPointX+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+204+X_Margins_Minimap_ic); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 3) {//Anchor None + rectLeft = markPointX+CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)+204+X_Margins_Minimap_ic; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == 4) {//Hidden rectLeft = -9999; } } else { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 3a77fb35f..c6b1415f6 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -187,7 +187,7 @@ void Message_HandleChoiceSelection(PlayState* play, u8 numChoices) { static s16 sAnalogStickHeld = false; MessageContext* msgCtx = &play->msgCtx; Input* input = &play->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if ((input->rel.stick_y >= 30 && !sAnalogStickHeld) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { sAnalogStickHeld = true; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 9b8f85042..d6d84486d 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1539,7 +1539,7 @@ void Inventory_SwapAgeEquipment(void) { // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { + if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { Flags_SetInfTable(INFTABLE_SWORDLESS); gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; } @@ -1554,7 +1554,7 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) { + if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; @@ -1629,7 +1629,7 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger("gSwitchTimeline", 0)) && + if ((CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) && (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { Flags_SetInfTable(INFTABLE_SWORDLESS); if (gSaveContext.childEquips.equipment == 0) { @@ -1640,7 +1640,7 @@ void Inventory_SwapAgeEquipment(void) { } } } - CVarSetInteger("gSwitchTimeline", 0); + CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 0); shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; if (shieldEquipValue != 0) { shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; @@ -3495,7 +3495,7 @@ void Interface_UpdateMagicBar(PlayState* play) { (msgCtx->msgMode == MSGMODE_NONE) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && (play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play)) { bool hasLens = false; - for (int buttonIndex = 1; buttonIndex < (CVarGetInteger("gDpadEquips", 0) != 0) ? ARRAY_COUNT(gSaveContext.equips.buttonItems) : 4; buttonIndex++) { + for (int buttonIndex = 1; buttonIndex < (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) ? ARRAY_COUNT(gSaveContext.equips.buttonItems) : 4; buttonIndex++) { if (gSaveContext.equips.buttonItems[buttonIndex] == ITEM_LENS) { hasLens = true; break; @@ -3616,7 +3616,7 @@ void Interface_DrawMagicBar(PlayState* play) { if (gSaveContext.magicLevel != 0) { s16 X_Margins; s16 Y_Margins; - if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.UseMargins"), 0) != 0) { X_Margins = Left_HUD_Margin; Y_Margins = (Top_HUD_Margin*-1); } else { @@ -3634,40 +3634,40 @@ void Interface_DrawMagicBar(PlayState* play) { s16 rMagicBarX; s16 PosX_MidEnd; s16 rMagicFillX; - s32 lineLength = CVarGetInteger(CVAR_COSMETIC("Hearts.LineLength"), 10); - if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) != 0) { - magicBarY = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosY"), 0)+Y_Margins; - if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) {X_Margins = Left_HUD_Margin;}; - PosX_Start = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); - rMagicBarX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); - PosX_MidEnd = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); - rMagicFillX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); - } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("MagicBar.UseMargins"), 0) != 0) {X_Margins = Right_HUD_Margin;}; - PosX_Start = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); - rMagicBarX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins); - PosX_MidEnd = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); - rMagicFillX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8); - } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 3) {//Anchor None - PosX_Start = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins; - rMagicBarX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins; - PosX_MidEnd = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8; - rMagicFillX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0)+X_Margins+8; - } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 4) {//hidden + s32 lineLength = CVarGetInteger(CVAR_COSMETIC("HUD.Hearts.LineLength"), 10); + if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) != 0) { + magicBarY = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosY"), 0)+Y_Margins; + if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.UseMargins"), 0) != 0) {X_Margins = Left_HUD_Margin;}; + PosX_Start = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins); + rMagicBarX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins); + PosX_MidEnd = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8); + rMagicFillX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.UseMargins"), 0) != 0) {X_Margins = Right_HUD_Margin;}; + PosX_Start = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins); + rMagicBarX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins); + PosX_MidEnd = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8); + rMagicFillX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) == 3) {//Anchor None + PosX_Start = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins; + rMagicBarX = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins; + PosX_MidEnd = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8; + rMagicFillX = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0)+X_Margins+8; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) == 4) {//hidden PosX_Start = -9999; rMagicBarX = -9999; PosX_MidEnd = -9999; rMagicFillX = -9999; - } else if (CVarGetInteger(CVAR_COSMETIC("MagicBar.PosType"), 0) == 5) {//Anchor To life meter + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosType"), 0) == 5) {//Anchor To life meter magicBarY = R_MAGIC_BAR_SMALL_Y-2 + magicDrop*(lineLength == 0 ? 0 : (gSaveContext.healthCapacity-1)/(0x10*lineLength)) + - CVarGetInteger(CVAR_COSMETIC("MagicBar.PosY"), 0) + getHealthMeterYOffset(); - s16 xPushover = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_BAR_X-1; + CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosY"), 0) + getHealthMeterYOffset(); + s16 xPushover = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_BAR_X-1; PosX_Start = xPushover; rMagicBarX = xPushover; PosX_MidEnd = xPushover+8; - rMagicFillX = CVarGetInteger(CVAR_COSMETIC("MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_FILL_X-1; + rMagicFillX = CVarGetInteger(CVAR_COSMETIC("HUD.MagicBar.PosX"), 0) + getHealthMeterXOffset() + R_MAGIC_FILL_X-1; } } else { if ((gSaveContext.healthCapacity-1)/0x10 >= lineLength && lineLength != 0) { @@ -3780,18 +3780,18 @@ void Interface_DrawEnemyHealthBar(TargetContext* targetCtx, PlayState* play) { Color_RGBA8 healthbar_border = { 255, 255, 255, 255 }; s16 healthbar_fillWidth = 64; s16 healthbar_actorOffset = 40; - s32 healthbar_offsetX = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosX"), 0); - s32 healthbar_offsetY = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosY"), 0); - s8 anchorType = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarPosType"), ENEMYHEALTH_ANCHOR_ACTOR); + s32 healthbar_offsetX = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.PosX"), 0); + s32 healthbar_offsetY = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.PosY"), 0); + s8 anchorType = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.PosType"), ENEMYHEALTH_ANCHOR_ACTOR); - if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Changed"), 0)) { - healthbar_red = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBar.Value"), healthbar_red); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar..Changed"), 0)) { + healthbar_red = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBar..Value"), healthbar_red); } if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBorder.Changed"), 0)) { healthbar_border = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBorder.Value"), healthbar_border); } - if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Changed"), 0)) { - healthbar_fillWidth = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBarWidth.Value"), healthbar_fillWidth); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Changed"), 0)) { + healthbar_fillWidth = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Value"), healthbar_fillWidth); } OPEN_DISPS(play->state.gfxCtx); @@ -3809,7 +3809,7 @@ void Interface_DrawEnemyHealthBar(TargetContext* targetCtx, PlayState* play) { func_8002BE04(play, &targetCtx->targetCenterPos, &projTargetCenter, &projTargetCappedInvW); projTargetCenter.x = (SCREEN_WIDTH / 2) * (projTargetCenter.x * projTargetCappedInvW); - projTargetCenter.x = projTargetCenter.x * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + projTargetCenter.x = projTargetCenter.x * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); projTargetCenter.x = CLAMP(projTargetCenter.x, (-SCREEN_WIDTH / 2) + halfBarWidth, (SCREEN_WIDTH / 2) - halfBarWidth); @@ -4010,12 +4010,12 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_BtnB; s16 BBtn_Size = 32; int BBtnScaled = BBtn_Size * 0.95f; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { - BBtnScaled = BBtn_Size * CVarGetFloat(CVAR_COSMETIC("BButton.Scale"), 0.95f); + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) != 0) { + BBtnScaled = BBtn_Size * CVarGetFloat(CVAR_COSMETIC("HUD.BButton.Scale"), 0.95f); } int BBtn_factor = (1 << 10) * BBtn_Size / BBtnScaled; - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; @@ -4025,17 +4025,17 @@ void Interface_DrawItemButtons(PlayState* play) { s16 PosY_BtnB_ori = R_ITEM_BTN_Y(0)+Y_Margins_BtnB; s16 PosX_BtnB; s16 PosY_BtnB; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { - PosY_BtnB = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - PosX_BtnB = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - PosX_BtnB = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None - PosX_BtnB = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) != 0) { + PosY_BtnB = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosY"), 0)+Y_Margins_BtnB; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + PosX_BtnB = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + PosX_BtnB = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 3) {//Anchor None + PosX_BtnB = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 4) {//Hidden PosX_BtnB = -9999; } } else { @@ -4045,8 +4045,8 @@ void Interface_DrawItemButtons(PlayState* play) { //Start Button s16 X_Margins_StartBtn; s16 Y_Margins_StartBtn; - if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) == 0) { X_Margins_StartBtn = Right_HUD_Margin; }; Y_Margins_StartBtn = Top_HUD_Margin*-1; @@ -4057,8 +4057,8 @@ void Interface_DrawItemButtons(PlayState* play) { s16 StartBtn_Icon_H = 32; s16 StartBtn_Icon_W = 32; float Start_BTN_Scale = 0.75f; - if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) != 0) { - Start_BTN_Scale = CVarGetFloat(CVAR_COSMETIC("StartButton.Scale"), 0.75f); + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) != 0) { + Start_BTN_Scale = CVarGetFloat(CVAR_COSMETIC("HUD.StartButton.Scale"), 0.75f); } int StartBTN_H_Scaled = StartBtn_Icon_H * Start_BTN_Scale; int StartBTN_W_Scaled = StartBtn_Icon_W * Start_BTN_Scale; @@ -4070,17 +4070,17 @@ void Interface_DrawItemButtons(PlayState* play) { s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT(); s16 PosX_StartBtn; s16 PosY_StartBtn; - if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) != 0) { - PosY_StartBtn = CVarGetInteger(CVAR_COSMETIC("StartButton.PosY"), 0)-(Start_BTN_Scale*13)+Y_Margins_StartBtn; - if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;}; - PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); - } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;}; - PosX_StartBtn = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); - } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 3) {//Anchor None - PosX_StartBtn = CVarGetInteger(CVAR_COSMETIC("StartButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("StartButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) != 0) { + PosY_StartBtn = CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosY"), 0)-(Start_BTN_Scale*13)+Y_Margins_StartBtn; + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;}; + PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.UseMargins"), 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;}; + PosX_StartBtn = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosX"), 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) == 3) {//Anchor None + PosX_StartBtn = CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.StartButton.PosType"), 0) == 4) {//Hidden PosX_StartBtn = -9999; } } else { @@ -4100,29 +4100,29 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_CR; s16 Y_Margins_CU; s16 Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 0) {X_Margins_CU = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) == 0) {X_Margins_CU = Right_HUD_Margin;}; Y_Margins_CU = (Top_HUD_Margin*-1); } else { X_Margins_CU = 0; Y_Margins_CU = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4140,23 +4140,23 @@ void Interface_DrawItemButtons(PlayState* play) { s16 C_Down_BTN_Pos[2]; //C button Left s16 C_Left_BTN_Size = 32; - float CLeftScale = CVarGetFloat(CVAR_COSMETIC("CLeftButton.Scale"), 0.87f); + float CLeftScale = CVarGetFloat(CVAR_COSMETIC("HUD.CLeftButton.Scale"), 0.87f); int CLeftScaled = C_Left_BTN_Size * 0.87f; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { CLeftScaled = C_Left_BTN_Size * CLeftScale; } int CLeft_factor = (1 << 10) * C_Left_BTN_Size / CLeftScaled; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { - C_Left_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - C_Left_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - C_Left_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None - C_Left_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { + C_Left_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + C_Left_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + C_Left_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 3) {//Anchor None + C_Left_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 4) {//Hidden C_Left_BTN_Pos[0] = -9999; } } else { @@ -4165,23 +4165,23 @@ void Interface_DrawItemButtons(PlayState* play) { } //C button Right s16 C_Right_BTN_Size = 32; - float CRightScale = CVarGetFloat(CVAR_COSMETIC("CRightButton.Scale"), 0.87f); + float CRightScale = CVarGetFloat(CVAR_COSMETIC("HUD.CRightButton.Scale"), 0.87f); int CRightScaled = C_Right_BTN_Size * 0.87f; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { CRightScaled = C_Right_BTN_Size * CRightScale; } int CRight_factor = (1 << 10) * C_Right_BTN_Size / CRightScaled; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { - C_Right_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - C_Right_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - C_Right_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None - C_Right_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { + C_Right_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + C_Right_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + C_Right_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 3) {//Anchor None + C_Right_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 4) {//Hidden C_Right_BTN_Pos[0] = -9999; } } else { @@ -4191,22 +4191,22 @@ void Interface_DrawItemButtons(PlayState* play) { //C Button Up s16 C_Up_BTN_Size = 32; int CUpScaled = C_Up_BTN_Size * 0.5f; - float CUpScale = CVarGetFloat(CVAR_COSMETIC("CUpButton.Scale"), 0.5f); - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) != 0) { + float CUpScale = CVarGetFloat(CVAR_COSMETIC("HUD.CUpButton.Scale"), 0.5f); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) != 0) { CUpScaled = C_Up_BTN_Size * CUpScale; } int CUp_factor = (1 << 10) * C_Up_BTN_Size / CUpScaled; - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) != 0) { - C_Up_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CUpButton.PosY"), 0)+Y_Margins_CU; - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Left_HUD_Margin;}; - C_Up_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0)+X_Margins_CU); - } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Right_HUD_Margin;}; - C_Up_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0)+X_Margins_CU); - } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 3) {//Anchor None - C_Up_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CUpButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CUpButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) != 0) { + C_Up_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosY"), 0)+Y_Margins_CU; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Left_HUD_Margin;}; + C_Up_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosX"), 0)+X_Margins_CU); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.UseMargins"), 0) != 0) {X_Margins_CU = Right_HUD_Margin;}; + C_Up_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosX"), 0)+X_Margins_CU); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) == 3) {//Anchor None + C_Up_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.PosType"), 0) == 4) {//Hidden C_Up_BTN_Pos[0] = -9999; } } else { @@ -4215,24 +4215,24 @@ void Interface_DrawItemButtons(PlayState* play) { } //C Button down s16 C_Down_BTN_Size = 32; - float CDownScale = CVarGetFloat(CVAR_COSMETIC("CDownButton.Scale"), 0.87f); - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) { + float CDownScale = CVarGetFloat(CVAR_COSMETIC("HUD.CDownButton.Scale"), 0.87f); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) { CDownScale = 0.87f; } int CDownScaled = C_Down_BTN_Size * CDownScale; int CDown_factor = (1 << 10) * C_Down_BTN_Size / CDownScaled; int PositionAdjustment = CDownScaled/2; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { - C_Down_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - C_Down_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - C_Down_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None - C_Down_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) != 0) { + C_Down_BTN_Pos[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + C_Down_BTN_Pos[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + C_Down_BTN_Pos[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 3) {//Anchor None + C_Down_BTN_Pos[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 4) {//Hidden C_Down_BTN_Pos[0] = -9999; } } else { @@ -4360,22 +4360,22 @@ void Interface_DrawItemButtons(PlayState* play) { s16 Y_Margins_CL; s16 Y_Margins_CR; s16 Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; @@ -4393,17 +4393,17 @@ void Interface_DrawItemButtons(PlayState* play) { }; s16 ItemIconPos[3][2]; //(X,Y) //C button Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4411,17 +4411,17 @@ void Interface_DrawItemButtons(PlayState* play) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C Button down - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4429,17 +4429,17 @@ void Interface_DrawItemButtons(PlayState* play) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C button Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4489,36 +4489,36 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; Y_Margins_CD = 0; } - if (CVarGetInteger("gDPadUseMargins", 0) != 0) { - if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; Y_Margins_DPad_Items = (Top_HUD_Margin*-1); } else { X_Margins_DPad_Items = 0; @@ -4552,29 +4552,29 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { }; //(X,Y) Used with custom position to place it properly. s16 ItemIconPos[8][2]; //(X,Y) //DPadItems - if (CVarGetInteger("gDPadPosType", 0) != 0) { - ItemIconPos[4][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up - ItemIconPos[5][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down - ItemIconPos[6][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left - ItemIconPos[7][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right - if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; - ItemIconPos[4][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - ItemIconPos[5][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - ItemIconPos[6][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - ItemIconPos[7][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; - ItemIconPos[4][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - ItemIconPos[5][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - ItemIconPos[6][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - ItemIconPos[7][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None - ItemIconPos[4][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[0][0]; - ItemIconPos[5][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[1][0]; - ItemIconPos[6][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[2][0]; - ItemIconPos[7][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[3][0]; - } else if (CVarGetInteger("gDPadPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) != 0) { + ItemIconPos[4][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up + ItemIconPos[5][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down + ItemIconPos[6][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left + ItemIconPos[7][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; + ItemIconPos[4][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + ItemIconPos[5][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + ItemIconPos[6][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + ItemIconPos[7][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + ItemIconPos[4][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + ItemIconPos[5][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + ItemIconPos[6][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + ItemIconPos[7][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 3) {//Anchor None + ItemIconPos[4][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[0][0]; + ItemIconPos[5][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[1][0]; + ItemIconPos[6][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[2][0]; + ItemIconPos[7][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[3][0]; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 4) {//Hidden ItemIconPos[4][0] = -9999; ItemIconPos[5][0] = -9999; ItemIconPos[6][0] = -9999; @@ -4591,17 +4591,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[7][1] = ItemIconPos_ori[7][1]; } //B Button - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosY"), 0)+Y_Margins_BtnB; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4609,17 +4609,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C button Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4627,17 +4627,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C Button down - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4645,17 +4645,17 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { ItemIconPos[2][1] = ItemIconPos_ori[2][1]; } //C button Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { - ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { + ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[3][0] = -9999; } } else { @@ -4698,36 +4698,36 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; Y_Margins_CD = 0; } - if (CVarGetInteger("gDPadUseMargins", 0) != 0) { - if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; Y_Margins_DPad_Items = (Top_HUD_Margin*-1); } else { X_Margins_DPad_Items = 0; @@ -4751,29 +4751,29 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { {23,19},//Right }; //(X,Y) Used with custom position to place it properly. //DPadItems - if (CVarGetInteger("gDPadPosType", 0) != 0) { - ItemIconPos[4][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up - ItemIconPos[5][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down - ItemIconPos[6][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left - ItemIconPos[7][1] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right - if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; - ItemIconPos[4][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - ItemIconPos[5][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - ItemIconPos[6][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - ItemIconPos[7][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; - ItemIconPos[4][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - ItemIconPos[5][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - ItemIconPos[6][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - ItemIconPos[7][0] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None - ItemIconPos[4][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[0][0]; - ItemIconPos[5][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[1][0]; - ItemIconPos[6][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[2][0]; - ItemIconPos[7][0] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[3][0]; - } else if (CVarGetInteger("gDPadPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) != 0) { + ItemIconPos[4][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up + ItemIconPos[5][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down + ItemIconPos[6][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left + ItemIconPos[7][1] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; + ItemIconPos[4][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + ItemIconPos[5][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + ItemIconPos[6][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + ItemIconPos[7][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + ItemIconPos[4][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + ItemIconPos[5][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + ItemIconPos[6][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + ItemIconPos[7][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 3) {//Anchor None + ItemIconPos[4][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[0][0]; + ItemIconPos[5][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[1][0]; + ItemIconPos[6][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[2][0]; + ItemIconPos[7][0] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[3][0]; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 4) {//Hidden ItemIconPos[4][0] = -9999; ItemIconPos[5][0] = -9999; ItemIconPos[6][0] = -9999; @@ -4792,17 +4792,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { //B Button s16 PosX_adjust = 1; s16 PosY_adjust = 17; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { - ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB+PosY_adjust; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; - ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+PosX_adjust; - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) != 0) { + ItemIconPos[0][1] = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosY"), 0)+Y_Margins_BtnB+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Left_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB = Right_HUD_Margin;}; + ItemIconPos[0][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[0][0] = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 4) {//Hidden ItemIconPos[0][0] = -9999; } } else { @@ -4810,17 +4810,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[0][1] = ItemIconPos_ori[0][1]; } //C button Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { - ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL+PosY_adjust; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+PosX_adjust; - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { + ItemIconPos[1][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosY"), 0)+Y_Margins_CL+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + ItemIconPos[1][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[1][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 4) {//Hidden ItemIconPos[1][0] = -9999; } } else { @@ -4828,17 +4828,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[1][1] = ItemIconPos_ori[1][1]; } //C Button down - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { - ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD+PosY_adjust; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+PosX_adjust; - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) != 0) { + ItemIconPos[2][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosY"), 0)+Y_Margins_CD+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + ItemIconPos[2][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[2][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 4) {//Hidden ItemIconPos[2][0] = -9999; } } else { @@ -4846,17 +4846,17 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ItemIconPos[2][1] = ItemIconPos_ori[2][1]; } //C button Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { - ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR+PosY_adjust; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None - ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+PosX_adjust; - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { + ItemIconPos[3][1] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosY"), 0)+Y_Margins_CR+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + ItemIconPos[3][0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 3) {//Anchor None + ItemIconPos[3][0] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 4) {//Hidden ItemIconPos[3][0] = -9999; } } else { @@ -5185,8 +5185,8 @@ void Interface_Draw(PlayState* play) { //Rupee icon & counter s16 X_Margins_RC; s16 Y_Margins_RC; - if (CVarGetInteger("gRCUseMargins", 0) != 0) { - if (CVarGetInteger("gRCPosType", 0) == 0) {X_Margins_RC = Left_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 0) {X_Margins_RC = Left_HUD_Margin;}; Y_Margins_RC = Bottom_HUD_Margin; } else { X_Margins_RC = 0; @@ -5196,17 +5196,17 @@ void Interface_Draw(PlayState* play) { s16 PosY_RC_ori = 206+Y_Margins_RC; s16 PosX_RC; s16 PosY_RC; - if (CVarGetInteger("gRCPosType", 0) != 0) { - PosY_RC = CVarGetInteger("gRCPosY", 0)+Y_Margins_RC; - if (CVarGetInteger("gRCPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gRCUseMargins", 0) != 0) {X_Margins_RC = Left_HUD_Margin;}; - PosX_RC = OTRGetDimensionFromLeftEdge(CVarGetInteger("gRCPosX", 0)+X_Margins_RC); - } else if (CVarGetInteger("gRCPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gRCUseMargins", 0) != 0) {X_Margins_RC = Right_HUD_Margin;}; - PosX_RC = OTRGetDimensionFromRightEdge(CVarGetInteger("gRCPosX", 0)+X_Margins_RC); - } else if (CVarGetInteger("gRCPosType", 0) == 3) {//Anchor None - PosX_RC = CVarGetInteger("gRCPosX", 0); - } else if (CVarGetInteger("gRCPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) != 0) { + PosY_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosY"), 0)+Y_Margins_RC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Left_HUD_Margin;}; + PosX_RC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Right_HUD_Margin;}; + PosX_RC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 3) {//Anchor None + PosX_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 4) {//Hidden PosX_RC = -9999; } } else { @@ -5237,8 +5237,8 @@ void Interface_Draw(PlayState* play) { if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] >= 0) { s16 X_Margins_SKC; s16 Y_Margins_SKC; - if (CVarGetInteger("gSKCUseMargins", 0) != 0) { - if (CVarGetInteger("gSKCPosType", 0) == 0) {X_Margins_SKC = Left_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 0) {X_Margins_SKC = Left_HUD_Margin;}; Y_Margins_SKC = Bottom_HUD_Margin; } else { X_Margins_SKC = 0; @@ -5248,17 +5248,17 @@ void Interface_Draw(PlayState* play) { s16 PosY_SKC_ori = 190+Y_Margins_SKC; s16 PosX_SKC; s16 PosY_SKC; - if (CVarGetInteger("gSKCPosType", 0) != 0) { - PosY_SKC = CVarGetInteger("gSKCPosY", 0)+Y_Margins_SKC; - if (CVarGetInteger("gSKCPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gSKCUseMargins", 0) != 0) {X_Margins_SKC = Left_HUD_Margin;}; - PosX_SKC = OTRGetDimensionFromLeftEdge(CVarGetInteger("gSKCPosX", 0)+X_Margins_SKC); - } else if (CVarGetInteger("gSKCPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gSKCUseMargins", 0) != 0) {X_Margins_SKC = Right_HUD_Margin;}; - PosX_SKC = OTRGetDimensionFromRightEdge(CVarGetInteger("gSKCPosX", 0)+X_Margins_SKC); - } else if (CVarGetInteger("gSKCPosType", 0) == 3) {//Anchor None - PosX_SKC = CVarGetInteger("gSKCPosX", 0); - } else if (CVarGetInteger("gSKCPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) != 0) { + PosY_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosY"), 0)+Y_Margins_SKC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Left_HUD_Margin;}; + PosX_SKC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Right_HUD_Margin;}; + PosX_SKC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 3) {//Anchor None + PosX_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 4) {//Hidden PosX_SKC = -9999; } } else { @@ -5357,11 +5357,11 @@ void Interface_Draw(PlayState* play) { Minimap_Draw(play); if ((R_PAUSE_MENU_MODE != 2) && (R_PAUSE_MENU_MODE != 3)) { - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { gSPMatrix(OVERLAY_DISP++, interfaceCtx->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); } func_8002C124(&play->actorCtx.targetCtx, play); // Draw Z-Target - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { gSPMatrix(OVERLAY_DISP++, interfaceCtx->view.projectionPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); } @@ -5421,24 +5421,24 @@ void Interface_Draw(PlayState* play) { s16 BbtnPosY; s16 X_Margins_BtnB_label; s16 Y_Margins_BtnB_label; - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; Y_Margins_BtnB_label = (Top_HUD_Margin*-1); } else { X_Margins_BtnB_label = 0; Y_Margins_BtnB_label = 0; } - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) != 0) { - BbtnPosY = CVarGetInteger(CVAR_COSMETIC("BButton.PosY"), 0)+Y_Margins_BtnB_label+PosY_adjust; - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Left_HUD_Margin;}; - BbtnPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; - BbtnPosX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 3) {//Anchor None - BbtnPosX = CVarGetInteger(CVAR_COSMETIC("BButton.PosX"), 0)+PosX_adjust; - } else if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) != 0) { + BbtnPosY = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosY"), 0)+Y_Margins_BtnB_label+PosY_adjust; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Left_HUD_Margin;}; + BbtnPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) {X_Margins_BtnB_label = Right_HUD_Margin;}; + BbtnPosX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+X_Margins_BtnB_label+PosX_adjust); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 3) {//Anchor None + BbtnPosX = CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosX"), 0)+PosX_adjust; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 4) {//Hidden BbtnPosX = -9999; } } else { @@ -5500,7 +5500,7 @@ void Interface_Draw(PlayState* play) { Interface_DrawAmmoCount(play, 3, interfaceCtx->cRightAlpha); } - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { // DPad is only greyed-out when all 4 DPad directions are too uint16_t dpadAlpha = MAX(MAX(MAX(interfaceCtx->dpadUpAlpha, interfaceCtx->dpadDownAlpha), interfaceCtx->dpadLeftAlpha), @@ -5511,24 +5511,24 @@ void Interface_Draw(PlayState* play) { s16 DpadPosY; s16 X_Margins_Dpad; s16 Y_Margins_Dpad; - if (CVarGetInteger("gDPadUseMargins", 0) != 0) { - if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_Dpad = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 0) {X_Margins_Dpad = Right_HUD_Margin;}; Y_Margins_Dpad = (Top_HUD_Margin*-1); } else { Y_Margins_Dpad = 0; X_Margins_Dpad = 0; } - if (CVarGetInteger("gDPadPosType", 0) != 0) { - DpadPosY = CVarGetInteger("gDPadPosY", 0)+Y_Margins_Dpad; - if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Left_HUD_Margin;}; - DpadPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); - } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Right_HUD_Margin;}; - DpadPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); - } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None - DpadPosX = CVarGetInteger("gDPadPosX", 0); - } else if (CVarGetInteger("gDPadPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) != 0) { + DpadPosY = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_Dpad; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_Dpad = Left_HUD_Margin;}; + DpadPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_Dpad); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_Dpad = Right_HUD_Margin;}; + DpadPosX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_Dpad); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 3) {//Anchor None + DpadPosX = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 4) {//Hidden DpadPosX = -9999; } } else { @@ -5597,7 +5597,7 @@ void Interface_Draw(PlayState* play) { Gfx_SetupDL_42Overlay(play->state.gfxCtx); s16 X_Margins_BtnA; s16 Y_Margins_BtnA; - if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.UseMargins"), 0) != 0) { X_Margins_BtnA = Right_HUD_Margin; Y_Margins_BtnA = (Top_HUD_Margin*-1); } else { @@ -5612,21 +5612,21 @@ void Interface_Draw(PlayState* play) { s16 PosY_BtnA; s16 rAIconX; s16 rAIconY; - if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) != 0) { - PosY_BtnA = CVarGetInteger(CVAR_COSMETIC("AButton.PosY"), 0)+Y_Margins_BtnA; + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosType"), 0) != 0) { + PosY_BtnA = CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosY"), 0)+Y_Margins_BtnA; rAIconY = 98.0f - PosY_BtnA; - if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Left_HUD_Margin;}; - PosX_BtnA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); - rAIconX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); - } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Right_HUD_Margin;}; - PosX_BtnA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); - rAIconX= OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0)+X_Margins_BtnA); - } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 3) {//Anchor None - PosX_BtnA = CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0); - rAIconX = CVarGetInteger(CVAR_COSMETIC("AButton.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("AButton.PosType"), 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Left_HUD_Margin;}; + PosX_BtnA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0)+X_Margins_BtnA); + rAIconX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0)+X_Margins_BtnA); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.UseMargins"), 0) != 0) {X_Margins_BtnA = Right_HUD_Margin;}; + PosX_BtnA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0)+X_Margins_BtnA); + rAIconX= OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0)+X_Margins_BtnA); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosType"), 0) == 3) {//Anchor None + PosX_BtnA = CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0); + rAIconX = CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.PosType"), 0) == 4) {//Hidden PosX_BtnA = -9999; rAIconX = -9999; } @@ -5730,17 +5730,17 @@ void Interface_Draw(PlayState* play) { s16 CarrotsPosX = ZREG(14); s16 CarrotsPosY = ZREG(15); s16 CarrotsMargins_X = 0; - if (CVarGetInteger("gCarrotsPosType", 0) != 0) { - CarrotsPosY = CVarGetInteger("gCarrotsPosY", 0); - if (CVarGetInteger("gCarrotsPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Left_HUD_Margin;}; - CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); - } else if (CVarGetInteger("gCarrotsPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Right_HUD_Margin;}; - CarrotsPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); - } else if (CVarGetInteger("gCarrotsPosType", 0) == 3) {//Anchor None - CarrotsPosX = CVarGetInteger("gCarrotsPosX", 0); - } else if (CVarGetInteger("gCarrotsPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosType"), 0) != 0) { + CarrotsPosY = CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosY"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.UseMargins"), 0) != 0) {CarrotsMargins_X = Left_HUD_Margin;}; + CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosX"), 0)+CarrotsMargins_X); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.UseMargins"), 0) != 0) {CarrotsMargins_X = Right_HUD_Margin;}; + CarrotsPosX = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosX"), 0)+CarrotsMargins_X); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosType"), 0) == 3) {//Anchor None + CarrotsPosX = CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Carrots.PosType"), 0) == 4) {//Hidden CarrotsPosX = -9999; } } @@ -5759,25 +5759,25 @@ void Interface_Draw(PlayState* play) { } else { // Score for the Horseback Archery s32 X_Margins_Archery; - if (CVarGetInteger("gASUseMargins", 0) != 0) { - if (CVarGetInteger("gASPosType", 0) == 0) {X_Margins_Archery = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) == 0) {X_Margins_Archery = Right_HUD_Margin;}; } else { X_Margins_Archery = 0; } s16 ArcheryPos_Y = ZREG(15); s16 ArcheryPos_X = OTRGetRectDimensionFromRightEdge(WREG(32)+X_Margins_Archery); - if (CVarGetInteger("gASPosType", 0) != 0) { - ArcheryPos_Y = CVarGetInteger("gASPosY", 0); - if (CVarGetInteger("gASPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gASUseMargins", 0) != 0) {X_Margins_Archery = Left_HUD_Margin;}; - ArcheryPos_X = OTRGetRectDimensionFromLeftEdge(CVarGetInteger("gASPosX", 0)+X_Margins_Archery); - } else if (CVarGetInteger("gASPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gASUseMargins", 0) != 0) {X_Margins_Archery = Right_HUD_Margin;}; - ArcheryPos_X = OTRGetRectDimensionFromRightEdge(CVarGetInteger("gASPosX", 0)+X_Margins_Archery); - } else if (CVarGetInteger("gASPosType", 0) == 3) {//Anchor None - ArcheryPos_X = CVarGetInteger("gASPosX", 0)+204+X_Margins_Archery; - } else if (CVarGetInteger("gASPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) != 0) { + ArcheryPos_Y = CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosY"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.UseMargins"), 0) != 0) {X_Margins_Archery = Left_HUD_Margin;}; + ArcheryPos_X = OTRGetRectDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosX"), 0)+X_Margins_Archery); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.UseMargins"), 0) != 0) {X_Margins_Archery = Right_HUD_Margin;}; + ArcheryPos_X = OTRGetRectDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosX"), 0)+X_Margins_Archery); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) == 3) {//Anchor None + ArcheryPos_X = CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosX"), 0)+204+X_Margins_Archery; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.ArcheryScore.PosType"), 0) == 4) {//Hidden ArcheryPos_X = -9999; } } @@ -6197,24 +6197,24 @@ void Interface_Draw(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, 255); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0); s32 X_Margins_Timer; - if (CVarGetInteger("gTimersUseMargins", 0) != 0) { - if (CVarGetInteger("gTimersPosType", 0) == 0) {X_Margins_Timer = Left_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 0) {X_Margins_Timer = Left_HUD_Margin;}; } else { X_Margins_Timer = 0; } svar5 = OTRGetRectDimensionFromLeftEdge(gSaveContext.timerX[svar6]+X_Margins_Timer); svar2 = gSaveContext.timerY[svar6]; - if (CVarGetInteger("gTimersPosType", 0) != 0) { - svar2 = (CVarGetInteger("gTimersPosY", 0)); - if (CVarGetInteger("gTimersPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gTimersUseMargins", 0) != 0) {X_Margins_Timer = Left_HUD_Margin;}; - svar5 = OTRGetRectDimensionFromLeftEdge(CVarGetInteger("gTimersPosX", 0)+X_Margins_Timer); - } else if (CVarGetInteger("gTimersPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gTimersUseMargins", 0) != 0) {X_Margins_Timer = Right_HUD_Margin;}; - svar5 = OTRGetRectDimensionFromRightEdge(CVarGetInteger("gTimersPosX", 0)+X_Margins_Timer); - } else if (CVarGetInteger("gTimersPosType", 0) == 3) {//Anchor None - svar5 = CVarGetInteger("gTimersPosX", 0)+204+X_Margins_Timer; - } else if (CVarGetInteger("gTimersPosType", 0) == 4) {//Hidden + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) != 0) { + svar2 = (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosY"), 0)); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.UseMargins"), 0) != 0) {X_Margins_Timer = Left_HUD_Margin;}; + svar5 = OTRGetRectDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosX"), 0)+X_Margins_Timer); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.UseMargins"), 0) != 0) {X_Margins_Timer = Right_HUD_Margin;}; + svar5 = OTRGetRectDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosX"), 0)+X_Margins_Timer); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 3) {//Anchor None + svar5 = CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosX"), 0)+204+X_Margins_Timer; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 4) {//Hidden svar5 = -9999; } } @@ -6273,31 +6273,31 @@ void Interface_DrawTotalGameplayTimer(PlayState* play) { // Draw timer based on the Gameplay Stats total time. if ((IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_TIMER] == BR_CHOICE_TIMER_YES) || - (CVarGetInteger("gGameplayStats.ShowIngameTimer", 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2)) { + (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ShowIngameTimer"), 0) && gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2)) { s32 X_Margins_Timer = 0; - if (CVarGetInteger("gIGTUseMargins", 0) != 0) { - if (CVarGetInteger("gIGTPosType", 0) == 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == 0) { X_Margins_Timer = Left_HUD_Margin; }; } s32 rectLeftOri = OTRGetRectDimensionFromLeftEdge(24 + X_Margins_Timer); s32 rectTopOri = 73; - if (CVarGetInteger("gIGTPosType", 0) != 0) { - rectTopOri = (CVarGetInteger("gIGTPosY", 0)); - if (CVarGetInteger("gIGTPosType", 0) == 1) { // Anchor Left - if (CVarGetInteger("gIGTUseMargins", 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) != 0) { + rectTopOri = (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosY"), 0)); + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == 1) { // Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.UseMargins"), 0) != 0) { X_Margins_Timer = Left_HUD_Margin; }; - rectLeftOri = OTRGetRectDimensionFromLeftEdge(CVarGetInteger("gIGTPosX", 0) + X_Margins_Timer); - } else if (CVarGetInteger("gIGTPosType", 0) == 2) { // Anchor Right - if (CVarGetInteger("gIGTUseMargins", 0) != 0) { + rectLeftOri = OTRGetRectDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosX"), 0) + X_Margins_Timer); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == 2) { // Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.UseMargins"), 0) != 0) { X_Margins_Timer = Right_HUD_Margin; }; - rectLeftOri = OTRGetRectDimensionFromRightEdge(CVarGetInteger("gIGTPosX", 0) + X_Margins_Timer); - } else if (CVarGetInteger("gIGTPosType", 0) == 3) { // Anchor None - rectLeftOri = CVarGetInteger("gIGTPosX", 0) + 204 + X_Margins_Timer; - } else if (CVarGetInteger("gIGTPosType", 0) == 4) { // Hidden + rectLeftOri = OTRGetRectDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosX"), 0) + X_Margins_Timer); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == 3) { // Anchor None + rectLeftOri = CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosX"), 0) + 204 + X_Margins_Timer; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.IGT.PosType"), 0) == 4) { // Hidden rectLeftOri = -9999; } } @@ -6384,10 +6384,10 @@ void Interface_Update(PlayState* play) { u16 action; Input* debugInput = &play->state.input[2]; - Top_HUD_Margin = CVarGetInteger("gHUDMargin_T", 0); - Left_HUD_Margin = CVarGetInteger("gHUDMargin_L", 0); - Right_HUD_Margin = CVarGetInteger("gHUDMargin_R", 0); - Bottom_HUD_Margin = CVarGetInteger("gHUDMargin_B", 0); + Top_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + Left_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + Right_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + Bottom_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); GameInteractor_ExecuteOnInterfaceUpdate(); diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 6e745ea7f..f3773d6a7 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -627,12 +627,6 @@ void Play_Init(GameState* thisx) { gTrnsnUnkState = 0; play->transitionMode = TRANS_MODE_OFF; - if (CVarGetInteger("gSceneTransitions", 255)!= 255){ - play->transitionMode = CVarGetInteger("gSceneTransitions", 0); - gSaveContext.nextTransitionType = CVarGetInteger("gSceneTransitions", 0); - play->transitionType = CVarGetInteger("gSceneTransitions", 0); - } - FrameAdvance_Init(&play->frameAdvCtx); Rand_Seed((u32)osGetTime()); Matrix_Init(&play->state); @@ -800,7 +794,7 @@ void Play_Update(PlayState* play) { HREG(82) = 0; } - if (CVarGetInteger("gFreeCamera", 0) && Player_InCsMode(play)) { + if (CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0) && Player_InCsMode(play)) { play->manualCamera = false; } @@ -1514,7 +1508,7 @@ void Play_Draw(PlayState* play) { // Flip the projections and invert culling for the OPA and XLU display buffers // These manage the world and effects - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING); gSPSetExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING); gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); @@ -1748,7 +1742,7 @@ void Play_Draw(PlayState* play) { GameInteractor_ExecuteOnPlayDrawEnd(); // Reset the inverted culling - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { gSPClearExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING); gSPClearExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING); } @@ -1796,11 +1790,11 @@ void Play_Main(GameState* thisx) { PlayState* play = (PlayState*)thisx; // Decrease the easy pause buffer timer every frame - if (CVarGetInteger("gCheatEasyPauseBufferTimer", 0) > 0) { - CVarSetInteger("gCheatEasyPauseBufferTimer", CVarGetInteger("gCheatEasyPauseBufferTimer", 0) - 1); + if (CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0) > 0) { + CVarSetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), CVarGetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 0) - 1); } - if (play->envCtx.unk_EE[2] == 0 && CVarGetInteger("gLetItSnow", 0)) { + if (play->envCtx.unk_EE[2] == 0 && CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { play->envCtx.unk_EE[3] = 64; Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_OBJECT_KANKYO, 0, 0, 0, 0, 0, 0, 3, 0); } @@ -1977,11 +1971,11 @@ void Play_InitScene(PlayState* play, s32 spawn) } void Play_SpawnScene(PlayState* play, s32 sceneNum, s32 spawn) { - uint8_t mqMode = CVarGetInteger("gBetterDebugWarpScreenMQMode", WARP_MODE_OVERRIDE_OFF); - int16_t mqModeScene = CVarGetInteger("gBetterDebugWarpScreenMQModeScene", -1); + uint8_t mqMode = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQMode"), WARP_MODE_OVERRIDE_OFF); + int16_t mqModeScene = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene"), -1); if (mqMode != WARP_MODE_OVERRIDE_OFF && sceneNum != mqModeScene) { - CVarClear("gBetterDebugWarpScreenMQMode"); - CVarClear("gBetterDebugWarpScreenMQModeScene"); + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQMode")); + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene")); } OTRPlay_SpawnScene(play, sceneNum, spawn); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index c38dc8ca8..b9ef17f6e 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1558,7 +1558,7 @@ void func_800906D4(PlayState* play, Player* this, Vec3f* newTipPos) { void Player_DrawGetItemIceTrap(PlayState* play, Player* this, Vec3f* refPos, s32 drawIdPlusOne, f32 height) { OPEN_DISPS(play->state.gfxCtx); - if (CVarGetInteger("gLetItSnow", 0)) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY); @@ -2123,8 +2123,8 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* playerSwordAndShield[1] = shield; Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0), - pos->y - (CVarGetInteger("gPauseTriforce", 0) ? 16 : 0), pos->z, rot); - Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), scale, scale, MTXMODE_APPLY); + pos->y - (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0) ? 16 : 0), pos->z, rot); + Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale, scale, MTXMODE_APPLY); gSPSegment(POLY_OPA_DISP++, 0x04, seg04); gSPSegment(POLY_OPA_DISP++, 0x06, seg06); @@ -2142,11 +2142,11 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* Player_DrawImpl(play, skelAnime->skeleton, skelAnime->jointTable, skelAnime->dListCount, 0, tunic, boots, 0, Player_OverrideLimbDrawPause, NULL, &playerSwordAndShield); - if (CVarGetInteger("gPauseTriforce", 0)) { + if (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0)) { Matrix_SetTranslateRotateYXZ(pos->x - (LINK_AGE_IN_YEARS == YEARS_ADULT ? 25 : 0), pos->y + 280 + (LINK_AGE_IN_YEARS == YEARS_ADULT ? 48 : 0), pos->z, rot); - Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), scale * 1, scale * 1, MTXMODE_APPLY); + Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale * 1, scale * 1, MTXMODE_APPLY); Gfx* ohNo = POLY_XLU_DISP; POLY_XLU_DISP = POLY_OPA_DISP; @@ -2202,7 +2202,7 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* }; s16 AnimArraySize = ARRAY_COUNT(PauseMenuAnimSet); - if (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) || CVarGetInteger("gPauseTriforce", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("PauseLiveLink"), 0) || CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0)) { uintptr_t anim = 0; // Initialise anim if (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) >= EQUIP_VALUE_SWORD_BIGGORON) { @@ -2359,7 +2359,7 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* //anim = gPlayerAnim_link_wait_itemD2_20f; // Use for biggoron sword? - if (CVarGetInteger("gPauseTriforce", 0)) { + if (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0)) { anim = gPlayerAnim_link_magic_kaze2; sword = 0; shield = 0; diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index 3b6085040..8970dac1b 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -5,6 +5,7 @@ #include "global.h" #include "vt.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #include #include @@ -275,7 +276,7 @@ void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 hei bg->b.imageFmt = fmt; bg->b.imageSiz = siz; bg->b.imagePal = 0; - bg->b.imageFlip = CVarGetInteger("gMirroredWorld", 0) ? G_BG_FLAG_FLIPS : 0; + bg->b.imageFlip = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_BG_FLAG_FLIPS : 0; // When an alt resource exists for the background, we need to unload the original asset // to clear the cache so the alt asset will be loaded instead @@ -412,7 +413,7 @@ BgImage* func_80096A74(PolygonType1* polygon1, PlayState* play) { camera = GET_ACTIVE_CAM(play); camId = camera->camDataIdx; - if (camId == -1 && (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) || CVarGetInteger("gCrowdControl", 0))) { + if (camId == -1 && (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)))) { // This prevents a crash when using items that change the // camera (such as din's fire), voiding out or dying on // scenes with prerendered backgrounds. diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 60285a8bf..af92afe91 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -232,7 +232,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.dayTime = 0x6AAB; gSaveContext.cutsceneIndex = 0xFFF1; - if ((fileChooseCtx->buttonIndex == 0 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) || CVarGetInteger("gNaviSkipCutscene", 0)) { + if ((fileChooseCtx->buttonIndex == 0 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0))) { gSaveContext.cutsceneIndex = 0; } @@ -245,7 +245,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { u8 currentQuest = fileChooseCtx->questType[fileChooseCtx->buttonIndex]; if (currentQuest == QUEST_RANDOMIZER && - strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0) { + strnlen(CVarGetString(CVAR_GENERAL("SpoilerLog"), ""), 1) != 0) { gSaveContext.questId = QUEST_RANDOMIZER; Randomizer_InitSaveFile(); diff --git a/soh/src/code/z_view.c b/soh/src/code/z_view.c index 42e4bcce7..c6235c923 100644 --- a/soh/src/code/z_view.c +++ b/soh/src/code/z_view.c @@ -432,7 +432,7 @@ s32 func_800AAA9C(View* view) { } osSyncPrintf("\n"); } - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { MtxF flipF; SkinMatrix_Clear(&flipF); flipF.xx = -1.0; @@ -553,7 +553,7 @@ s32 func_800AB2C4(View* view) { (f32)gScreenHeight * 0.5f, -30, view->zFar, view->scale); // This is for z-targeting - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { MtxF flipF; SkinMatrix_Clear(&flipF); flipF.xx = -1.0; diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index bb521ede9..80457e5fb 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -258,7 +258,7 @@ void ArmsHook_Shoot(ArmsHook* this, PlayState* play) { sp60.y = this->unk_1F4.y - (this->unk_1E8.y - this->unk_1F4.y); sp60.z = this->unk_1F4.z - (this->unk_1E8.z - this->unk_1F4.z); u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (BgCheck_EntityLineTest1(&play->colCtx, &sp60, &this->unk_1E8, &sp78, &poly, true, true, true, true, diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index 6e1c36f78..ea4cfbfec 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -6,6 +6,7 @@ #include "z_bg_mori_bigst.h" #include "objects/object_mori_objects/object_mori_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -216,8 +217,8 @@ void BgMoriBigst_SetupStalfosPairFight(BgMoriBigst* this, PlayState* play) { void BgMoriBigst_StalfosPairFight(BgMoriBigst* this, PlayState* play) { if ((this->dyna.actor.home.rot.z == 0 || // Check if all enemies are defeated instead of the regular stalfos when enemy randomizer or crowd control is on. - (Flags_GetTempClear(play, this->dyna.actor.room) && (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger("gCrowdControl", 0))))) && - !Player_InCsMode(play)) { + (Flags_GetTempClear(play, this->dyna.actor.room) && (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || + ((CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)))))) && !Player_InCsMode(play)) { Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); BgMoriBigst_SetupDone(this, play); } diff --git a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c index 816f96aa4..9a22a21c6 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c @@ -251,7 +251,7 @@ void BgSpot06Objects_GateSpawnBubbles(BgSpot06Objects* this, PlayState* play) { void BgSpot06Objects_GateWaitForSwitch(BgSpot06Objects* this, PlayState* play) { s32 i; - if ((CVarGetInteger("gWaterTempleGateFix", 0) == 0 || LINK_IS_ADULT) && Flags_GetSwitch(play, this->switchFlag)) { + if (Flags_GetSwitch(play, this->switchFlag)) { this->timer = 100; this->dyna.actor.world.pos.y += 3.0f; this->actionFunc = BgSpot06Objects_GateWaitToOpen; diff --git a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c index d612475d4..0d367a411 100644 --- a/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c +++ b/soh/src/overlays/actors/ovl_En_Blkobj/z_en_blkobj.c @@ -6,6 +6,7 @@ #include "z_en_blkobj.h" #include "objects/object_blkobj/object_blkobj.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -104,8 +105,11 @@ void EnBlkobj_DarkLinkFight(EnBlkobj* this, PlayState* play) { // Check for if Dark Link is defeated in authentic gameplay. // Check for if all enemies are defeated with enemy randomizer or crowd control on. uint8_t roomCleared = - (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && !CVarGetInteger("gCrowdControl", 0) && Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) || - ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) && Flags_GetTempClear(play, this->dyna.actor.room)); + (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && + !(CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)) && + Actor_Find(&play->actorCtx, ACTOR_EN_TORCH2, ACTORCAT_BOSS) == NULL) || + ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) && + Flags_GetTempClear(play, this->dyna.actor.room)); if (roomCleared) { Flags_SetClear(play, this->dyna.actor.room); this->timer++; diff --git a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index 40ba64503..c265b3eb0 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -491,7 +491,7 @@ void EnBomChu_Draw(Actor* thisx, PlayState* play) { f32 colorIntensity; s32 blinkHalfPeriod; s32 blinkTime; - Color_RGB8 BombchuCol = CVarGetColor24("gBombTrailCol", BombchuColorOriginal); + Color_RGB8 BombchuCol = CVarGetColor24(CVAR_COSMETIC("Trails.Bombchu.Value"), BombchuColorOriginal); OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 7ec29b818..ee052bc58 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -733,7 +733,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } } - if (CVarGetInteger("gLetItSnow", 0) && hasChristmasChestTexturesAvailable && hasCreatedRandoChestTextures && !hasCustomChestDLs) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0) && hasChristmasChestTexturesAvailable && hasCreatedRandoChestTextures && !hasCustomChestDLs) { if (this->dyna.actor.scale.x == 0.01f) { this->boxBodyDL = gChristmasRedTreasureChestChestFrontDL; this->boxLidDL = gChristmasRedTreasureChestChestSideAndLidDL; diff --git a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c index c4ed47bf6..f0f6b5bb5 100644 --- a/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c +++ b/soh/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c @@ -262,7 +262,7 @@ void EnClearTag_Init(Actor* thisx, PlayState* play) { // Change Arwing to regular enemy instead of boss with enemy randomizer and crowd control. // This way Arwings will be considered for "clear enemy" rooms properly. - if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) { Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index d8155e2da..67ac098ff 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -1363,7 +1363,7 @@ void EnGo2_RollingAnimation(EnGo2* this, PlayState* play) { } void EnGo2_WakeUp(EnGo2* this, PlayState* play) { - if (CVarGetInteger("gUnfixGoronSpin", 0)) { + if (CVarGetInteger(CVAR_COSMETIC("UnfixGoronSpin"), 0)) { // Trick SkelAnime into thinking the current animation is changing so that it morphs between the same position, // making the goron do a spin this->skelAnime.animation = NULL; @@ -1384,14 +1384,14 @@ void EnGo2_WakeUp(EnGo2* this, PlayState* play) { // which uses the same frame data as ANIM_1/10 but no morph frames, but only when the // current animation frame is at 0, meaning no morphing is necessary anyway. // ANIM_13 is ANIM_0 but with the startFrame and mode adjusted for biggoron. - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { + if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger(CVAR_COSMETIC("UnfixGoronSpin"), 0)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_13); } else { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10); } this->skelAnime.playSpeed = 0.5f; } else { - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { + if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger(CVAR_COSMETIC("UnfixGoronSpin"), 0)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_0); } else { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1); diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index de3770988..a9fb3267e 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -3042,7 +3042,7 @@ void EnHorse_StickDirection(Vec2f* curStick, f32* stickMag, s16* angle) { void EnHorse_UpdateStick(EnHorse* this, PlayState* play) { this->lastStick = this->curStick; - this->curStick.x = play->state.input[0].rel.stick_x * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + this->curStick.x = play->state.input[0].rel.stick_x * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); this->curStick.y = play->state.input[0].rel.stick_y; } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index b3f1219ad..87ed6aeae 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -233,7 +233,8 @@ void func_80A74398(Actor* thisx, PlayState* play) { Effect_Add(play, &this->blureIdx, EFFECT_BLURE1, 0, 0, &blureInit); func_80A74714(this); - uint8_t enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); + uint8_t enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || + (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)); if (this->switchFlags != 0xFF) { // In vanilla gameplay, Iron Knuckles are despawned based on specific flags in specific scenarios. @@ -663,7 +664,8 @@ void func_80A75A38(EnIk* this, PlayState* play) { Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xB0); // Don't set flag when Enemy Rando or CrowdControl are on. // Instead Iron Knuckles rely on the "clear room" flag. - if (this->switchFlags != 0xFF && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && !CVarGetInteger("gCrowdControl", 0)) { + if (this->switchFlags != 0xFF && !CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) && + !(CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) { Flags_SetSwitch(play, this->switchFlags); } Actor_Kill(&this->actor); @@ -1484,7 +1486,8 @@ void EnIk_Init(Actor* thisx, PlayState* play) { } // Immediately trigger Iron Knuckle for Enemy Rando and Crowd Control - if ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) && (thisx->params == 2 || thisx->params == 3)) { + if ((CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) + && (thisx->params == 2 || thisx->params == 3)) { this->skelAnime.playSpeed = 1.0f; } } diff --git a/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c b/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c index adff5253e..44b3399b0 100644 --- a/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c +++ b/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c @@ -655,7 +655,7 @@ void EnMag_DrawInnerMq(Actor* thisx, PlayState* play, Gfx** gfxp) { u16 rectTop; u16 length; int lang = LANGUAGE_ENG; - if (CVarGetInteger("gTitleScreenTranslation", 0)) { + if (CVarGetInteger(CVAR_SETTING("TitleScreenTranslation"), 0)) { lang = gSaveContext.language; } @@ -855,7 +855,7 @@ void EnMag_DrawInnerVanilla(Actor* thisx, PlayState* play, Gfx** gfxp) { u16 rectTop; u16 length; int lang = LANGUAGE_ENG; - if (CVarGetInteger("gTitleScreenTranslation", 0)) { + if (CVarGetInteger(CVAR_SETTING("TitleScreenTranslation"), 0)) { lang = gSaveContext.language; } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index c538e568e..5f0270d03 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -664,7 +664,7 @@ void EnOssan_UpdateCursorPos(PlayState* play, EnOssan* this) { this->cursorX = x; this->cursorY = y; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { this->cursorX = SCREEN_WIDTH - x; } } @@ -775,7 +775,7 @@ void EnOssan_UpdateJoystickInputState(PlayState* play, EnOssan* this) { s8 stickX = input->rel.stick_x; s8 stickY = input->rel.stick_y; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { stickX = -input->rel.stick_x; } @@ -981,7 +981,7 @@ s32 EnOssan_FacingShopkeeperDialogResult(EnOssan* this, PlayState* play) { void EnOssan_State_FacingShopkeeper(EnOssan* this, PlayState* play, Player* player) { Input* input = &play->state.input[0]; u8 nextIndex; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && !EnOssan_TestEndInteraction(this, play, &play->state.input[0])) { @@ -992,7 +992,7 @@ void EnOssan_State_FacingShopkeeper(EnOssan* this, PlayState* play, Player* play u16 dLeft = BTN_DLEFT; u16 dRight = BTN_DRIGHT; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { dLeft = BTN_DRIGHT; dRight = BTN_DLEFT; } @@ -1070,7 +1070,7 @@ void EnOssan_CursorUpDown(EnOssan* this, PlayState* play) { Input* input = &play->state.input[0]; u8 curTemp = this->cursorIndex; u8 curScanTemp; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if ((this->stickAccumY < 0) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { curTemp &= 0xFE; @@ -1223,7 +1223,7 @@ void EnOssan_State_BrowseLeftShelf(EnOssan* this, PlayState* play, Player* playe u8 prevIndex = this->cursorIndex; s32 c; s32 d; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (!EnOssan_ReturnItemToShelf(this)) { osSyncPrintf("%s[%d]:" VT_FGCOL(GREEN) "ズーム中!!" VT_RST "\n", __FILE__, __LINE__); @@ -1242,7 +1242,7 @@ void EnOssan_State_BrowseLeftShelf(EnOssan* this, PlayState* play, Player* playe u16 dLeft = BTN_DLEFT; u16 dRight = BTN_DRIGHT; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { dLeft = BTN_DRIGHT; dRight = BTN_DLEFT; } @@ -1292,7 +1292,7 @@ void EnOssan_State_BrowseRightShelf(EnOssan* this, PlayState* play, Player* play s32 pad[2]; u8 prevIndex; u8 nextIndex; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); prevIndex = this->cursorIndex; if (!EnOssan_ReturnItemToShelf(this)) { @@ -1312,7 +1312,7 @@ void EnOssan_State_BrowseRightShelf(EnOssan* this, PlayState* play, Player* play u16 dLeft = BTN_DLEFT; u16 dRight = BTN_DRIGHT; - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { dLeft = BTN_DRIGHT; dRight = BTN_DLEFT; } @@ -2414,7 +2414,7 @@ void EnOssan_DrawStickDirectionPrompts(PlayState* play, EnOssan* this) { s32 drawStickRightPrompt = this->stickRightPrompt.isEnabled; // Invert which stick prompt is active when only one is active - if (CVarGetInteger("gMirroredWorld", 0) && (drawStickLeftPrompt != drawStickRightPrompt)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) && (drawStickLeftPrompt != drawStickRightPrompt)) { drawStickLeftPrompt = !drawStickLeftPrompt; drawStickRightPrompt = !drawStickRightPrompt; } diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index 901191d0d..de7bddf82 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -580,7 +580,7 @@ void EnPartner_Update(Actor* thisx, PlayState* play) { Input sControlInput = play->state.input[this->actor.params]; - f32 relX = sControlInput.cur.stick_x / 10.0f * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1); + f32 relX = sControlInput.cur.stick_x / 10.0f * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1); f32 relY = sControlInput.cur.stick_y / 10.0f; Vec3f camForward = { GET_ACTIVE_CAM(play)->at.x - GET_ACTIVE_CAM(play)->eye.x, 0.0f, @@ -689,7 +689,7 @@ void EnPartner_Update(Actor* thisx, PlayState* play) { uint16_t partnerButtons[7] = { BTN_CLEFT, BTN_CDOWN, BTN_CRIGHT, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT}; uint8_t buttonMax = 3; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonMax = ARRAY_COUNT(gSaveContext.equips.cButtonSlots); } diff --git a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 0ffd1459e..e69cfda78 100644 --- a/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/soh/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -254,7 +254,7 @@ void func_80AE2744(EnRd* this, PlayState* play) { // Add a height check to redeads/gibdos freeze when Enemy Randomizer is on. // Without the height check, redeads/gibdos can freeze the player from insane distances in // vertical rooms (like the first room in Deku Tree), making these rooms nearly unplayable. - s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); + s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)); if (!enemyRandoCCActive || (enemyRandoCCActive && this->actor.yDistToPlayer <= 100.0f && this->actor.yDistToPlayer >= -100.0f)) { if ((this->actor.params != 2) && (this->unk_305 == 0)) { func_80AE37BC(this); @@ -668,7 +668,7 @@ void func_80AE3C98(EnRd* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { if (this->unk_30C == 0) { - s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0); + s8 enemyRandoCCActive = CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0)); // Don't set this flag in Enemy Rando as it can overlap with other objects using the same flag. if (!Flags_GetSwitch(play, this->unk_312 & 0x7F) && !enemyRandoCCActive) { Flags_SetSwitch(play, this->unk_312 & 0x7F); diff --git a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index ef2b79cdb..9e9fc82f5 100644 --- a/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/soh/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -128,7 +128,7 @@ void EnTorch2_Init(Actor* thisx, PlayState* play2) { // Change Dark Link to regular enemy instead of boss with enemy randomizer and crowd control. // This way Dark Link will be considered for "clear enemy" rooms properly. - if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || CVarGetInteger("gCrowdControl", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0) || (CVarGetInteger(CVAR_REMOTE("Scheme"), GI_SCHEME_SAIL) == GI_SCHEME_CROWD_CONTROL && CVarGetInteger(CVAR_REMOTE("Enabled"), 0))) { Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_ENEMY); } @@ -592,7 +592,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) { input->prev.button = input->cur.button & (u16) ~(BTN_A | BTN_B); PadUtils_UpdateRelXY(input); - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { input->rel.stick_x *= -1; } diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 7bf1ac7d1..b54a3ee76 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -2025,7 +2025,7 @@ void Fishing_DrawRod(PlayState* play) { spC8 = player->unk_85C - spC8; spC4 = player->unk_858; - Math_SmoothStepToF(&player->unk_858, input->rel.stick_x * 0.02f * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), 0.3f, 5.0f, 0.0f); + Math_SmoothStepToF(&player->unk_858, input->rel.stick_x * 0.02f * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), 0.3f, 5.0f, 0.0f); spC4 = player->unk_858 - spC4; if (player->unk_858 > 1.0f) { diff --git a/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c b/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c index 73a588ab3..db1ea8208 100644 --- a/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c +++ b/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c @@ -200,8 +200,8 @@ void MagicDark_DiamondDraw(Actor* thisx, PlayState* play) { u16 gameplayFrames = play->gameplayFrames; Color_RGB8 Spell_env_ori = {0, 100, 255}; Color_RGB8 Spell_col_ori = {170, 255, 255}; - Color_RGB8 Spell_env = CVarGetColor24("gNL_Diamond_Env", Spell_env_ori); - Color_RGB8 Spell_col = CVarGetColor24("gNL_Diamond_Col", Spell_col_ori); + Color_RGB8 Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusSecondary.Value"), Spell_env_ori); + Color_RGB8 Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusPrimary.Value"), Spell_col_ori); OPEN_DISPS(play->state.gfxCtx); @@ -224,7 +224,7 @@ void MagicDark_DiamondDraw(Actor* thisx, PlayState* play) { Matrix_RotateY(this->actor.shape.rot.y * (M_PI / 0x8000), MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - if (CVarGetInteger("gUseSpellsCol",0)) { + if (CVarGetInteger(CVAR_COSMETIC("UseSpellsColors"),0)) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (s32)(this->primAlpha * 0.6f) & 0xFF); gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 128); } else { diff --git a/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c b/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c index b245c988c..f785124f4 100644 --- a/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c +++ b/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c @@ -218,8 +218,8 @@ void MagicFire_Draw(Actor* thisx, PlayState* play) { u8 alpha; Color_RGB8 Spell_env_ori = {255, 0, 0}; Color_RGB8 Spell_col_ori = {255, 200, 0}; - Color_RGB8 Spell_env = CVarGetColor24("gDF_Env", Spell_env_ori); - Color_RGB8 Spell_col = CVarGetColor24("gDF_Col", Spell_col_ori); + Color_RGB8 Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.DinsSecondary.Value"), Spell_env_ori); + Color_RGB8 Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.DinsPrimaryary.Value"), Spell_col_ori); if (this->action > 0) { OPEN_DISPS(play->state.gfxCtx); @@ -231,7 +231,7 @@ void MagicFire_Draw(Actor* thisx, PlayState* play) { gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE); gDPFillRectangle(POLY_XLU_DISP++, 0, 0, 319, 239); Gfx_SetupDL_25Xlu(play->state.gfxCtx); - if (CVarGetInteger("gUseSpellsCol",0)) { + if (CVarGetInteger(CVAR_COSMETIC("UseSpellsColors"),0)) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (u8)(this->alphaMultiplier * 255)); gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, (u8)(this->alphaMultiplier * 255)); } else { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index cef3f2d3f..f1dd52d6e 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2213,7 +2213,7 @@ s32 Player_ItemIsItemAction(s32 item1, s32 itemAction) { } s32 Player_GetItemOnButton(PlayState* play, s32 index) { - if (index >= ((CVarGetInteger("gDpadEquips", 0) != 0) ? 8 : 4)) { + if (index >= ((CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) ? 8 : 4)) { return ITEM_NONE; } else if (play->bombchuBowlingStatus != 0) { return (play->bombchuBowlingStatus > 0) ? ITEM_BOMBCHU : ITEM_NONE; @@ -2254,7 +2254,7 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) { s32 maskItem = this->currentMask - PLAYER_MASK_KEATON + ITEM_MASK_KEATON; bool hasOnDpad = false; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { for (int buttonIndex = 4; buttonIndex < 8; buttonIndex++) { hasOnDpad |= gSaveContext.equips.buttonItems[buttonIndex] == maskItem; } @@ -2270,7 +2270,7 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { maskItemAction = this->currentMask - 1 + PLAYER_IA_MASK_KEATON; bool hasOnDpad = false; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) { hasOnDpad |= Player_ItemIsItemAction(DPAD_ITEM(buttonIndex), maskItemAction); } @@ -2286,7 +2286,7 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { if (!(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)) && !func_8008F128(this)) { if (this->itemAction >= PLAYER_IA_FISHING_POLE) { bool hasOnDpad = false; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) { hasOnDpad |= Player_ItemIsInUse(this, DPAD_ITEM(buttonIndex)); } @@ -2677,7 +2677,7 @@ int func_80834E44(PlayState* play) { int func_80834E7C(PlayState* play) { u16 buttonsToCheck = BTN_A | BTN_B | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } return (play->shootingGalleryStatus != 0) && @@ -4003,7 +4003,7 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) { } if ((arg2 >= PLAYER_MWA_FLIPSLASH_START) && (arg2 <= PLAYER_MWA_JUMPSLASH_FINISH)) { - if (CVarGetInteger("gRestoreQPA", 1) && temp == -1) { + if (CVarGetInteger(CVAR_GENERAL("RestoreQPA"), 1) && temp == -1) { dmgFlags = 0x16171617; } else { @@ -5653,7 +5653,7 @@ s32 Player_ActionChange_4(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT; } - if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP) && !sp28) { + if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger(CVAR_SETTING("NaviOnL"), 0) ? BTN_L : BTN_CUP) && !sp28) { return 0; } @@ -5702,7 +5702,7 @@ s32 Player_ActionChange_0(Player* this, PlayState* play) { if ((this->unk_664 != NULL) && (CHECK_FLAG_ALL(this->unk_664->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_NAVI_HAS_INFO) || (this->unk_664->naviEnemyId != 0xFF))) { this->stateFlags2 |= PLAYER_STATE2_NAVI_ALERT; - } else if ((this->naviTextId == 0 || CVarGetInteger("gNaviOnL", 0)) && !func_8008E9C4(this) && CHECK_BTN_ALL(sControlInput->press.button, BTN_CUP) && + } else if ((this->naviTextId == 0 || CVarGetInteger(CVAR_SETTING("NaviOnL"), 0)) && !func_8008E9C4(this) && CHECK_BTN_ALL(sControlInput->press.button, BTN_CUP) && (YREG(15) != 0x10) && (YREG(15) != 0x20) && !func_8083B8F4(this, play)) { func_80078884(NA_SE_SY_ERROR); @@ -6551,18 +6551,18 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { maxSpeed *= 1.5f; } - if (CVarGetInteger("gEnableWalkModify", 0) && !CVarGetInteger("gWalkModifierDoesntChangeJump", 0)) { - if (CVarGetInteger("gWalkSpeedToggle", 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0) && !CVarGetInteger(CVAR_SETTING("WalkModifier.DoesntChangeJump"), 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.SpeedToggle"), 0)) { if (gWalkSpeedToggle1) { - maxSpeed *= CVarGetFloat("gWalkModifierOne", 1.0f); + maxSpeed *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping1"), 1.0f); } else if (gWalkSpeedToggle2) { - maxSpeed *= CVarGetFloat("gWalkModifierTwo", 1.0f); + maxSpeed *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping2"), 1.0f); } } else { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { - maxSpeed *= CVarGetFloat("gWalkModifierOne", 1.0f); + maxSpeed *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping1"), 1.0f); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { - maxSpeed *= CVarGetFloat("gWalkModifierTwo", 1.0f); + maxSpeed *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping2"), 1.0f); } } } @@ -6932,7 +6932,7 @@ s32 func_8083EAF0(Player* this, Actor* actor) { s32 Player_ActionChange_9(Player* this, PlayState* play) { u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->heldActor != NULL) && @@ -7415,7 +7415,7 @@ s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) { } // #region SOH [Enhancement] - if (CVarGetInteger("gRightStickAiming", 0) || !CVarGetInteger("gInvertZAimingYAxis", 1)) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0) || !CVarGetInteger(CVAR_SETTING("Controls.InvertZAimingYAxis"), 1)) { if (this->unk_664 != NULL) { func_8083DB98(this, 1); @@ -7423,7 +7423,7 @@ s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) { int8_t relStickY; // preserves simultaneous left/right-stick aiming - if (CVarGetInteger("gRightStickAiming", 0)) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { if ((sControlInput->rel.stick_y + sControlInput->rel.right_stick_y) >= 0) { relStickY = (((sControlInput->rel.stick_y) > (sControlInput->rel.right_stick_y)) ? (sControlInput->rel.stick_y) @@ -7438,7 +7438,7 @@ s32 func_8083FD78(Player* this, f32* arg1, s16* arg2, PlayState* play) { } Math_SmoothStepToS(&this->actor.focus.rot.x, - relStickY * (CVarGetInteger("gInvertZAimingYAxis", 1) ? 1 : -1) * 240.0f, 14, 4000, 30); + relStickY * (CVarGetInteger(CVAR_SETTING("Controls.InvertZAimingYAxis"), 1) ? 1 : -1) * 240.0f, 14, 4000, 30); func_80836AB8(this, 1); } // #endregion @@ -8289,18 +8289,18 @@ void Player_Action_80842180(Player* this, PlayState* play) { sp2C *= 1.5f; } - if (CVarGetInteger("gEnableWalkModify", 0)) { - if (CVarGetInteger("gWalkSpeedToggle", 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.SpeedToggle"), 0)) { if (gWalkSpeedToggle1) { - sp2C *= CVarGetFloat("gWalkModifierOne", 1.0f); + sp2C *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping1"), 1.0f); } else if (gWalkSpeedToggle2) { - sp2C *= CVarGetFloat("gWalkModifierTwo", 1.0f); + sp2C *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping2"), 1.0f); } } else { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { - sp2C *= CVarGetFloat("gWalkModifierOne", 1.0f); + sp2C *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping1"), 1.0f); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { - sp2C *= CVarGetFloat("gWalkModifierTwo", 1.0f); + sp2C *= CVarGetFloat(CVAR_SETTING("WalkModifier.Mapping2"), 1.0f); } } } @@ -8694,8 +8694,8 @@ void Player_Action_80843188(Player* this, PlayState* play) { func_8083721C(this); if (this->av2.actionVar2 != 0) { - sp54 = sControlInput->rel.stick_y * 100 * (CVarGetInteger("gInvertShieldAimingYAxis", 1) ? 1 : -1); - sp50 = sControlInput->rel.stick_x * (CVarGetInteger("gMirroredWorld", 0) ? 120 : -120) * (CVarGetInteger("gInvertShieldAimingXAxis", 0) ? -1 : 1); + sp54 = sControlInput->rel.stick_y * 100 * (CVarGetInteger(CVAR_SETTING("Controls.InvertShieldAimingYAxis"), 1) ? 1 : -1); + sp50 = sControlInput->rel.stick_x * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 120 : -120) * (CVarGetInteger(CVAR_SETTING("Controls.InvertShieldAimingYAxis"), 0) ? -1 : 1); sp4E = this->actor.shape.rot.y - Camera_GetInputDirYaw(GET_ACTIVE_CAM(play)); sp40 = Math_CosS(sp4E); @@ -9076,7 +9076,7 @@ void Player_Action_8084411C(Player* this, PlayState* play) { Actor* heldActor = this->heldActor; u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (!func_80835644(play, this, heldActor) && (heldActor->id == ACTOR_EN_NIW) && @@ -9858,7 +9858,7 @@ void Player_Action_80846260(Player* this, PlayState* play) { } u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (this->av2.actionVar2 == 0) { @@ -11074,13 +11074,13 @@ void func_80848EF8(Player* this, PlayState* play) { stoneOfAgonyColor = CVarGetColor24(CVAR_COSMETIC("HUD.StoneOfAgony.Value"), stoneOfAgonyColor); } if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"), 0) && !this->stateFlags1 && !GameInteractor_NoUIActive()) { - s16 Top_Margins = (CVarGetInteger("gHUDMargin_T", 0) * -1); - s16 Left_Margins = CVarGetInteger("gHUDMargin_L", 0); - s16 Right_Margins = CVarGetInteger("gHUDMargin_R", 0); + s16 Top_Margins = (CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0) * -1); + s16 Left_Margins = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + s16 Right_Margins = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); s16 X_Margins_VSOA; s16 Y_Margins_VSOA; - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 0) { X_Margins_VSOA = Left_Margins; }; Y_Margins_VSOA = Top_Margins; @@ -11092,21 +11092,21 @@ void func_80848EF8(Player* this, PlayState* play) { s16 PosY_VSOA_ori = 60 + Y_Margins_VSOA; s16 PosX_VSOA; s16 PosY_VSOA; - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) != 0) { - PosY_VSOA = CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosY"), 0) + Y_Margins_VSOA; - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 1) { // Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) != 0) { + PosY_VSOA = CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosY"), 0) + Y_Margins_VSOA; + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 1) { // Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.UseMargins"), 0) != 0) { X_Margins_VSOA = Left_Margins; }; - PosX_VSOA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0) + X_Margins_VSOA); - } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 2) { // Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.UseMargins"), 0) != 0) { + PosX_VSOA = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosX"), 0) + X_Margins_VSOA); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 2) { // Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.UseMargins"), 0) != 0) { X_Margins_VSOA = Right_Margins; }; - PosX_VSOA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0) + X_Margins_VSOA); - } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 3) { // Anchor None - PosX_VSOA = CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("VisualSoA.PosType"), 0) == 4) { // Hidden + PosX_VSOA = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosX"), 0) + X_Margins_VSOA); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 3) { // Anchor None + PosX_VSOA = CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 4) { // Hidden PosX_VSOA = -9999; } } else { @@ -11661,7 +11661,7 @@ void Player_Update(Actor* thisx, PlayState* play) { } } - if (CVarGetInteger("gEnableWalkModify", 0) && CVarGetInteger("gWalkSpeedToggle", 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0) && CVarGetInteger(CVAR_SETTING("WalkModifier.SpeedToggle"), 0)) { if (CHECK_BTN_ALL(sControlInput->press.button, BTN_MODIFIER1)) { gWalkSpeedToggle1 = !gWalkSpeedToggle1; } @@ -11774,7 +11774,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, if ((overrideLimbDraw == Player_OverrideLimbDrawGameplayDefault) && (this->currentMask != PLAYER_MASK_NONE)) { // Fixes a bug in vanilla where ice traps are rendered extremely large while wearing a bunny hood - if (CVarGetInteger("gFixIceTrapWithBunnyHood", 1)) Matrix_Push(); + if (CVarGetInteger(CVAR_GENERAL("FixIceTrapWithBunnyHood"), 1)) Matrix_Push(); Mtx* bunnyEarMtx = Graph_Alloc(play->state.gfxCtx, 2 * sizeof(Mtx)); if (this->currentMask == PLAYER_MASK_BUNNY) { @@ -11803,7 +11803,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]); } - if (CVarGetInteger("gFixIceTrapWithBunnyHood", 1)) Matrix_Pop(); + if (CVarGetInteger(CVAR_GENERAL("FixIceTrapWithBunnyHood"), 1)) Matrix_Pop(); } if ((this->currentBoots == PLAYER_BOOTS_HOVER || @@ -11997,23 +11997,23 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { s32 temp1 = 0; s16 temp2 = 0; s16 temp3 = 0; - s8 invertXAxisMulti = ((CVarGetInteger("gInvertAimingXAxis", 0) && !CVarGetInteger("gMirroredWorld", 0)) || (!CVarGetInteger("gInvertAimingXAxis", 0) && CVarGetInteger("gMirroredWorld", 0))) ? -1 : 1; - s8 invertYAxisMulti = CVarGetInteger("gInvertAimingYAxis", 1) ? 1 : -1; - f32 xAxisMulti = CVarGetFloat("gFirstPersonCameraSensitivityX", 1.0f); - f32 yAxisMulti = CVarGetFloat("gFirstPersonCameraSensitivityY", 1.0f); + s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) && !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) || (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0))) ? -1 : 1; + s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1; + f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f); + f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f); if (!func_8002DD78(this) && !func_808334B4(this) && (arg2 == 0)) { // First person without weapon // Y Axis - if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) { + if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) { temp2 += sControlInput->rel.stick_y * 240.0f * invertYAxisMulti * yAxisMulti; } - if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) { temp2 += sControlInput->cur.right_stick_y * 240.0f * invertYAxisMulti * yAxisMulti; } if (fabsf(sControlInput->cur.gyro_x) > 0.01f) { temp2 += (-sControlInput->cur.gyro_x) * 750.0f; } - if (CVarGetInteger("gDisableAutoCenterViewFirstPerson", 0)) { + if (CVarGetInteger(CVAR_SETTING("DisableFirstPersonAutoCenterView"), 0)) { this->actor.focus.rot.x += temp2 * 0.1f; this->actor.focus.rot.x = CLAMP(this->actor.focus.rot.x, -14000, 14000); } else { @@ -12022,10 +12022,10 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { // X Axis temp2 = 0; - if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) { + if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) { temp2 += sControlInput->rel.stick_x * -16.0f * invertXAxisMulti * xAxisMulti; } - if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) { temp2 += sControlInput->cur.right_stick_x * -16.0f * invertXAxisMulti * xAxisMulti; } if (fabsf(sControlInput->cur.gyro_y) > 0.01f) { @@ -12037,11 +12037,11 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { // Y Axis temp1 = (this->stateFlags1 & PLAYER_STATE1_ON_HORSE) ? 3500 : 14000; - if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) { + if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) { temp3 += ((sControlInput->rel.stick_y >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(sControlInput->rel.stick_y * 200)) * 1500.0f) * invertYAxisMulti * yAxisMulti; } - if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0) && fabsf(sControlInput->cur.right_stick_y) > 15.0f) { temp3 += ((sControlInput->cur.right_stick_y >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(sControlInput->cur.right_stick_y * 200)) * 1500.0f) * invertYAxisMulti * yAxisMulti; } @@ -12055,11 +12055,11 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { temp1 = 19114; temp2 = this->actor.focus.rot.y - this->actor.shape.rot.y; temp3 = 0; - if (!CVarGetInteger("gMoveWhileFirstPerson", 0)) { + if (!CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) { temp3 = ((sControlInput->rel.stick_x >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(sControlInput->rel.stick_x * 200)) * -1500.0f) * invertXAxisMulti * xAxisMulti; } - if (CVarGetInteger("gRightStickAiming", 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) { + if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0) && fabsf(sControlInput->cur.right_stick_x) > 15.0f) { temp3 += ((sControlInput->cur.right_stick_x >= 0) ? 1 : -1) * (s32)((1.0f - Math_CosS(sControlInput->cur.right_stick_x * 200)) * -1500.0f) * invertXAxisMulti * xAxisMulti; } @@ -12070,7 +12070,7 @@ s16 func_8084ABD8(PlayState* play, Player* this, s32 arg2, s16 arg3) { this->actor.focus.rot.y = CLAMP(temp2, -temp1, temp1) + this->actor.shape.rot.y; } - if (CVarGetInteger("gMoveWhileFirstPerson", 0)) { + if (CVarGetInteger(CVAR_SETTING("MoveInFirstPerson"), 0)) { f32 movementSpeed = LINK_IS_ADULT ? 9.0f : 8.25f; if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { movementSpeed *= 1.5f; @@ -12109,18 +12109,18 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { // #region SOH [Enhancement] f32 swimMod = 1.0f; - if (CVarGetInteger("gEnableWalkModify", 0) == 1) { - if (CVarGetInteger("gWalkSpeedToggle", 0) == 1) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0) == 1) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.SpeedToggle"), 0) == 1) { if (gWalkSpeedToggle1) { - swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f); + swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping1"), 1.0f); } else if (gWalkSpeedToggle2) { - swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f); + swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping2"), 1.0f); } } else { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { - swimMod *= CVarGetFloat("gSwimModifierOne", 1.0f); + swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping1"), 1.0f); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { - swimMod *= CVarGetFloat("gSwimModifierTwo", 1.0f); + swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping2"), 1.0f); } } temp1 = this->skelAnime.curFrame - 10.0f; @@ -12268,7 +12268,7 @@ void Player_Action_8084B1D8(Player* this, PlayState* play) { } u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; - if (CVarGetInteger("gDpadEquips", 0) != 0) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if ((this->csAction != 0) || (this->unk_6AD == 0) || (this->unk_6AD >= 4) || func_80833B54(this) || @@ -12707,7 +12707,7 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) { if ((this->av1.actionVar1 != 0) && (sp80 != 0)) { anim2 = this->ageProperties->unk_BC[this->av2.actionVar2]; - if (CVarGetInteger("gMirroredWorld", 0) ? (sp80 < 0) : (sp80 > 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? (sp80 < 0) : (sp80 > 0)) { this->skelAnime.prevTransl = this->ageProperties->unk_7A[this->av2.actionVar2]; Player_AnimPlayOnce(play, this, anim2); } else { @@ -13356,7 +13356,7 @@ void func_8084DBC4(PlayState* play, Player* this, f32 arg2) { func_8084AEEC(this, &this->linearVelocity, sp2C * 0.5f, sp2A); // Original implementation of func_8084AEEC (SurfaceWithoutSwimMod) to prevent velocity increases via swim mod which push Link into the air // #region SOH [Enhancement] - if (CVarGetInteger("gEnableWalkModify", 0)) { + if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) { SurfaceWithoutSwimMod(this, &this->actor.velocity.y, arg2, this->yaw); // #endregion } else { @@ -14413,9 +14413,9 @@ s32 func_8084FCAC(Player* this, PlayState* play) { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DDOWN)) { angle = temp + 0x8000; } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DLEFT)) { - angle = temp + (0x4000 * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1)); + angle = temp + (0x4000 * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1)); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_DRIGHT)) { - angle = temp - (0x4000 * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1)); + angle = temp - (0x4000 * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1)); } this->actor.world.pos.x += speed * Math_SinS(angle); diff --git a/soh/src/overlays/effects/ovl_Effect_Ss_Extra/z_eff_ss_extra.c b/soh/src/overlays/effects/ovl_Effect_Ss_Extra/z_eff_ss_extra.c index fe92d8a3f..014541ee0 100644 --- a/soh/src/overlays/effects/ovl_Effect_Ss_Extra/z_eff_ss_extra.c +++ b/soh/src/overlays/effects/ovl_Effect_Ss_Extra/z_eff_ss_extra.c @@ -62,7 +62,7 @@ void EffectSsExtra_Draw(PlayState* play, u32 index, EffectSs* this) { s32 pad; f32 scale = this->rScale / 100.0f; void* object = play->objectCtx.status[this->rObjBankIdx].segment; - u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0); + u8 mirroredWorld = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0); OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index f43cf7a74..bb22c90ae 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -673,7 +673,7 @@ void Sram_InitDebugSave(void); void Sram_InitBossRushSave(); u8 hasRandomizerQuest() { - if (strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0) { + if (strnlen(CVarGetString(CVAR_GENERAL("SpoilerLog"), ""), 1) != 0) { return 1; } return 0; @@ -991,7 +991,7 @@ void DrawSeedHashSprites(FileChooseContext* this) { // Draw Seed Icons for spoiler log if (this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER && - strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 && fileSelectSpoilerFileLoaded) { + strnlen(CVarGetString(CVAR_GENERAL("SpoilerLog"), ""), 1) != 0 && fileSelectSpoilerFileLoaded) { u16 xStart = 64; for (unsigned int i = 0; i < 5; i++) { SpriteLoad(this, GetSeedTexture(gSaveContext.seedIcons[i])); @@ -1008,12 +1008,12 @@ void DrawSeedHashSprites(FileChooseContext* this) { u8 generating; void FileChoose_UpdateRandomizer() { - if (CVarGetInteger("gRandoGenerating", 0) != 0 && generating == 0) { + if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) != 0 && generating == 0) { generating = 1; func_800F5E18(SEQ_PLAYER_BGM_MAIN, NA_BGM_HORSE, 0, 7, 1); return; - } else if (CVarGetInteger("gRandoGenerating", 0) == 0 && generating) { - if (SpoilerFileExists(CVarGetString("gSpoilerLog", ""))) { + } else if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) == 0 && generating) { + if (SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), ""))) { Audio_PlayFanfare(NA_BGM_HORSE_GOAL); } else { func_80078884(NA_SE_SY_OCARINA_ERROR); @@ -1025,25 +1025,25 @@ void FileChoose_UpdateRandomizer() { return; } - if (!SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && !CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { - CVarSetString("gSpoilerLog", ""); + if (!SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), "")) && !CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { + CVarSetString(CVAR_GENERAL("SpoilerLog"), ""); fileSelectSpoilerFileLoaded = false; } - if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) || - (!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString("gSpoilerLog", "")))) { - if (CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) { - CVarSetString("gSpoilerLog", CVarGetString("gRandomizerDroppedFile", "None")); + if ((CVarGetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 0) != 0) || (CVarGetInteger(CVAR_GENERAL("NewSeedGenerated"), 0) != 0) || + (!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), "")))) { + if (CVarGetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 0) != 0) { + CVarSetString(CVAR_GENERAL("SpoilerLog"), CVarGetString(CVAR_GENERAL("RandomizerDroppedFile"), "None")); } bool silent = true; - if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) { + if ((CVarGetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 0) != 0) || (CVarGetInteger(CVAR_GENERAL("NewSeedGenerated"), 0) != 0)) { silent = false; } - CVarSetInteger("gNewSeedGenerated", 0); - CVarSetInteger("gRandomizerNewFileDropped", 0); - CVarSetString("gRandomizerDroppedFile", ""); + CVarSetInteger(CVAR_GENERAL("NewSeedGenerated"), 0); + CVarSetInteger(CVAR_GENERAL("RandomizerNewFileDropped"), 0); + CVarSetString(CVAR_GENERAL("RandomizerDroppedFile"), ""); fileSelectSpoilerFileLoaded = false; - const char* fileLoc = CVarGetString("gSpoilerLog", ""); + const char* fileLoc = CVarGetString(CVAR_GENERAL("SpoilerLog"), ""); Randomizer_LoadSettings(fileLoc); Randomizer_LoadHintLocations(fileLoc); Randomizer_LoadRequiredTrials(fileLoc); @@ -1053,7 +1053,7 @@ void FileChoose_UpdateRandomizer() { Randomizer_LoadEntranceOverrides(fileLoc, silent); fileSelectSpoilerFileLoaded = true; - if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) && CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { + if (SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), "")) && CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { remove(fileLoc); } } @@ -1074,7 +1074,7 @@ void FileChoose_UpdateMainMenu(GameState* thisx) { static u8 linkName[] = { 0x15, 0x2C, 0x31, 0x2E, 0x3E, 0x3E, 0x3E, 0x3E }; FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); FileChoose_UpdateRandomizer(); @@ -1264,7 +1264,7 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; s8 i = 0; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); FileChoose_UpdateRandomizer(); @@ -1311,7 +1311,7 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) { this->prevConfigMode = this->configMode; this->configMode = CM_ROTATE_TO_NAME_ENTRY; this->logoAlpha = 0; - CVarSetInteger("gOnFileSelectNameEntry", 1); + CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 1); this->kbdButton = FS_KBD_BTN_NONE; this->charPage = FS_CHAR_PAGE_ENG; this->kbdX = 0; @@ -1340,7 +1340,7 @@ void FileChoose_UpdateBossRushMenu(GameState* thisx) { FileChoose_UpdateStickDirectionPromptAnim(thisx); FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); // Fade in elements after opening Boss Rush options menu this->bossRushUIAlpha += 25; @@ -2816,7 +2816,7 @@ void FileChoose_FadeInFileInfo(GameState* thisx) { void FileChoose_ConfirmFile(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (CHECK_BTN_ALL(input->press.button, BTN_START) || (CHECK_BTN_ALL(input->press.button, BTN_A))) { if (this->confirmButtonIndex == FS_BTN_CONFIRM_YES) { @@ -3016,21 +3016,6 @@ void FileChoose_LoadGame(GameState* thisx) { gSaveContext.naviTimer = 0; - // SWORDLESS LINK IS BACK BABY - if (CVarGetInteger("gSwordlessLink", 0) != 0) - { - if ((gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI) && - (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_MASTER) && - (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_BGS) && - (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KNIFE)) { - - gSaveContext.equips.buttonItems[0] = ITEM_NONE; - swordEquipValue = (BOMSWAP16(gEquipMasks[EQUIP_TYPE_SWORD]) & gSaveContext.equips.equipment) >> (EQUIP_TYPE_SWORD * 4); - gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SWORD]; - gSaveContext.inventory.equipment ^= (gBitFlags[swordEquipValue - 1] << BOMSWAP16(gEquipShifts[EQUIP_TYPE_SWORD])); - } - } - if (IS_RANDO) { // Setup the modified entrance table and entrance shuffle table for rando Entrance_Init(); @@ -3313,7 +3298,7 @@ void FileChoose_Main(GameState* thisx) { this->stickRelX = input->rel.stick_x; this->stickRelY = input->rel.stick_y; - if (CVarGetInteger("gDpadHoldChange", 1) && CVarGetInteger("gDpadText", 0)) { + if (CVarGetInteger(CVAR_SETTING("DpadHoldChange"), 1) && CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { if (CHECK_BTN_ALL(input->cur.button, BTN_DLEFT)) { if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { this->inputTimerX = 10; @@ -3661,7 +3646,7 @@ void FileChoose_Init(GameState* thisx) { this->questType[2] = MIN_QUEST; fileSelectSpoilerFileLoaded = false; isFastFileIdIncompatible = 0; - CVarSetInteger("gOnFileSelectNameEntry", 0); + CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0); SREG(30) = 1; osSyncPrintf("SIZE=%x\n", size); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c index 6f155e367..3080eb14f 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c @@ -64,7 +64,7 @@ static s16 sLastCopyEraseButtonIndex; void FileChoose_SelectCopySource(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || CHECK_BTN_ALL(input->press.button, BTN_B)) { @@ -181,7 +181,7 @@ void FileChoose_SetupCopyDest2(GameState* thisx) { void FileChoose_SelectCopyDest(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || CHECK_BTN_ALL(input->press.button, BTN_B)) { @@ -370,7 +370,7 @@ void FileChoose_CopyConfirm(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; u16 dayTime; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (((this->buttonIndex != FS_BTN_CONFIRM_YES) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || CHECK_BTN_ALL(input->press.button, BTN_B)) { @@ -695,7 +695,7 @@ void FileChoose_SetupEraseSelect(GameState* thisx) { void FileChoose_EraseSelect(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || CHECK_BTN_ALL(input->press.button, BTN_B)) { @@ -837,7 +837,7 @@ void FileChoose_SetupEraseConfirm2(GameState* thisx) { void FileChoose_EraseConfirm(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (((this->buttonIndex != FS_BTN_CONFIRM_YES) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || CHECK_BTN_ALL(input->press.button, BTN_B)) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c index 525f5ac28..26c24e37d 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c @@ -380,7 +380,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) { } this->prevConfigMode = CM_NAME_ENTRY; sLastCharIndex = -1; - CVarSetInteger("gOnFileSelectNameEntry", 0); + CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0); } else { for (i = this->newFileNameCharCount; i < 7; i++) { filename[i] = filename[i + 1]; @@ -455,7 +455,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) { gSaveContext.dayTime = dayTime; this->prevConfigMode = CM_MAIN_MENU; this->configMode = CM_NAME_ENTRY_TO_MAIN; - CVarSetInteger("gOnFileSelectNameEntry", 0); + CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0); this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200; this->connectorAlpha[this->buttonIndex] = 255; func_800AA000(300.0f, 0xB4, 0x14, 0x64); @@ -527,7 +527,7 @@ void FileChoose_UpdateKeyboardCursor(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; s16 prevKbdX; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); this->kbdButton = 99; @@ -683,7 +683,7 @@ static s8 sLastOptionButtonIndex = -1; void FileChoose_UpdateOptionsMenu(GameState* thisx) { FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - bool dpad = CVarGetInteger("gDpadText", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0); if (CHECK_BTN_ALL(input->press.button, BTN_B)) { Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -753,7 +753,7 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { // Persist the new language so it is not overridden on the next frame if (languageChanged) { - CVarSetInteger("gLanguages", gSaveContext.language); + CVarSetInteger(CVAR_SETTING("Languages"), gSaveContext.language); GameInteractor_ExecuteOnSetGameLanguage(); } diff --git a/soh/src/overlays/gamestates/ovl_select/z_select.c b/soh/src/overlays/gamestates/ovl_select/z_select.c index 65c23b685..f4d577c5c 100644 --- a/soh/src/overlays/gamestates/ovl_select/z_select.c +++ b/soh/src/overlays/gamestates/ovl_select/z_select.c @@ -45,9 +45,9 @@ void Select_LoadGame(SelectContext* this, s32 entranceIndex) { } if (this->isBetterWarp) { - CVarSetInteger("gBetterDebugWarpScreenCurrentScene", this->currentScene); - CVarSetInteger("gBetterDebugWarpScreenTopDisplayedScene", this->topDisplayedScene); - CVarSetInteger("gBetterDebugWarpScreenPageDownIndex", this->pageDownIndex); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenCurrentScene"), this->currentScene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenTopDisplayedScene"), this->topDisplayedScene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenPageDownIndex"), this->pageDownIndex); CVarSave(); if (ResourceMgr_GameHasMasterQuest() && ResourceMgr_GameHasOriginal()) { @@ -57,11 +57,11 @@ void Select_LoadGame(SelectContext* this, s32 entranceIndex) { s16 scene = gEntranceTable[entrancePair.entranceIndex].scene; u8 isEntranceDefaultMQ = ResourceMgr_IsSceneMasterQuest(scene); if (!isEntranceDefaultMQ && this->opt) { // Force vanilla for default MQ scene - CVarSetInteger("gBetterDebugWarpScreenMQMode", WARP_MODE_OVERRIDE_MQ_AS_VANILLA); - CVarSetInteger("gBetterDebugWarpScreenMQModeScene", scene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQMode"), WARP_MODE_OVERRIDE_MQ_AS_VANILLA); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene"), scene); } else if (isEntranceDefaultMQ && !this->opt) { // Force MQ for default vanilla scene - CVarSetInteger("gBetterDebugWarpScreenMQMode", WARP_MODE_OVERRIDE_VANILLA_AS_MQ); - CVarSetInteger("gBetterDebugWarpScreenMQModeScene", scene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQMode"), WARP_MODE_OVERRIDE_VANILLA_AS_MQ); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene"), scene); } } } @@ -111,9 +111,9 @@ void Select_Grotto_LoadGame(SelectContext* this, s32 grottoIndex) { } if (this->isBetterWarp) { - CVarSetInteger("gBetterDebugWarpScreenCurrentScene", this->currentScene); - CVarSetInteger("gBetterDebugWarpScreenTopDisplayedScene", this->topDisplayedScene); - CVarSetInteger("gBetterDebugWarpScreenPageDownIndex", this->pageDownIndex); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenCurrentScene"), this->currentScene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenTopDisplayedScene"), this->topDisplayedScene); + CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenPageDownIndex"), this->pageDownIndex); CVarSave(); } @@ -1564,13 +1564,13 @@ void Select_SwitchBetterWarpMode(SelectContext* this, u8 isBetterWarpMode) { gSaveContext.dayTime = 0x8000; if (isBetterWarpMode) { - s32 currScene = CVarGetInteger("gBetterDebugWarpScreenCurrentScene", 0); + s32 currScene = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenCurrentScene"), 0); this->count = ARRAY_COUNT(sBetterScenes); if (currScene >= 0 && currScene < this->count) { this->currentScene = currScene; - this->topDisplayedScene = CVarGetInteger("gBetterDebugWarpScreenTopDisplayedScene", 0); - this->pageDownIndex = CVarGetInteger("gBetterDebugWarpScreenPageDownIndex", 0); + this->topDisplayedScene = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenTopDisplayedScene"), 0); + this->pageDownIndex = CVarGetInteger(CVAR_GENERAL("BetterDebugWarpScreenPageDownIndex"), 0); BetterSceneSelectEntrancePair entrancePair = this->betterScenes[this->currentScene].entrancePairs[this->pageDownIndex]; if (entrancePair.canBeMQ && ResourceMgr_IsSceneMasterQuest(gEntranceTable[entrancePair.entranceIndex].scene)) { @@ -1637,7 +1637,7 @@ void Select_Init(GameState* thisx) { gSaveContext.nightFlag = 0; gSaveContext.dayTime = 0x8000; - CVarClear("gBetterDebugWarpScreenMQMode"); - CVarClear("gBetterDebugWarpScreenMQModeScene"); + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQMode")); + CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene")); Select_SwitchBetterWarpMode(this, CVarGetInteger(CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"), 0)); } diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 617edba1b..51d0ac62b 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -204,7 +204,7 @@ void Title_Draw(TitleContext* this) { } // Draw ice cube around N64 logo. - if (CVarGetInteger("gLetItSnow", 0)) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { f32 scale = 0.4f; gSPSegment(POLY_OPA_DISP++, 0x08, diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c index 80d47ea4f..72f07b522 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c @@ -103,7 +103,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { s16 pad2; s16 phi_s0_2; s16 sp208[3]; - bool dpad = CVarGetInteger("gDpadPause", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); OPEN_DISPS(gfxCtx); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 9d699db90..99ba5df72 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -143,7 +143,7 @@ void KaleidoScope_DrawPlayerWork(PlayState* play) { pos.y = -130.0f; pos.z = -150.0f; scale = 0.046f; - } else if (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) != EQUIP_VALUE_SWORD_MASTER && !CVarGetInteger("gPauseTriforce", 0)) { + } else if (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) != EQUIP_VALUE_SWORD_MASTER && !CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0)) { pos.x = 25.0f; pos.y = -228.0f; pos.z = 60.0f; @@ -213,9 +213,9 @@ void KaleidoScope_DrawEquipment(PlayState* play) { s16 cursorX; s16 cursorY; s16 oldCursorPoint; - bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); + bool pauseAnyCursor = (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); OPEN_DISPS(play->state.gfxCtx); @@ -552,7 +552,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { } u16 buttonsToCheck = BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; - if (CVarGetInteger("gDpadEquips", 0) && (!CVarGetInteger("gDpadPause", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) && (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 40d00a1a4..6cc02aa03 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -252,7 +252,7 @@ void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 canCycle, u8 void KaleidoScope_HandleItemCycleExtras(PlayState* play, u8 slot, bool canCycle, u8 leftItem, u8 rightItem, bool replaceCButtons) { Input* input = &play->state.input[0]; PauseContext* pauseCtx = &play->pauseCtx; - bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); + bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); u8 slotItem = gSaveContext.inventory.items[slot]; u8 hasLeftItem = leftItem != ITEM_NONE && slotItem != leftItem; u8 hasRightItem = rightItem != ITEM_NONE && slotItem != rightItem && leftItem != rightItem; @@ -414,9 +414,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { s16 cursorY; s16 oldCursorPoint; s16 moveCursorResult; - bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); + bool dpad = (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); + bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); OPEN_DISPS(play->state.gfxCtx); @@ -669,7 +669,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { if ((pauseCtx->debugState == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0)) { KaleidoScope_HandleItemCycles(play); u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; - if (CVarGetInteger("gDpadEquips", 0) && (!CVarGetInteger("gDpadPause", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { + if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) && (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (CHECK_BTN_ANY(input->press.button, buttonsToCheck)) { @@ -803,7 +803,7 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, pauseCtx->equipTargetCBtn = 1; } else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { pauseCtx->equipTargetCBtn = 2; - } else if (CVarGetInteger("gDpadEquips", 0)) { + } else if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0)) { if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { pauseCtx->equipTargetCBtn = 3; } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { @@ -858,10 +858,10 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { u16 offsetX; u16 offsetY; - s16 Top_HUD_Margin = CVarGetInteger("gHUDMargin_T", 0); - s16 Left_HUD_Margin = CVarGetInteger("gHUDMargin_L", 0); - s16 Right_HUD_Margin = CVarGetInteger("gHUDMargin_R", 0); - s16 Bottom_HUD_Margin = CVarGetInteger("gHUDMargin_B", 0); + s16 Top_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + s16 Left_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + s16 Right_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + s16 Bottom_HUD_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); s16 X_Margins_CL; s16 X_Margins_CR; @@ -873,36 +873,36 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { s16 Y_Margins_BtnB; s16 X_Margins_DPad_Items; s16 Y_Margins_DPad_Items; - if (CVarGetInteger(CVAR_COSMETIC("BButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.BButton.PosType"), 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; Y_Margins_BtnB = (Top_HUD_Margin*-1); } else { X_Margins_BtnB = 0; Y_Margins_BtnB = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 0) {X_Margins_CL = Right_HUD_Margin;}; Y_Margins_CL = (Top_HUD_Margin*-1); } else { X_Margins_CL = 0; Y_Margins_CL = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 0) {X_Margins_CR = Right_HUD_Margin;}; Y_Margins_CR = (Top_HUD_Margin*-1); } else { X_Margins_CR = 0; Y_Margins_CR = 0; } - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 0) {X_Margins_CD = Right_HUD_Margin;}; Y_Margins_CD = (Top_HUD_Margin*-1); } else { X_Margins_CD = 0; Y_Margins_CD = 0; } - if (CVarGetInteger("gDPadUseMargins", 0) != 0) { - if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; Y_Margins_DPad_Items = (Top_HUD_Margin*-1); } else { X_Margins_DPad_Items = 0; @@ -925,28 +925,28 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { }; //(X,Y) Used with custom position to place it properly. //DPadItems - if (CVarGetInteger("gDPadPosType", 0) != 0) { - sCButtonPosY[3] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up - sCButtonPosY[4] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down - sCButtonPosY[5] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left - sCButtonPosY[6] = CVarGetInteger("gDPadPosY", 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right - if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; - sCButtonPosX[3] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - sCButtonPosX[4] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - sCButtonPosX[5] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - sCButtonPosX[6] = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; - sCButtonPosX[3] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); - sCButtonPosX[4] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); - sCButtonPosX[5] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); - sCButtonPosX[6] = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); - } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None - sCButtonPosX[3] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[0][0]; - sCButtonPosX[4] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[1][0]; - sCButtonPosX[5] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[2][0]; - sCButtonPosX[6] = CVarGetInteger("gDPadPosX", 0)+DPad_ItemsOffset[3][0]; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) != 0) { + sCButtonPosY[3] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[0][1];//Up + sCButtonPosY[4] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[1][1];//Down + sCButtonPosY[5] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[2][1];//Left + sCButtonPosY[6] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosY"), 0)+Y_Margins_DPad_Items+DPad_ItemsOffset[3][1];//Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Left_HUD_Margin;}; + sCButtonPosX[3] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + sCButtonPosX[4] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + sCButtonPosX[5] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + sCButtonPosX[6] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.UseMargins"), 0) != 0) {X_Margins_DPad_Items = Right_HUD_Margin;}; + sCButtonPosX[3] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[0][0]); + sCButtonPosX[4] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[1][0]); + sCButtonPosX[5] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[2][0]); + sCButtonPosX[6] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+X_Margins_DPad_Items+DPad_ItemsOffset[3][0]); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[3] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[0][0]; + sCButtonPosX[4] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[1][0]; + sCButtonPosX[5] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[2][0]; + sCButtonPosX[6] = CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosX"), 0)+DPad_ItemsOffset[3][0]; } } else { sCButtonPosX[3] = OTRGetDimensionFromRightEdge(ItemIconPos_ori[3][0]); @@ -959,48 +959,48 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { sCButtonPosY[6] = ItemIconPos_ori[6][1]; } //C button Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) != 0) { - sCButtonPosY[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosY"), 0)+Y_Margins_CL; - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; - sCButtonPosX[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; - sCButtonPosX[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0)+X_Margins_CL); - } else if (CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosType"), 0) == 3) {//Anchor None - sCButtonPosX[0] = CVarGetInteger(CVAR_COSMETIC("CLeftButton.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) != 0) { + sCButtonPosY[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosY"), 0)+Y_Margins_CL; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Left_HUD_Margin;}; + sCButtonPosX[0] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.UseMargins"), 0) != 0) {X_Margins_CL = Right_HUD_Margin;}; + sCButtonPosX[0] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0)+X_Margins_CL); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[0] = CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.PosX"), 0); } } else { sCButtonPosX[0] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[0][0]); sCButtonPosY[0] = ItemIconPos_ori[0][1]; } //C Button down - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) != 0) { - sCButtonPosY[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosY"), 0)+Y_Margins_CD; - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; - sCButtonPosX[1] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; - sCButtonPosX[1] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0)+X_Margins_CD); - } else if (CVarGetInteger(CVAR_COSMETIC("CDownButton.PosType"), 0) == 3) {//Anchor None - sCButtonPosX[1] = CVarGetInteger(CVAR_COSMETIC("CDownButton.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) != 0) { + sCButtonPosY[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosY"), 0)+Y_Margins_CD; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Left_HUD_Margin;}; + sCButtonPosX[1] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.UseMargins"), 0) != 0) {X_Margins_CD = Right_HUD_Margin;}; + sCButtonPosX[1] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0)+X_Margins_CD); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[1] = CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.PosX"), 0); } } else { sCButtonPosX[1] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[1][0]); sCButtonPosY[1] = ItemIconPos_ori[1][1]; } //C button Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) != 0) { - sCButtonPosY[2] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosY"), 0)+Y_Margins_CR; - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; - sCButtonPosX[2] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; - sCButtonPosX[2] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0)+X_Margins_CR); - } else if (CVarGetInteger(CVAR_COSMETIC("CRightButton.PosType"), 0) == 3) {//Anchor None - sCButtonPosX[2] = CVarGetInteger(CVAR_COSMETIC("CRightButton.PosX"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) != 0) { + sCButtonPosY[2] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosY"), 0)+Y_Margins_CR; + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Left_HUD_Margin;}; + sCButtonPosX[2] = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.UseMargins"), 0) != 0) {X_Margins_CR = Right_HUD_Margin;}; + sCButtonPosX[2] = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0)+X_Margins_CR); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosType"), 0) == 3) {//Anchor None + sCButtonPosX[2] = CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.PosX"), 0); } } else { sCButtonPosX[2] = OTRGetRectDimensionFromRightEdge(ItemIconPos_ori[2][0]); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index dc574532c..8aba85040 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -54,7 +54,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { s16 stepG; s16 stepB; u16 rgba16; - bool dpad = CVarGetInteger("gDpadPause", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); OPEN_DISPS(gfxCtx); @@ -347,7 +347,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { gDPLoadTLUT_pal16(POLY_KAL_DISP++, 0, interfaceCtx->mapPalettesPulse[palettePulseIdx]); gDPSetTextureLUT(POLY_KAL_DISP++, G_TT_RGBA16); - u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0); + u8 mirroredWorld = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0); u8 mirrorMode = mirroredWorld ? G_TX_MIRROR : G_TX_NOMIRROR; // Offset the U value of each vertex to be in the mirror boundary for the map textures if (mirroredWorld) { @@ -443,8 +443,8 @@ void KaleidoScope_DrawWorldMap(PlayState* play, GraphicsContext* gfxCtx) { s16 stepR; s16 stepG; s16 stepB; - bool dpad = CVarGetInteger("gDpadPause", 0); - u8 mirroredWorld = CVarGetInteger("gMirroredWorld", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); + u8 mirroredWorld = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0); u8 mirrorMode = mirroredWorld ? G_TX_MIRROR : G_TX_NOMIRROR; OPEN_DISPS(gfxCtx); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_prompt.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_prompt.c index 0807b8356..80ab3da9e 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_prompt.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_prompt.c @@ -7,7 +7,7 @@ void KaleidoScope_UpdatePrompt(PlayState* play) { Input* input = &play->state.input[0]; s8 relStickX = input->rel.stick_x; s16 step; - bool dpad = CVarGetInteger("gDpadPause", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); if (((pauseCtx->state == 7) && (pauseCtx->unk_1EC == 1)) || (pauseCtx->state == 0xE) || (pauseCtx->state == 0x10)) { if ((pauseCtx->promptChoice == 0) && ((relStickX >= 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)))) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 8939b0c61..424c823d6 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -945,7 +945,7 @@ Gfx* KaleidoScope_QuadTextureIA4(Gfx* gfx, void* texture, s16 width, s16 height, } Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point) { - u8 mirrorMode = CVarGetInteger("gMirroredWorld", 0) ? G_TX_MIRROR : G_TX_NOMIRROR; + u8 mirrorMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; gDPLoadTextureBlock(gfx++, texture, G_IM_FMT_IA, G_IM_SIZ_8b, width, height, 0, mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gSP1Quadrangle(gfx++, point, point + 2, point + 3, point + 1, 0); @@ -1099,7 +1099,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { return; } - bool dpad = CVarGetInteger("gDpadPause", 0); + bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) { if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT))) { pauseCtx->pageSwitchTimer++; @@ -1273,7 +1273,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { } } - if (CVarGetInteger("gDpadHoldChange", 1) && CVarGetInteger("gDpadPause", 0)) { + if (CVarGetInteger(CVAR_SETTING("DpadHoldChange"), 1) && CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) { if (CHECK_BTN_ALL(input->cur.button, BTN_DLEFT)) { if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { D_8082AD44 = XREG(8); @@ -2061,8 +2061,8 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { } } else { bool pauseAnyCursor = - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); if (!pauseCtx->pageIndex && (!pauseAnyCursor || (gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE))) { // pageIndex == PAUSE_ITEM pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = WREG(49 + gSaveContext.language); @@ -2199,8 +2199,8 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { void KaleidoScope_UpdateNamePanel(PlayState* play) { PauseContext* pauseCtx = &play->pauseCtx; u16 sp2A; - bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool pauseAnyCursor = (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger(CVAR_SETTING("PauseAnyCursor"), 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); if ((pauseCtx->namedItem != pauseCtx->cursorItem[pauseCtx->pageIndex]) || ((pauseCtx->pageIndex == PAUSE_MAP) && (pauseCtx->cursorSpecialPos != 0))) { @@ -2868,7 +2868,7 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { for (phi_t3 = 1; phi_t3 < ARRAY_COUNT(gSaveContext.equips.buttonItems); phi_t3++, phi_t2 += 4) { if (gSaveContext.equips.cButtonSlots[phi_t3 - 1] != ITEM_NONE && - ((phi_t3 < 4) || CVarGetInteger("gDpadEquips", 0))) { + ((phi_t3 < 4) || CVarGetInteger(CVAR_SETTING("DpadEquips"), 0))) { phi_t4 = gSaveContext.equips.cButtonSlots[phi_t3 - 1] * 4; pauseCtx->itemVtx[phi_t2 + 0].v.ob[0] = pauseCtx->itemVtx[phi_t2 + 2].v.ob[0] = @@ -3267,7 +3267,7 @@ void KaleidoScope_Draw(PlayState* play) { func_800AAA50(&play->view, 15); // Flip the OPA and XLU projections again as the set view call above reset the original flips from z_play - if (CVarGetInteger("gMirroredWorld", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gSPMatrix(POLY_XLU_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gSPMatrix(POLY_OPA_DISP++, play->view.viewingPtr, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); @@ -3996,7 +3996,7 @@ void KaleidoScope_Update(PlayState* play) (CHECK_BTN_ALL(input->press.button, BTN_B) && IS_BOSS_RUSH)) { if (CVarGetInteger(CVAR_CHEAT("EasyPauseBuffer"), 0) || CVarGetInteger(CVAR_CHEAT("EasyInputBuffer"), 0)) { // Easy pause buffer is 13 frames, 12 for kaledio to end, and one more to advance a single frame - CVarSetInteger("gCheatEasyPauseBufferTimer", 13); + CVarSetInteger(CVAR_GENERAL("CheatEasyPauseBufferTimer"), 13); } Interface_SetDoAction(play, DO_ACTION_NONE); pauseCtx->state = 0x12; @@ -4560,7 +4560,7 @@ void KaleidoScope_Update(PlayState* play) R_UPDATE_RATE = 3; R_PAUSE_MENU_MODE = 0; - CVarSetInteger("gPauseTriforce", 0); + CVarSetInteger(CVAR_GENERAL("PauseTriforce"), 0); func_800981B8(&play->objectCtx); func_800418D0(&play->colCtx, play); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c index 37093a283..0de1d117a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c @@ -132,7 +132,7 @@ void PauseMapMark_DrawForDungeon(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); // Compute the offset to mirror icons over the map center (48) as an axis line - s16 mirrorOffset = CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset = (48 - markPoint->x) * 2 + 1 : 0; + s16 mirrorOffset = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? mirrorOffset = (48 - markPoint->x) * 2 + 1 : 0; Matrix_Push(); Matrix_Translate(GREG(92) + markPoint->x + mirrorOffset, GREG(93) + markPoint->y, 0.0f, MTXMODE_APPLY); From 0c69ff17c2525607cc28acc9d2097879218b3fae Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 5 May 2024 14:46:23 -0500 Subject: [PATCH 216/300] Fix two minor issues from merge --- soh/soh/Enhancements/randomizer/location_list.cpp | 1 + soh/soh/Enhancements/randomizer/randomizer.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 97d432de3..92a91f32a 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1,4 +1,5 @@ #include "static_data.h" +#include "z64save.h" #define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ea0b30bfb..de0295b30 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -329,13 +329,13 @@ void Randomizer::LoadMerchantMessages() { "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); } -std::map trialFlagToTrialKey = { - { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, Rando::TrialKey::LIGHT_TRIAL, }, - { EVENTCHKINF_COMPLETED_FOREST_TRIAL, Rando::TrialKey::FOREST_TRIAL, }, - { EVENTCHKINF_COMPLETED_FIRE_TRIAL, Rando::TrialKey::FIRE_TRIAL, }, - { EVENTCHKINF_COMPLETED_WATER_TRIAL, Rando::TrialKey::WATER_TRIAL, }, - { EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, Rando::TrialKey::SPIRIT_TRIAL, }, - { EVENTCHKINF_COMPLETED_SHADOW_TRIAL, Rando::TrialKey::SHADOW_TRIAL, } +std::map trialFlagToTrialKey = { + { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, TK_LIGHT_TRIAL, }, + { EVENTCHKINF_COMPLETED_FOREST_TRIAL, TK_FOREST_TRIAL, }, + { EVENTCHKINF_COMPLETED_FIRE_TRIAL, TK_FIRE_TRIAL, }, + { EVENTCHKINF_COMPLETED_WATER_TRIAL, TK_WATER_TRIAL, }, + { EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, TK_SPIRIT_TRIAL, }, + { EVENTCHKINF_COMPLETED_SHADOW_TRIAL, TK_SHADOW_TRIAL, } }; bool Randomizer::IsTrialRequired(s32 trialFlag) { From b4a30f708f9d3e0949214573ded543a0f4ef12a6 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 5 May 2024 16:29:02 -0500 Subject: [PATCH 217/300] Change GI_VB_ to VB_ (#4116) --- soh/soh/Enhancements/cheat_hook_handlers.cpp | 8 +- .../game-interactor/GameInteractor.h | 302 +++++++++--------- .../Enhancements/randomizer/hook_handlers.cpp | 188 +++++------ .../Enhancements/timesaver_hook_handlers.cpp | 136 ++++---- soh/src/code/z_demo.c | 22 +- soh/src/code/z_en_item00.c | 6 +- soh/src/code/z_message_PAL.c | 24 +- soh/src/code/z_onepointdemo.c | 4 +- .../ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c | 4 +- .../actors/ovl_Bg_Breakwall/z_bg_breakwall.c | 2 +- .../ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c | 2 +- .../ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c | 6 +- .../ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c | 4 +- .../z_bg_spot02_objects.c | 2 +- .../ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c | 4 +- .../actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c | 4 +- .../actors/ovl_Bg_Treemouth/z_bg_treemouth.c | 2 +- .../ovl_Boss_Ganondrof/z_boss_ganondrof.c | 4 +- .../overlays/actors/ovl_Demo_Du/z_demo_du.c | 4 +- .../overlays/actors/ovl_Demo_Im/z_demo_im.c | 8 +- .../overlays/actors/ovl_Demo_Sa/z_demo_sa.c | 4 +- .../actors/ovl_Door_Shutter/z_door_shutter.c | 4 +- .../actors/ovl_Door_Warp1/z_door_warp1.c | 32 +- .../overlays/actors/ovl_Elf_Msg/z_elf_msg.c | 4 +- soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c | 6 +- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c | 4 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 2 +- soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c | 4 +- .../ovl_En_Diving_Game/z_en_diving_game.c | 8 +- soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 4 +- .../actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c | 2 +- soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c | 18 +- soh/src/overlays/actors/ovl_En_Du/z_en_du.c | 8 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 10 +- soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 10 +- soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 14 +- soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c | 12 +- soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c | 4 +- soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c | 6 +- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 62 ++-- soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c | 8 +- soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c | 2 +- soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c | 2 +- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 2 +- soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c | 6 +- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 18 +- soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c | 18 +- soh/src/overlays/actors/ovl_En_Md/z_en_md.c | 4 +- soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c | 18 +- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 4 +- soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c | 4 +- .../actors/ovl_En_Niw_Lady/z_en_niw_lady.c | 10 +- .../ovl_En_Okarina_Tag/z_en_okarina_tag.c | 10 +- soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c | 2 +- soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c | 2 +- soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c | 4 +- soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c | 8 +- .../actors/ovl_En_Shopnuts/z_en_shopnuts.c | 2 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 6 +- soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c | 10 +- soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c | 6 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 8 +- soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 8 +- soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c | 8 +- .../overlays/actors/ovl_En_Toryo/z_en_toryo.c | 4 +- .../ovl_En_Wonder_Talk2/z_en_wonder_talk2.c | 4 +- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 30 +- soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c | 2 +- soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c | 4 +- .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 4 +- .../actors/ovl_Obj_Dekujr/z_obj_dekujr.c | 2 +- .../actors/ovl_Obj_Switch/z_obj_switch.c | 4 +- .../actors/ovl_player_actor/z_player.c | 16 +- 73 files changed, 597 insertions(+), 597 deletions(-) diff --git a/soh/soh/Enhancements/cheat_hook_handlers.cpp b/soh/soh/Enhancements/cheat_hook_handlers.cpp index cdc8333ce..c8565e8ab 100644 --- a/soh/soh/Enhancements/cheat_hook_handlers.cpp +++ b/soh/soh/Enhancements/cheat_hook_handlers.cpp @@ -14,13 +14,13 @@ extern PlayState* gPlayState; void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { - case GI_VB_DEKU_STICK_BREAK: { + case VB_DEKU_STICK_BREAK: { if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } break; } - case GI_VB_DEKU_STICK_BE_ON_FIRE: { + case VB_DEKU_STICK_BE_ON_FIRE: { if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { Player* player = GET_PLAYER(gPlayState); player->unk_860 = 200; // Keeps the stick's flame lit @@ -29,13 +29,13 @@ void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* op } break; } - case GI_VB_DEKU_STICK_BURN_OUT: { + case VB_DEKU_STICK_BURN_OUT: { if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } break; } - case GI_VB_DEKU_STICK_BURN_DOWN: { + case VB_DEKU_STICK_BURN_DOWN: { if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 84126099f..3a3a30d18 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -70,32 +70,32 @@ typedef enum { typedef enum { // Vanilla condition: gSaveContext.showTitleCard - GI_VB_SHOW_TITLE_CARD, + VB_SHOW_TITLE_CARD, // Opt: *EnWonderTalk2 - GI_VB_WONDER_TALK, + VB_WONDER_TALK, // Opt: *ElfMsg - GI_VB_NAVI_TALK, + VB_NAVI_TALK, // Vanilla condition: INFTABLE_GREETED_BY_SARIA - GI_VB_NOT_BE_GREETED_BY_SARIA, + VB_NOT_BE_GREETED_BY_SARIA, // Opt: *EnMd // Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION - GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, + VB_MOVE_MIDO_IN_KOKIRI_FOREST, // Opt: *EnMd // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) - GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, + VB_MIDO_CONSIDER_DEKU_TREE_DEAD, // Opt: *ObjDekujr // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) - GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, + VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, // Opt: *EnKo // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) - GI_VB_OPEN_KOKIRI_FOREST, + VB_OPEN_KOKIRI_FOREST, // Opt: *EnOwl // Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist - GI_VB_OWL_INTERACTION, + VB_OWL_INTERACTION, // Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE - GI_VB_MALON_RETURN_FROM_CASTLE, + VB_MALON_RETURN_FROM_CASTLE, // Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0 - GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, + VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, /* Vanilla condition: ``` LINK_IS_ADULT && @@ -105,18 +105,18 @@ typedef enum { !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); ``` */ - GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, + VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, // Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA) - GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, + VB_BE_ELIGIBLE_FOR_SARIAS_SONG, // Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA) - GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, + VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) - GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, + VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, // Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT - GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, + VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, // Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP - GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, - GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, + VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, + VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, /* Vanilla Condition: ``` LINK_IS_ADULT && @@ -127,30 +127,30 @@ typedef enum { !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); ``` */ - GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, + VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, // Opt: *EnGo2 // Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12 - GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, + VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, // Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) - GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, + VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, // Opt: *EnMs // Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT] - GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, + VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, // Opt: *EnItem00 // Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag) - GI_VB_ITEM00_DESPAWN, + VB_ITEM00_DESPAWN, // Opt: *EnTk // Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD - GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, + VB_DAMPE_IN_GRAVEYARD_DESPAWN, // Opt: *EnTk // Vanilla condition: this->validDigHere == 1 - GI_VB_BE_VALID_GRAVEDIGGING_SPOT, + VB_BE_VALID_GRAVEDIGGING_SPOT, // Opt: *EnTk // Vanilla condition: this->currentReward == 3 - GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, + VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, // Opt: *EnTk // Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C) - GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, + VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, // Opt: *EnShopnuts /* Vanilla Condition: ``` @@ -159,235 +159,235 @@ typedef enum { ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))) ``` */ - GI_VB_BUSINESS_SCRUB_DESPAWN, + VB_BUSINESS_SCRUB_DESPAWN, // Opt: *EnCow // Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) - GI_VB_DESPAWN_HORSE_RACE_COW, + VB_DESPAWN_HORSE_RACE_COW, // Opt: *EnHs // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) - GI_VB_DESPAWN_GROG, + VB_DESPAWN_GROG, // Opt: *EnKo // Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false; - GI_VB_SPAWN_LW_FADO, + VB_SPAWN_LW_FADO, // Opt: *EnMk - GI_VB_PLAY_EYEDROP_CREATION_ANIM, + VB_PLAY_EYEDROP_CREATION_ANIM, // Opt: *EnDs - GI_VB_PLAY_ODD_POTION_ANIM, + VB_PLAY_ODD_POTION_ANIM, // Opt: *EnMk // Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS - GI_VB_USE_EYEDROP_DIALOGUE, + VB_USE_EYEDROP_DIALOGUE, // Opt: *EnMk // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) - GI_VB_OFFER_BLUE_POTION, + VB_OFFER_BLUE_POTION, // Vanilla condition: Inventory_HasEmptyBottle() == 0 - GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, + VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, // Opt: *EnNiwLady - GI_VB_SET_CUCCO_COUNT, + VB_SET_CUCCO_COUNT, // Opt: *EnKz // Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) - GI_VB_KING_ZORA_THANK_CHILD, + VB_KING_ZORA_THANK_CHILD, // Opt: *EnKz // Vanilla condition: this->actor.textId == 0x401A - GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, + VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, // Opt: *EnKz // Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) - GI_VB_KING_ZORA_BE_MOVED, + VB_KING_ZORA_BE_MOVED, // Vanilla condition: gSaveState.bgsFlag - GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, + VB_BIGGORON_CONSIDER_TRADE_COMPLETE, // Vanilla condition: gSaveState.bgsFlag - GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, + VB_BIGGORON_CONSIDER_SWORD_COLLECTED, // Vanilla condition: Environment_GetBgsDayCount() >= 3 - GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, + VB_BIGGORON_CONSIDER_SWORD_FORGED, // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) - GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, + VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, // Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY) - GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, + VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, // Opt: *uint16_t // Vanilla condition: false - GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, + VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON) - GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, + VB_GORONS_CONSIDER_TUNIC_COLLECTED, // Opt: *EnSyatekiMan // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) - GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, + VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, // Opt: *EnOkarinaTag // Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME) - GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, + VB_BE_ELIGIBLE_TO_OPEN_DOT, // Opt: *BgDyYoseizo // Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c - GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, + VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, // Vanilla condition: see CheckCarpentersFreed in z_en_ge1 and z_en_ge2 - GI_VB_GERUDOS_BE_FRIENDLY, + VB_GERUDOS_BE_FRIENDLY, // Vanilla condition: switch - GI_VB_GTG_GATE_BE_OPEN, + VB_GTG_GATE_BE_OPEN, /*** Play Cutscenes ***/ - GI_VB_PLAY_TRANSITION_CS, + VB_PLAY_TRANSITION_CS, // Opt: *EventChkInf flag - GI_VB_PLAY_ENTRANCE_CS, + VB_PLAY_ENTRANCE_CS, // Opt: *cutsceneId - GI_VB_PLAY_ONEPOINT_CS, + VB_PLAY_ONEPOINT_CS, // Opt: *actor - GI_VB_PLAY_ONEPOINT_ACTOR_CS, + VB_PLAY_ONEPOINT_ACTOR_CS, // Opt: *BgTreemouth - GI_VB_PLAY_DEKU_TREE_INTRO_CS, + VB_PLAY_DEKU_TREE_INTRO_CS, // Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true - GI_VB_PLAY_BLUE_WARP_CS, - GI_VB_PLAY_DARUNIAS_JOY_CS, - GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, + VB_PLAY_BLUE_WARP_CS, + VB_PLAY_DARUNIAS_JOY_CS, + VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, // Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL - GI_VB_PLAY_PULL_MASTER_SWORD_CS, - GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, + VB_PLAY_PULL_MASTER_SWORD_CS, + VB_PLAY_DROP_FISH_FOR_JABU_CS, // Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER - GI_VB_PLAY_NABOORU_CAPTURED_CS, - GI_VB_PLAY_ZELDAS_LULLABY_CS, + VB_PLAY_NABOORU_CAPTURED_CS, + VB_PLAY_ZELDAS_LULLABY_CS, // Opt: *EnSa - GI_VB_PLAY_SARIAS_SONG_CS, - GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, - GI_VB_PLAY_MINUET_OF_FOREST_CS, - GI_VB_PLAY_BOLERO_OF_FIRE_CS, - GI_VB_PLAY_SERENADE_OF_WATER_CS, - GI_VB_PLAY_EYEDROPS_CS, + VB_PLAY_SARIAS_SONG_CS, + VB_PLAY_PRELUDE_OF_LIGHT_CS, + VB_PLAY_MINUET_OF_FOREST_CS, + VB_PLAY_BOLERO_OF_FIRE_CS, + VB_PLAY_SERENADE_OF_WATER_CS, + VB_PLAY_EYEDROPS_CS, // Opt: *EnOkarinaTag - GI_VB_PLAY_DRAIN_WELL_CS, + VB_PLAY_DRAIN_WELL_CS, // Opt: *EnOkarinaTag // Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SUN) - GI_VB_PLAY_SUNS_SONG_CS, + VB_PLAY_SUNS_SONG_CS, // Opt: *EnOkarinaTag - GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, - GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, + VB_PLAY_ROYAL_FAMILY_TOMB_CS, + VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, // Opt: *EnOkarinaTag - GI_VB_PLAY_DOOR_OF_TIME_CS, - GI_VB_PLAY_RAINBOW_BRIDGE_CS, + VB_PLAY_DOOR_OF_TIME_CS, + VB_PLAY_RAINBOW_BRIDGE_CS, /*** Give Items ***/ // Opt: *EnBox - GI_VB_GIVE_ITEM_FROM_CHEST, - GI_VB_GIVE_ITEM_FROM_BLUE_WARP, + VB_GIVE_ITEM_FROM_CHEST, + VB_GIVE_ITEM_FROM_BLUE_WARP, // Opt: *EnItem00 - GI_VB_GIVE_ITEM_FROM_ITEM_00, + VB_GIVE_ITEM_FROM_ITEM_00, // Opt: *EnSi - GI_VB_GIVE_ITEM_SKULL_TOKEN, + VB_GIVE_ITEM_SKULL_TOKEN, // Opt: *EnCow - GI_VB_GIVE_ITEM_FROM_COW, + VB_GIVE_ITEM_FROM_COW, // Opt: *EnDns - GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, + VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, // Opt: *EnMk - GI_VB_GIVE_ITEM_FROM_LAB_DIVE, + VB_GIVE_ITEM_FROM_LAB_DIVE, // Opt: *EnDs - GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, + VB_GIVE_ITEM_FROM_GRANNYS_SHOP, // Opt: *EnNiwLady - GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, + VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, // Opt: *EnNiwLady - GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, + VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, // Opt: *EnKz // Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) - GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, // Opt: *EnGo2 - GI_VB_GIVE_ITEM_FROM_GORON, + VB_GIVE_ITEM_FROM_GORON, // Opt: *EnJs - GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, + VB_GIVE_ITEM_FROM_CARPET_SALESMAN, // Opt: *EnGm - GI_VB_GIVE_ITEM_FROM_MEDIGORON, + VB_GIVE_ITEM_FROM_MEDIGORON, // Opt: *EnMs - GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, + VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, // Opt: *EnFr - GI_VB_GIVE_ITEM_FROM_FROGS, + VB_GIVE_ITEM_FROM_FROGS, // Opt: *EnSkj - GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, + VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, // Opt: *EnSkj - GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, - GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, + VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, + VB_GIVE_ITEM_FROM_MAN_ON_ROOF, // Opt: *EnSyatekiMan - GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, + VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, // Opt: *EnExItem - GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, + VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, // Opt: *EnTa - GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, + VB_GIVE_ITEM_FROM_TALONS_CHICKENS, // Opt: *EnDivingGame - GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, + VB_GIVE_ITEM_FROM_DIVING_MINIGAME, // Opt: *EnGe1 - GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, + VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, // Opt: *EnSth - GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, + VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, // Opt: *EnHy - GI_VB_GIVE_ITEM_FROM_LOST_DOG, + VB_GIVE_ITEM_FROM_LOST_DOG, // Opt: *EnBomBowlPit - GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, + VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, - GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, + VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, - GI_VB_GIVE_ITEM_FAIRY_OCARINA, - GI_VB_GIVE_ITEM_WEIRD_EGG, - GI_VB_GIVE_ITEM_LIGHT_ARROW, - GI_VB_GIVE_ITEM_STRENGTH_1, - GI_VB_GIVE_ITEM_ZELDAS_LETTER, - GI_VB_GIVE_ITEM_MASTER_SWORD, - GI_VB_GIVE_ITEM_OCARINA_OF_TIME, - GI_VB_GIVE_ITEM_KOKIRI_EMERALD, - GI_VB_GIVE_ITEM_GORON_RUBY, - GI_VB_GIVE_ITEM_ZORA_SAPPHIRE, - GI_VB_GIVE_ITEM_LIGHT_MEDALLION, - GI_VB_GIVE_ITEM_FOREST_MEDALLION, - GI_VB_GIVE_ITEM_FIRE_MEDALLION, - GI_VB_GIVE_ITEM_WATER_MEDALLION, - GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, - GI_VB_GIVE_ITEM_SHADOW_MEDALLION, + VB_GIVE_ITEM_FAIRY_OCARINA, + VB_GIVE_ITEM_WEIRD_EGG, + VB_GIVE_ITEM_LIGHT_ARROW, + VB_GIVE_ITEM_STRENGTH_1, + VB_GIVE_ITEM_ZELDAS_LETTER, + VB_GIVE_ITEM_MASTER_SWORD, + VB_GIVE_ITEM_OCARINA_OF_TIME, + VB_GIVE_ITEM_KOKIRI_EMERALD, + VB_GIVE_ITEM_GORON_RUBY, + VB_GIVE_ITEM_ZORA_SAPPHIRE, + VB_GIVE_ITEM_LIGHT_MEDALLION, + VB_GIVE_ITEM_FOREST_MEDALLION, + VB_GIVE_ITEM_FIRE_MEDALLION, + VB_GIVE_ITEM_WATER_MEDALLION, + VB_GIVE_ITEM_SPIRIT_MEDALLION, + VB_GIVE_ITEM_SHADOW_MEDALLION, /*** Give Songs ***/ - GI_VB_GIVE_ITEM_ZELDAS_LULLABY, - GI_VB_GIVE_ITEM_SARIAS_SONG, - GI_VB_GIVE_ITEM_EPONAS_SONG, - GI_VB_GIVE_ITEM_SUNS_SONG, - GI_VB_GIVE_ITEM_SONG_OF_TIME, - GI_VB_GIVE_ITEM_SONG_OF_STORMS, - GI_VB_GIVE_ITEM_MINUET_OF_FOREST, - GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, - GI_VB_GIVE_ITEM_SERENADE_OF_WATER, - GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, - GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, - GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, + VB_GIVE_ITEM_ZELDAS_LULLABY, + VB_GIVE_ITEM_SARIAS_SONG, + VB_GIVE_ITEM_EPONAS_SONG, + VB_GIVE_ITEM_SUNS_SONG, + VB_GIVE_ITEM_SONG_OF_TIME, + VB_GIVE_ITEM_SONG_OF_STORMS, + VB_GIVE_ITEM_MINUET_OF_FOREST, + VB_GIVE_ITEM_BOLERO_OF_FIRE, + VB_GIVE_ITEM_SERENADE_OF_WATER, + VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, + VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, + VB_GIVE_ITEM_PRELUDE_OF_LIGHT, /*** Adult Trade ***/ // Opt: *EnNiwLady - GI_VB_TRADE_POCKET_CUCCO, + VB_TRADE_POCKET_CUCCO, // Opt: *EnHs - GI_VB_TRADE_COJIRO, + VB_TRADE_COJIRO, // Opt: *EnDs - GI_VB_TRADE_ODD_MUSHROOM, + VB_TRADE_ODD_MUSHROOM, // Opt: *EnKo - GI_VB_TRADE_ODD_POTION, + VB_TRADE_ODD_POTION, // Opt: *EnToryo - GI_VB_TRADE_SAW, + VB_TRADE_SAW, // Opt: *EnKz, - GI_VB_TRADE_PRESCRIPTION, + VB_TRADE_PRESCRIPTION, // Opt: *EnMk - GI_VB_TRADE_FROG, + VB_TRADE_FROG, - GI_VB_TRADE_TIMER_ODD_MUSHROOM, - GI_VB_TRADE_TIMER_EYEDROPS, - GI_VB_TRADE_TIMER_FROG, + VB_TRADE_TIMER_ODD_MUSHROOM, + VB_TRADE_TIMER_EYEDROPS, + VB_TRADE_TIMER_FROG, // Opt: *EnNiwLady - GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, + VB_ANJU_SET_OBTAINED_TRADE_ITEM, /*** Fixes ***/ // Vanilla condition: false - GI_VB_FIX_SAW_SOFTLOCK, + VB_FIX_SAW_SOFTLOCK, /*** Cheats? ***/ - GI_VB_DEKU_STICK_BE_ON_FIRE, - GI_VB_DEKU_STICK_BREAK, - GI_VB_DEKU_STICK_BURN_DOWN, - GI_VB_DEKU_STICK_BURN_OUT, - GI_VB_DEKU_UPDATE_BURNING_DEKU_STICK, + VB_DEKU_STICK_BE_ON_FIRE, + VB_DEKU_STICK_BREAK, + VB_DEKU_STICK_BURN_DOWN, + VB_DEKU_STICK_BURN_OUT, + VB_DEKU_UPDATE_BURNING_DEKU_STICK, /*** Quick Boss Deaths ***/ // Vanilla condition: true - GI_VB_PHANTOM_GANON_DEATH_SCENE, - GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, + VB_PHANTOM_GANON_DEATH_SCENE, + VB_NABOORU_KNUCKLE_DEATH_SCENE, } GIVanillaBehavior; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index bd71f7e0c..8360ece10 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -539,7 +539,7 @@ void RandomizerSetChestGameRandomizerInf(RandomizerCheck rc) { void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) { switch (id) { - case GI_VB_GIVE_ITEM_FROM_CHEST: { + case VB_GIVE_ITEM_FROM_CHEST: { EnBox* chest = static_cast(optionalArg); RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(chest->dyna.actor.id, gPlayState->sceneNum, chest->dyna.actor.params); @@ -553,38 +553,38 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_PLAY_NABOORU_CAPTURED_CS: + case VB_PLAY_NABOORU_CAPTURED_CS: // This behavior is replicated for randomizer in RandomizerOnItemReceiveHandler *should = false; break; - case GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: { + case VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: { *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !Flags_GetTreasure(gPlayState, 0x2); break; } - case GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER: + case VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER: *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetTreasure(gPlayState, 0x2); break; - case GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT: + case VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT: *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST); break; - case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + case VB_MOVE_MIDO_IN_KOKIRI_FOREST: if (RAND_GET_OPTION(RSK_FOREST) == RO_FOREST_OPEN) { *should = true; } break; - case GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD: + case VB_MIDO_CONSIDER_DEKU_TREE_DEAD: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); break; - case GI_VB_OPEN_KOKIRI_FOREST: + case VB_OPEN_KOKIRI_FOREST: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_FOREST_CLOSED; break; - case GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD: + case VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD: *should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY); break; - case GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS: + case VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS: *should = !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements(); break; - case GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW: + case VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW: *should = !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) && LINK_IS_ADULT && @@ -593,18 +593,18 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER); break; - case GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: { + case VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: { // Don't require a bomb bag to get prize in rando *should = true; break; } - case GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE: { + case VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE: { if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { *should = gSaveContext.rupees >= 60; } break; } - case GI_VB_GIVE_ITEM_MASTER_SWORD: + case VB_GIVE_ITEM_MASTER_SWORD: if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD)) { *should = false; } else { @@ -612,7 +612,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void Rando::Context::GetInstance()->GetItemLocation(RC_TOT_MASTER_SWORD)->MarkAsObtained(); } break; - case GI_VB_ITEM00_DESPAWN: { + case VB_ITEM00_DESPAWN: { EnItem00* item00 = static_cast(optionalArg); if (item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY) { RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(item00->actor.id, gPlayState->sceneNum, item00->ogParams); @@ -629,18 +629,18 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG: { + case VB_MALON_ALREADY_TAUGHT_EPONAS_SONG: { *should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); break; } - case GI_VB_SET_CUCCO_COUNT: { + case VB_SET_CUCCO_COUNT: { EnNiwLady* enNiwLady = static_cast(optionalArg); // Override starting Cucco count using setting value enNiwLady->cuccosInPen = 7 - RAND_GET_OPTION(RSK_CUCCO_COUNT); *should = false; break; } - case GI_VB_KING_ZORA_THANK_CHILD: { + case VB_KING_ZORA_THANK_CHILD: { // Allow turning in Ruto's letter even if you have already rescued her if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { GET_PLAYER(gPlayState)->exchangeItemId = EXCH_ITEM_LETTER_RUTO; @@ -648,11 +648,11 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); break; } - case GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: { + case VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: { *should = LINK_IS_CHILD; break; } - case GI_VB_KING_ZORA_BE_MOVED: { + case VB_KING_ZORA_BE_MOVED: { *should = false; switch (RAND_GET_OPTION(RSK_ZORAS_FOUNTAIN)) { case RO_ZF_CLOSED: @@ -673,29 +673,29 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED: { + case VB_BIGGORON_CONSIDER_SWORD_COLLECTED: { *should = Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); break; } - case GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE: { + case VB_BIGGORON_CONSIDER_TRADE_COMPLETE: { // This being true will prevent other biggoron trades, there are already safegaurds in place to prevent // claim check from being traded multiple times, so we don't really need the quest to ever be considered "complete" *should = false; break; } - case GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { + case VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); break; } - case GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED: { + case VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED: { *should = Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); break; } - case GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED: { + case VB_GORONS_CONSIDER_TUNIC_COLLECTED: { *should = Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); break; } - case GI_VB_GIVE_ITEM_FROM_ITEM_00: { + case VB_GIVE_ITEM_FROM_ITEM_00: { EnItem00* item00 = static_cast(optionalArg); if (item00->actor.params == ITEM00_SOH_DUMMY) { if (item00->randoInf != RAND_INF_MAX) { @@ -730,11 +730,11 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG: { + case VB_BE_ELIGIBLE_FOR_SARIAS_SONG: { *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); break; } - case GI_VB_GIVE_ITEM_FROM_COW: { + case VB_GIVE_ITEM_FROM_COW: { if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { break; } @@ -751,7 +751,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP: { + case VB_GIVE_ITEM_FROM_GRANNYS_SHOP: { if (!EnDs_RandoCanGetGrannyItem()) { break; } @@ -760,7 +760,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA: { + case VB_GIVE_ITEM_FROM_THAWING_KING_ZORA: { EnKz* enKz = static_cast(optionalArg); // If we aren't setting up the item offer, then we're just checking if it should be possible. if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { @@ -771,28 +771,28 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD: { + case VB_GIVE_ITEM_FROM_ANJU_AS_CHILD: { Flags_SetItemGetInf(ITEMGETINF_0C); *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: { + case VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: { Flags_SetItemGetInf(ITEMGETINF_2C); *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN: { + case VB_GIVE_ITEM_FROM_CARPET_SALESMAN: { *should = RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_OFF || // If the rando check has already been awarded, use vanilla behavior. Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); break; } - case GI_VB_GIVE_ITEM_FROM_MEDIGORON: { + case VB_GIVE_ITEM_FROM_MEDIGORON: { // fallthrough - case GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE: + case VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE: if (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - if (id == GI_VB_GIVE_ITEM_FROM_MEDIGORON) { + if (id == VB_GIVE_ITEM_FROM_MEDIGORON) { Flags_SetInfTable(INFTABLE_B1); *should = false; } else { @@ -803,7 +803,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN: { + case VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN: { EnMs* enMs = static_cast(optionalArg); if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { Rupees_ChangeBy(-60); @@ -815,7 +815,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_GIVE_ITEM_FROM_FROGS: { + case VB_GIVE_ITEM_FROM_FROGS: { EnFr* enFr = static_cast(optionalArg); // Skip GiveReward+SetIdle action func if the reward is an ice trap @@ -830,26 +830,26 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_TRADE_POCKET_CUCCO: { + case VB_TRADE_POCKET_CUCCO: { Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_POCKET_CUCCO); // Trigger the reward now Flags_SetItemGetInf(ITEMGETINF_2E); *should = false; break; } - case GI_VB_TRADE_COJIRO: { + case VB_TRADE_COJIRO: { Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_COJIRO); *should = false; break; } - case GI_VB_TRADE_ODD_MUSHROOM: { + case VB_TRADE_ODD_MUSHROOM: { Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_MUSHROOM); // Trigger the reward now Flags_SetItemGetInf(ITEMGETINF_30); *should = false; break; } - case GI_VB_TRADE_ODD_POTION: { + case VB_TRADE_ODD_POTION: { EnKo* enKo = static_cast(optionalArg); Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_POTION); // Trigger the reward now @@ -857,12 +857,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_TRADE_SAW: { + case VB_TRADE_SAW: { Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SAW); *should = false; break; } - case GI_VB_TRADE_PRESCRIPTION: { + case VB_TRADE_PRESCRIPTION: { EnKz* enKz = static_cast(optionalArg); // If we aren't setting up the item offer, then we're just checking if it should be possible. if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { @@ -873,12 +873,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_TRADE_FROG: { + case VB_TRADE_FROG: { Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_FROG); *should = false; break; } - case GI_VB_DESPAWN_HORSE_RACE_COW: { + case VB_DESPAWN_HORSE_RACE_COW: { if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { break; } @@ -887,7 +887,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void EnCow_MoveForRandomizer(enCow, gPlayState); break; } - case GI_VB_BUSINESS_SCRUB_DESPAWN: { + case VB_BUSINESS_SCRUB_DESPAWN: { EnShopnuts* enShopnuts = static_cast(optionalArg); s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); ScrubIdentity scrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enShopnuts->actor.params, respawnData); @@ -897,7 +897,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB: { + case VB_GIVE_ITEM_FROM_BUSINESS_SCRUB: { EnDns* enDns = static_cast(optionalArg); *should = !enDns->sohScrubIdentity.isShuffled; break; @@ -907,7 +907,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. // - If you don't have either but have traded the mushroom, don't spawn either. - case GI_VB_DESPAWN_GROG: { + case VB_DESPAWN_GROG: { if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { break; } @@ -920,7 +920,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_SPAWN_LW_FADO: { + case VB_SPAWN_LW_FADO: { if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { break; } @@ -933,23 +933,23 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void break; } - case GI_VB_USE_EYEDROP_DIALOGUE: { + case VB_USE_EYEDROP_DIALOGUE: { // Skip eye drop text on rando if Link went in the water, so you can still receive the dive check EnMk* enMk = static_cast(optionalArg); *should &= enMk->swimFlag == 0; break; } - case GI_VB_OFFER_BLUE_POTION: { + case VB_OFFER_BLUE_POTION: { // Always offer blue potion when adult trade is off *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF; break; } - case GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM: { + case VB_NEED_BOTTLE_FOR_GRANNYS_ITEM: { // Allow buying the rando item regardless of having a bottle *should &= !EnDs_RandoCanGetGrannyItem(); break; } - case GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY: { + case VB_GIVE_ITEM_FROM_SHOOTING_GALLERY: { EnSyatekiMan* enSyatekiMan = static_cast(optionalArg); enSyatekiMan->getItemId = GI_RUPEE_PURPLE; if (LINK_IS_ADULT) { @@ -961,7 +961,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD: { + case VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD: { *should = CUR_UPG_VALUE(UPG_QUIVER) > 0; if (!*should) { // In Rando without a quiver, display a message reminding the player to come back with a bow @@ -969,7 +969,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_BE_ELIGIBLE_TO_OPEN_DOT: { + case VB_BE_ELIGIBLE_TO_OPEN_DOT: { bool eligible = RAND_GET_OPTION(RSK_DOOR_OF_TIME) != RO_DOOROFTIME_CLOSED || ( INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_TIME && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && @@ -979,7 +979,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = eligible; break; } - case GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY: { + case VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY: { // give both rewards at the same time if (gSaveContext.minigameScore >= 1500) { Flags_SetItemGetInf(ITEMGETINF_0F); @@ -987,7 +987,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD: { + case VB_GIVE_ITEM_FROM_SKULLTULA_REWARD: { // In z_en_sth.c the rewards are stored in sGetItemIds, the first entry // in that array is GI_RUPEE_GOLD, and the reward is picked in EnSth_GivePlayerItem // via sGetItemIds[this->actor.params]. This means if actor.params == 0 we're looking @@ -1014,14 +1014,14 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME: { + case VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME: { EnSkj* enSkj = static_cast(optionalArg); Flags_SetItemGetInf(ITEMGETINF_17); enSkj->actionFunc = (EnSkjActionFunc)EnSkj_CleanupOcarinaGame; *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_LOST_DOG: { + case VB_GIVE_ITEM_FROM_LOST_DOG: { EnHy* enHy = static_cast(optionalArg); Flags_SetInfTable(INFTABLE_191); gSaveContext.dogParams = 0; @@ -1030,33 +1030,33 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } - case GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING: { + case VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING: { EnBomBowlPit* enBomBowlPit = static_cast(optionalArg); if (enBomBowlPit->prizeIndex == EXITEM_BOMB_BAG_BOWLING || enBomBowlPit->prizeIndex == EXITEM_HEART_PIECE_BOWLING) { *should = false; } break; } - case GI_VB_GERUDOS_BE_FRIENDLY: { + case VB_GERUDOS_BE_FRIENDLY: { *should = CHECK_QUEST_ITEM(QUEST_GERUDO_CARD); break; } - case GI_VB_GTG_GATE_BE_OPEN: { + case VB_GTG_GATE_BE_OPEN: { if (Flags_GetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)) { *should = true; } break; } - case GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD: { + case VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD: { Flags_SetRandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS); *should = false; break; } - case GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE: { + case VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE: { *should = MeetsRainbowBridgeRequirements(); break; } - case GI_VB_PLAY_BLUE_WARP_CS: { + case VB_PLAY_BLUE_WARP_CS: { // We need to override just these two temples because they check medallions instead of flags if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { *should = !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); @@ -1065,34 +1065,34 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } - case GI_VB_TRADE_TIMER_ODD_MUSHROOM: - case GI_VB_TRADE_TIMER_EYEDROPS: - case GI_VB_TRADE_TIMER_FROG: - case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: - case GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: - case GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS: - case GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME: - case GI_VB_GIVE_ITEM_FROM_GORON: - case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: - case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: - case GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF: - case GI_VB_GIVE_ITEM_SKULL_TOKEN: - case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: - case GI_VB_GIVE_ITEM_FAIRY_OCARINA: - case GI_VB_GIVE_ITEM_WEIRD_EGG: - case GI_VB_GIVE_ITEM_LIGHT_ARROW: - case GI_VB_GIVE_ITEM_STRENGTH_1: - case GI_VB_GIVE_ITEM_ZELDAS_LETTER: - case GI_VB_GIVE_ITEM_OCARINA_OF_TIME: - case GI_VB_GIVE_ITEM_KOKIRI_EMERALD: - case GI_VB_GIVE_ITEM_GORON_RUBY: - case GI_VB_GIVE_ITEM_ZORA_SAPPHIRE: - case GI_VB_GIVE_ITEM_LIGHT_MEDALLION: - case GI_VB_GIVE_ITEM_FOREST_MEDALLION: - case GI_VB_GIVE_ITEM_FIRE_MEDALLION: - case GI_VB_GIVE_ITEM_WATER_MEDALLION: - case GI_VB_GIVE_ITEM_SPIRIT_MEDALLION: - case GI_VB_GIVE_ITEM_SHADOW_MEDALLION: + case VB_TRADE_TIMER_ODD_MUSHROOM: + case VB_TRADE_TIMER_EYEDROPS: + case VB_TRADE_TIMER_FROG: + case VB_ANJU_SET_OBTAINED_TRADE_ITEM: + case VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: + case VB_GIVE_ITEM_FROM_TALONS_CHICKENS: + case VB_GIVE_ITEM_FROM_DIVING_MINIGAME: + case VB_GIVE_ITEM_FROM_GORON: + case VB_GIVE_ITEM_FROM_LAB_DIVE: + case VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: + case VB_GIVE_ITEM_FROM_MAN_ON_ROOF: + case VB_GIVE_ITEM_SKULL_TOKEN: + case VB_GIVE_ITEM_FROM_BLUE_WARP: + case VB_GIVE_ITEM_FAIRY_OCARINA: + case VB_GIVE_ITEM_WEIRD_EGG: + case VB_GIVE_ITEM_LIGHT_ARROW: + case VB_GIVE_ITEM_STRENGTH_1: + case VB_GIVE_ITEM_ZELDAS_LETTER: + case VB_GIVE_ITEM_OCARINA_OF_TIME: + case VB_GIVE_ITEM_KOKIRI_EMERALD: + case VB_GIVE_ITEM_GORON_RUBY: + case VB_GIVE_ITEM_ZORA_SAPPHIRE: + case VB_GIVE_ITEM_LIGHT_MEDALLION: + case VB_GIVE_ITEM_FOREST_MEDALLION: + case VB_GIVE_ITEM_FIRE_MEDALLION: + case VB_GIVE_ITEM_WATER_MEDALLION: + case VB_GIVE_ITEM_SPIRIT_MEDALLION: + case VB_GIVE_ITEM_SHADOW_MEDALLION: *should = false; break; } diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 642eae7cc..ad612a82e 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -40,7 +40,7 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) { if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) { // Typically this doesn't get get live updated in vanilla, but we need to // live update it if we're skipping a certain cutscene or in randomizer - if (GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { + if (GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { enKo->collider.dim.height -= 200; Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos); enKo->actionFunc = func_80A99384; @@ -140,7 +140,7 @@ void TimeSaverOnGameFrameUpdateHandler() { void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { - case GI_VB_PLAY_TRANSITION_CS: { + case VB_PLAY_TRANSITION_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.cutsceneIndex = 0; *should = false; @@ -160,7 +160,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); // Normally happens in the cutscene gSaveContext.dayTime = gSaveContext.skyboxTime = 0xAC60; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { Item_Give(gPlayState, ITEM_SONG_REQUIEM); } *should = false; @@ -173,11 +173,11 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); - if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, meetsBurningKakRequirements, NULL)) { + if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, meetsBurningKakRequirements, NULL)) { Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); // Normally happens in the cutscene Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { Item_Give(gPlayState, ITEM_SONG_NOCTURNE); } *should = false; @@ -255,7 +255,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* // Lost Woods Bridge if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { Item_Give(gPlayState, ITEM_OCARINA_FAIRY); } *should = false; @@ -268,9 +268,9 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); - if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements, NULL)) { + if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements, NULL)) { Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { Item_Give(gPlayState, ITEM_ARROW_LIGHT); } *should = false; @@ -293,14 +293,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_PLAY_ENTRANCE_CS: { + case VB_PLAY_ENTRANCE_CS: { s32* entranceFlag = static_cast(opt); if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { *should = false; } break; } - case GI_VB_PLAY_ONEPOINT_CS: { + case VB_PLAY_ONEPOINT_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { s16* csId = static_cast(opt); switch (*csId) { @@ -310,13 +310,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* RateLimitedSuccessChime(); break; default: - SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_CS {}", *csId); + SPDLOG_INFO("VB_PLAY_ONEPOINT_CS {}", *csId); break; } } break; } - case GI_VB_PLAY_ONEPOINT_ACTOR_CS: { + case VB_PLAY_ONEPOINT_ACTOR_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { Actor* actor = static_cast(opt); @@ -398,23 +398,23 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } if (*should) { - SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category); + SPDLOG_INFO("VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category); } } break; } - case GI_VB_SHOW_TITLE_CARD: + case VB_SHOW_TITLE_CARD: if (CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO)) { *should = false; } break; - case GI_VB_WONDER_TALK: { + case VB_WONDER_TALK: { if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { *should = false; } break; } - case GI_VB_NAVI_TALK: { + case VB_NAVI_TALK: { if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { ElfMsg* naviTalk = static_cast(opt); Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F); @@ -423,13 +423,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_NOT_BE_GREETED_BY_SARIA: + case VB_NOT_BE_GREETED_BY_SARIA: if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); *should = true; } break; - case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + case VB_MOVE_MIDO_IN_KOKIRI_FOREST: if ( CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && @@ -440,7 +440,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = true; } break; - case GI_VB_PLAY_DEKU_TREE_INTRO_CS: { + case VB_PLAY_DEKU_TREE_INTRO_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { BgTreemouth* treeMouth = static_cast(opt); Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); @@ -450,7 +450,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { + case VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { // We're overriding this so that the Deku JR doesn't despawn after skipping the forest temple blue warp cutscene. // It typically relies on the forest medallion being obtained, but that isn't given yet until after scene init if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { @@ -458,21 +458,21 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: - case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: - case GI_VB_GIVE_ITEM_FAIRY_OCARINA: - case GI_VB_GIVE_ITEM_LIGHT_ARROW: + case VB_GIVE_ITEM_FROM_BLUE_WARP: + case VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: + case VB_GIVE_ITEM_FAIRY_OCARINA: + case VB_GIVE_ITEM_LIGHT_ARROW: if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { *should = false; } break; - case GI_VB_PLAY_NABOORU_CAPTURED_CS: + case VB_PLAY_NABOORU_CAPTURED_CS: if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA); *should = false; } break; - case GI_VB_PLAY_PULL_MASTER_SWORD_CS: + case VB_PLAY_PULL_MASTER_SWORD_CS: if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { // Normally, these would be done in the cutscene, but we're skipping it @@ -480,14 +480,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); Flags_SetEventChkInf(EVENTCHKINF_TIME_TRAVELED_TO_ADULT); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { Item_Give(gPlayState, ITEM_MEDALLION_LIGHT); } } *should = false; } break; - case GI_VB_OWL_INTERACTION: { + case VB_OWL_INTERACTION: { if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && *should) { EnOwl* enOwl = static_cast(opt); s32 owlType = (enOwl->actor.params & 0xFC0) >> 6; @@ -501,7 +501,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { + case VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { u16* textId = static_cast(opt); // If the doors are not open yet, prioritize opening them @@ -512,15 +512,15 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_PLAY_EYEDROP_CREATION_ANIM: - case GI_VB_PLAY_EYEDROPS_CS: - case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS: - case GI_VB_PLAY_DARUNIAS_JOY_CS: + case VB_PLAY_EYEDROP_CREATION_ANIM: + case VB_PLAY_EYEDROPS_CS: + case VB_PLAY_DROP_FISH_FOR_JABU_CS: + case VB_PLAY_DARUNIAS_JOY_CS: if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; } break; - case GI_VB_PLAY_ZELDAS_LULLABY_CS: { + case VB_PLAY_ZELDAS_LULLABY_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { DemoIm* demoIm = static_cast(opt); Player* player = GET_PLAYER(gPlayState); @@ -570,7 +570,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_PLAY_SARIAS_SONG_CS: { + case VB_PLAY_SARIAS_SONG_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { EnSa* enSa = static_cast(opt); enSa->actionFunc = func_80AF6B20; @@ -578,13 +578,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_DESPAWN_HORSE_RACE_COW: { + case VB_DESPAWN_HORSE_RACE_COW: { if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger("gCowOfTime", 0)) { *should = false; } break; } - case GI_VB_PLAY_DRAIN_WELL_CS: { + case VB_PLAY_DRAIN_WELL_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { *should = false; Flags_SetSwitch(gPlayState, 0x2); @@ -593,7 +593,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_PLAY_SUNS_SONG_CS: + case VB_PLAY_SUNS_SONG_CS: if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { *should = false; Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG); @@ -602,19 +602,19 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* // When it's 0x8000, it's changed to 0xC090 } break; - case GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS: { + case VB_PLAY_ROYAL_FAMILY_TOMB_CS: { if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; } break; } - case GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { + case VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); } break; } - case GI_VB_PLAY_DOOR_OF_TIME_CS: { + case VB_PLAY_DOOR_OF_TIME_CS: { if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { *should = false; Flags_SetEnv(gPlayState, 2); @@ -622,59 +622,59 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_GIVE_ITEM_MINUET_OF_FOREST: - case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE: - case GI_VB_GIVE_ITEM_SERENADE_OF_WATER: - case GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT: - case GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW: - case GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT: - case GI_VB_GIVE_ITEM_ZELDAS_LULLABY: - case GI_VB_GIVE_ITEM_EPONAS_SONG: - case GI_VB_GIVE_ITEM_SARIAS_SONG: - case GI_VB_GIVE_ITEM_SUNS_SONG: - case GI_VB_GIVE_ITEM_SONG_OF_TIME: - case GI_VB_GIVE_ITEM_SONG_OF_STORMS: - case GI_VB_PLAY_MINUET_OF_FOREST_CS: - case GI_VB_PLAY_BOLERO_OF_FIRE_CS: - case GI_VB_PLAY_SERENADE_OF_WATER_CS: - case GI_VB_PLAY_PRELUDE_OF_LIGHT_CS: + case VB_GIVE_ITEM_MINUET_OF_FOREST: + case VB_GIVE_ITEM_BOLERO_OF_FIRE: + case VB_GIVE_ITEM_SERENADE_OF_WATER: + case VB_GIVE_ITEM_REQUIEM_OF_SPIRIT: + case VB_GIVE_ITEM_NOCTURNE_OF_SHADOW: + case VB_GIVE_ITEM_PRELUDE_OF_LIGHT: + case VB_GIVE_ITEM_ZELDAS_LULLABY: + case VB_GIVE_ITEM_EPONAS_SONG: + case VB_GIVE_ITEM_SARIAS_SONG: + case VB_GIVE_ITEM_SUNS_SONG: + case VB_GIVE_ITEM_SONG_OF_TIME: + case VB_GIVE_ITEM_SONG_OF_STORMS: + case VB_PLAY_MINUET_OF_FOREST_CS: + case VB_PLAY_BOLERO_OF_FIRE_CS: + case VB_PLAY_SERENADE_OF_WATER_CS: + case VB_PLAY_PRELUDE_OF_LIGHT_CS: if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { *should = false; } break; - case GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN: + case VB_DAMPE_IN_GRAVEYARD_DESPAWN: if (CVarGetInteger("gDampeAllNight", 0)) { *should = LINK_IS_ADULT || gPlayState->sceneNum != SCENE_GRAVEYARD; } break; - case GI_VB_BE_VALID_GRAVEDIGGING_SPOT: + case VB_BE_VALID_GRAVEDIGGING_SPOT: if (CVarGetInteger("gDampeWin", 0)) { EnTk *enTk = static_cast(opt); enTk->validDigHere = true; *should = true; } break; - case GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: + case VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: if (CVarGetInteger("gDampeWin", 0)) { EnTk *enTk = static_cast(opt); enTk->currentReward = 3; *should = true; } break; - case GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE: + case VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE: if (CVarGetInteger("gGravediggingTourFix", 0) || IS_RANDO) { *should = !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE); } break; - case GI_VB_FIX_SAW_SOFTLOCK: + case VB_FIX_SAW_SOFTLOCK: // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. *should = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should; break; - case GI_VB_BIGGORON_CONSIDER_SWORD_FORGED: + case VB_BIGGORON_CONSIDER_SWORD_FORGED: *should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3); break; - case GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD: { + case VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD: { BgDyYoseizo* bgDyYoseizo = static_cast(opt); RandomizerInf flag = RAND_INF_MAX; @@ -715,14 +715,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } - case GI_VB_PLAY_RAINBOW_BRIDGE_CS: { + case VB_PLAY_RAINBOW_BRIDGE_CS: { if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { *should = false; func_800F595C(NA_BGM_BRIDGE_TO_GANONS); } break; } - case GI_VB_PHANTOM_GANON_DEATH_SCENE: { + case VB_PHANTOM_GANON_DEATH_SCENE: { if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO || IS_BOSS_RUSH)) { *should = false; BossGanondrof* pg = static_cast(opt); @@ -747,7 +747,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } - case GI_VB_NABOORU_KNUCKLE_DEATH_SCENE: { + case VB_NABOORU_KNUCKLE_DEATH_SCENE: { EnIk* ik = static_cast(opt); if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO)) { // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor @@ -964,7 +964,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { } break; case SCENE_LON_LON_RANCH: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 94b04580f..51d0053e1 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -497,11 +497,11 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB bool shouldSkipCommand = false; - if (cmd->base == 8 && !GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) { + if (cmd->base == 8 && !GameInteractor_Should(VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) { shouldSkipCommand = true; } - if (cmd->base == 24 && !GameInteractor_Should(GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) { + if (cmd->base == 24 && !GameInteractor_Should(VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) { shouldSkipCommand = true; } @@ -631,7 +631,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB gSaveContext.fw.set = 0; gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0; } - if (GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) { + if (GameInteractor_Should(VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0; play->transitionTrigger = TRANS_TRIGGER_START; @@ -723,7 +723,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_WHITE; break; case 22: - if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { Item_Give(play, ITEM_SONG_REQUIEM); } play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; @@ -777,7 +777,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_WHITE; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_FIRE); } gSaveContext.chamberCutsceneNum = 1; @@ -859,7 +859,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; break; case 47: - if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { Item_Give(play, ITEM_SONG_NOCTURNE); } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); @@ -2183,7 +2183,7 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) { (gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) && (gSaveContext.respawnFlag <= 0)) { Flags_SetEventChkInf(entranceCutscene->flag); - if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) { + if (GameInteractor_Should(VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) { Cutscene_SetSegment(play, entranceCutscene->segAddr); gSaveContext.cutsceneTrigger = 2; gSaveContext.showTitleCard = false; @@ -2197,7 +2197,7 @@ void Cutscene_HandleConditionalTriggers(PlayState* play) { osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag)); LUSLOG_INFO("Cutscene_HandleConditionalTriggers - entranceIndex: %#x cutsceneIndex: %#x", gSaveContext.entranceIndex, gSaveContext.cutsceneIndex); - if (!GameInteractor_Should(GI_VB_PLAY_TRANSITION_CS, true, NULL)) { + if (!GameInteractor_Should(VB_PLAY_TRANSITION_CS, true, NULL)) { return; } @@ -2206,7 +2206,7 @@ void Cutscene_HandleConditionalTriggers(PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; gSaveContext.cutsceneIndex = 0xFFF0; - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, ( + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, ( (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && LINK_IS_ADULT && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && @@ -2218,12 +2218,12 @@ void Cutscene_HandleConditionalTriggers(PlayState* play) { gSaveContext.cutsceneIndex = 0xFFF0; } else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { Item_Give(play, ITEM_OCARINA_FAIRY); } gSaveContext.entranceIndex = ENTR_LOST_WOODS_0; gSaveContext.cutsceneIndex = 0xFFF0; - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, ( + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, ( CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && LINK_IS_ADULT && diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 873a91ec9..e6a3fd756 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -360,7 +360,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.params &= 0xFF; - if (GameInteractor_Should(GI_VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) { + if (GameInteractor_Should(VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) { Actor_Kill(&this->actor); return; } @@ -512,7 +512,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.velocity.y = 0.0f; this->actor.gravity = 0.0f; - if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + if (!GameInteractor_Should(VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { return; } @@ -866,7 +866,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { return; } - if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + if (!GameInteractor_Should(VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { return; } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index a025a2c0d..015d7c4b0 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2610,18 +2610,18 @@ void Message_DrawMain(PlayState* play, Gfx** p) { u8 songItemId = ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]; if ( - (songItemId == ITEM_SONG_MINUET && GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) || - (songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) || - (songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) || - (songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) || - (songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) || - (songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) || - (songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) || - (songItemId == ITEM_SONG_EPONA && GameInteractor_Should(GI_VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) || - (songItemId == ITEM_SONG_SARIA && GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) || - (songItemId == ITEM_SONG_SUN && GameInteractor_Should(GI_VB_GIVE_ITEM_SUNS_SONG, true, NULL)) || - (songItemId == ITEM_SONG_TIME && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) || - (songItemId == ITEM_SONG_STORMS && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL)) + (songItemId == ITEM_SONG_MINUET && GameInteractor_Should(VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) || + (songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) || + (songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) || + (songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) || + (songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) || + (songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) || + (songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) || + (songItemId == ITEM_SONG_EPONA && GameInteractor_Should(VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SARIA && GameInteractor_Should(VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SUN && GameInteractor_Should(VB_GIVE_ITEM_SUNS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_TIME && GameInteractor_Should(VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) || + (songItemId == ITEM_SONG_STORMS && GameInteractor_Should(VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL)) ) { Item_Give(play, songItemId); } diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 24a8820af..95030baf6 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -1173,11 +1173,11 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1 Camera* csCam; if (actor != NULL && actor->id != ACTOR_PLAYER) { - if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) { + if (!GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) { return SUBCAM_NONE; } } else { - if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) { + if (!GameInteractor_Should(VB_PLAY_ONEPOINT_CS, true, &csId)) { return SUBCAM_NONE; } } diff --git a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c index e05c171f0..7e0781067 100644 --- a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c +++ b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c @@ -225,7 +225,7 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) { if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { type = this->dyna.actor.params & 0xFF; Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { if (type == BLUE || type == YELLOW_TALL_2) { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); } else { @@ -239,7 +239,7 @@ void func_8086D548(BgBdanSwitch* this, PlayState* play) { if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) { - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); } } diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 8b901339f..3e7f60da9 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -302,7 +302,7 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) { if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); s32 flag = EVENTCHKINF_ENTERED_DODONGOS_CAVERN; - if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + if (GameInteractor_Should(VB_PLAY_ENTRANCE_CS, true, &flag)) { Cutscene_SetSegment(play, gDcOpeningCs); gSaveContext.cutsceneTrigger = 1; Player_SetCsActionWithHaltedActors(play, NULL, 0x31); diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index 8e2139aed..799a46c62 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -198,7 +198,7 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { } } - if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) { + if (!GameInteractor_Should(VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) { Actor_Kill(&this->actor); return; } diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index 543770505..afbe34053 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -70,7 +70,7 @@ void func_808787A4(BgGjyoBridge* this, PlayState* play) { } void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) { - if (GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); gSaveContext.cutsceneTrigger = 1; } @@ -92,7 +92,7 @@ void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) { (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, play); - if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) { + if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) { LaunchBridgeCutscene(this, play); } } @@ -103,7 +103,7 @@ void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) { (play->csCtx.npcActions[2] != NULL) && (play->csCtx.npcActions[2]->action == 2); - if (!GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) { + if (!GameInteractor_Should(VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) { this->dyna.actor.draw = BgGjyoBridge_Draw; func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId); Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT); diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index 51b7dc622..5088334ed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -150,7 +150,7 @@ void BgMoriBigst_StalfosFight(BgMoriBigst* this, PlayState* play) { if ((this->dyna.actor.home.rot.z == 0) && ((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) { BgMoriBigst_SetupFall(this, play); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); } } @@ -166,7 +166,7 @@ void BgMoriBigst_Fall(BgMoriBigst* this, PlayState* play) { this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y; BgMoriBigst_SetupLanding(this, play); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); func_8002DF38(play, NULL, 0x3C); } diff --git a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c index cc7d4c854..c2e8e1123 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c @@ -130,7 +130,7 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) { static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; Vec3f pos; - if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, play->csCtx.state != 0 && play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2, this)) { + if (GameInteractor_Should(VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, play->csCtx.state != 0 && play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2, this)) { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); this->timer = 25; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c index 6d65c049f..571123057 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c @@ -61,7 +61,7 @@ void BgSpot12Saku_Init(Actor* thisx, PlayState* play) { func_808B3420(this, play, &gGerudoFortressGTGShutterCol, DPM_UNK); Actor_ProcessInitChain(&this->dyna.actor, sInitChain); - if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { + if (GameInteractor_Should(VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B3714(this); } else { func_808B3550(this); @@ -82,7 +82,7 @@ void func_808B3550(BgSpot12Saku* this) { } void func_808B357C(BgSpot12Saku* this, PlayState* play) { - if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { + if (GameInteractor_Should(VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B35E4(this); this->timer = 20; OnePointCutscene_Init(play, 4170, -99, &this->dyna.actor, MAIN_CAM); diff --git a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c index b6d5ed15a..0d1c234b5 100644 --- a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c +++ b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c @@ -117,7 +117,7 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) { Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); s32 flag = EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER; - if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + if (GameInteractor_Should(VB_PLAY_ENTRANCE_CS, true, &flag)) { play->csCtx.segment = D_808BBD90; gSaveContext.cutsceneTrigger = 1; } @@ -126,7 +126,7 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) { if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) { if (Actor_HasParent(&this->actor, play)) { if (!LINK_IS_ADULT) { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) { Item_Give(play, ITEM_SWORD_MASTER); } play->csCtx.segment = D_808BB2F0; diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c index 04d1d6c72..4c4d828f8 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c @@ -154,7 +154,7 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) { } } else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) { Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); - if (GameInteractor_Should(GI_VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) { play->csCtx.segment = D_808BCE20; gSaveContext.cutsceneTrigger = 1; BgTreemouth_SetupAction(this, func_808BC9EC); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 0b025dcd6..05740bff9 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -944,7 +944,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { case DEATH_THROES: switch (this->work[GND_ACTION_STATE]) { case DEATH_SPASM: - if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, this)) { + if (GameInteractor_Should(VB_PHANTOM_GANON_DEATH_SCENE, true, this)) { if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) { this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim); Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f, @@ -963,7 +963,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { bodyDecayLevel = 1; break; } - if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, NULL)) { + if (GameInteractor_Should(VB_PHANTOM_GANON_DEATH_SCENE, true, NULL)) { Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8); Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f); Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f); diff --git a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c index cffdbea38..b0804724a 100644 --- a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c +++ b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c @@ -185,7 +185,7 @@ void func_80969F38(DemoDu* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, DEMO_EFFECT_MEDAL_FIRE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_FIRE); } } @@ -204,7 +204,7 @@ void DemoDu_CsFireMedallion_AdvanceTo01(DemoDu* this, PlayState* play) { this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1); play->csCtx.segment = D_8096C1A4; gSaveContext.cutsceneTrigger = 2; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_FIRE); } diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index 1df2325e8..ca8713805 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -319,7 +319,7 @@ void func_809853B4(DemoIm* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0, 0, 0, 0xD); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_SHADOW); } } @@ -337,7 +337,7 @@ void func_8098544C(DemoIm* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8098786C; gSaveContext.cutsceneTrigger = 2; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_SHADOW); } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; @@ -910,13 +910,13 @@ void func_80986BF8(DemoIm* this, PlayState* play) { void func_80986C30(DemoIm* this, PlayState* play) { if (func_80986A5C(this, play)) { - if (GameInteractor_Should(GI_VB_PLAY_ZELDAS_LULLABY_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ZELDAS_LULLABY_CS, true, this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs); gSaveContext.cutsceneTrigger = 1; func_80985F54(this); } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) { Item_Give(play, ITEM_SONG_LULLABY); } } diff --git a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c index 85dcb4ebe..b0d210bbc 100644 --- a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c +++ b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c @@ -242,7 +242,7 @@ void func_8098E8C8(DemoSa* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xB); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_FOREST); } } @@ -261,7 +261,7 @@ void func_8098E960(DemoSa* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8099010C; gSaveContext.cutsceneTrigger = 2; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_FOREST); } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index 34c0a0f20..843e95f25 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -355,7 +355,7 @@ void func_80996A54(DoorShutter* this, PlayState* play) { if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) { Flags_SetClear(play, this->dyna.actor.room); DoorShutter_SetupAction(this, func_80997150); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_Attention(play, &this->dyna.actor); OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); this->unk_16F = -100; @@ -473,7 +473,7 @@ void func_80996EE8(DoorShutter* this, PlayState* play) { if (func_80996E08(this, play, 1.0f)) { if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { DoorShutter_SetupAction(this, func_80997150); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_Attention(play, &this->dyna.actor); this->unk_16F = -100; } diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 710c138e2..ff55bf65f 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -528,9 +528,9 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) { osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START); if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) { Item_Give(play, ITEM_GORON_RUBY); } play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; @@ -540,10 +540,10 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) { Item_Give(play, ITEM_KOKIRI_EMERALD); } play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0; @@ -645,9 +645,9 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, PlayState* play) { this->warpTimer++; if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) { Item_Give(play, ITEM_ZORA_SAPPHIRE); } gSaveContext.nextCutsceneIndex = 0xFFF0; @@ -762,9 +762,9 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { if (IS_BOSS_RUSH) { BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z); } else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) { Item_Give(play, ITEM_MEDALLION_FOREST); } play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; @@ -779,9 +779,9 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) { Item_Give(play, ITEM_MEDALLION_FIRE); } play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; @@ -795,9 +795,9 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) { Item_Give(play, ITEM_MEDALLION_WATER); } play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; @@ -812,9 +812,9 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { Item_Give(play, ITEM_MEDALLION_SPIRIT); } play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; @@ -829,9 +829,9 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { Item_Give(play, ITEM_MEDALLION_SHADOW); } play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; diff --git a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c index 495ef96b8..53a0d749c 100644 --- a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c +++ b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c @@ -126,7 +126,7 @@ void ElfMsg_CallNaviCuboid(ElfMsg* this, PlayState* play) { (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) && (fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) { - if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + if (GameInteractor_Should(VB_NAVI_TALK, true, this)) { player->naviTextId = ElfMsg_GetMessageId(this); navi->elfMsg = this; } @@ -148,7 +148,7 @@ void ElfMsg_CallNaviCylinder(ElfMsg* this, PlayState* play) { if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) && (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) { - if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + if (GameInteractor_Should(VB_NAVI_TALK, true, this)) { player->naviTextId = ElfMsg_GetMessageId(this); navi->elfMsg = this; } diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 57cb6045e..8f4ee815c 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -120,7 +120,7 @@ void func_809B0524(EnAni* this, PlayState* play) { } void func_809B0558(EnAni* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { this->actor.parent = NULL; if (!LINK_IS_ADULT) { EnAni_SetupAction(this, func_809B04F0); @@ -129,7 +129,7 @@ void func_809B0558(EnAni* this, PlayState* play) { } Flags_SetItemGetInf(ITEMGETINF_15); } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } @@ -140,7 +140,7 @@ void func_809B05F0(EnAni* this, PlayState* play) { EnAni_SetupAction(this, func_809B0558); } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 7e5cc3ef1..1a1ed01a6 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -185,7 +185,7 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; this->actor.parent = NULL; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -193,7 +193,7 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { } void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { this->actionFunc = EnBomBowlPit_Reset; } else { Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index f6deade38..a60b7c5ed 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -278,7 +278,7 @@ void EnBox_Fall(EnBox* this, PlayState* play) { this->dyna.actor.shape.rot.z = 0; this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; EnBox_SetupAction(this, EnBox_WaitOpen); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_EndCutscene(play, this->unk_1AC); } } diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 9869a0621..c01ac30b5 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -118,7 +118,7 @@ void EnCow_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit); func_809DEE9C(this); this->actionFunc = func_809DF96C; - if (GameInteractor_Should(GI_VB_DESPAWN_HORSE_RACE_COW, ( + if (GameInteractor_Should(VB_DESPAWN_HORSE_RACE_COW, ( play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) ), this)) { Actor_Kill(&this->actor); @@ -260,7 +260,7 @@ void func_809DF96C(EnCow* this, PlayState* play) { if ((this->actor.xzDistToPlayer < 150.0f) && (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) { DREG(53) = 0; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_COW, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_COW, true, this)) { this->actionFunc = func_809DF8FC; this->actor.flags |= ACTOR_FLAG_WILL_TALK; func_8002F2CC(&this->actor, play, 170.0f); diff --git a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c index b411c1427..0a2d4c6fe 100644 --- a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c +++ b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c @@ -456,7 +456,7 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { if ((this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play))) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } this->actionFunc = func_809EEA90; @@ -465,10 +465,10 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { void func_809EEA90(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { this->actionFunc = func_809EEAF8; } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } } @@ -478,7 +478,7 @@ void func_809EEA90(EnDivingGame* this, PlayState* play) { void func_809EEAF8(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) || - !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + !GameInteractor_Should(VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); this->allRupeesThrown = this->state = this->phase = this->unk_2A2 = this->grabbedRupeesCounter = 0; diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 6ea9c26e1..d2d8963c3 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -397,7 +397,7 @@ void func_809EFDD0(EnDns* this, PlayState* play) { void func_809EFEE8(EnDns* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { func_809EFDD0(this, play); } this->actionFunc = func_809EFF50; @@ -405,7 +405,7 @@ void func_809EFEE8(EnDns* this, PlayState* play) { } void func_809EFF50(EnDns* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { this->actor.parent = NULL; this->actionFunc = func_809EFF98; } else { diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c index 102a904cf..eaee07ae7 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c @@ -253,7 +253,7 @@ void EnDntNomal_TargetWait(EnDntNomal* this, PlayState* play) { if (!LINK_IS_ADULT && !Flags_GetItemGetInf(ITEMGETINF_1D)) { this->hitCounter++; if (this->hitCounter >= 3) { - if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { + if (!GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { this->actionFunc = EnDntNomal_TargetGivePrize; } else { OnePointCutscene_Init(play, 4140, -99, &this->actor, MAIN_CAM); diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index e94ff9039..7e3f97856 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -90,7 +90,7 @@ void EnDs_DisplayOddPotionText(EnDs* this, PlayState* play) { } void EnDs_GiveOddPotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_TRADE_ODD_MUSHROOM, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; @@ -104,7 +104,7 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, PlayState* play) { Message_CloseTextbox(play); this->actionFunc = EnDs_GiveOddPotion; u32 itemId = GI_ODD_POTION; - if (GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { + if (GameInteractor_Should(VB_TRADE_ODD_MUSHROOM, true, this)) { Actor_OfferGetItem(&this->actor, play, itemId, 10000.0f, 50.0f); } } @@ -127,7 +127,7 @@ void EnDs_BrewOddPotion2(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion3; - this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; + this->brewTimer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_UnsetSwitch(play, 0x3F); } } @@ -137,7 +137,7 @@ void EnDs_BrewOddPotion1(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion2; - this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 20 : 0; + this->brewTimer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 20 : 0; } Math_StepToF(&this->unk_1E4, 1.0f, 0.01f); @@ -151,7 +151,7 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: // yes this->actionFunc = EnDs_BrewOddPotion1; - this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; + this->brewTimer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_SetSwitch(play, 0x3F); play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; @@ -166,7 +166,7 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { s32 EnDs_CheckRupeesAndBottle() { if (gSaveContext.rupees < 100) { return 0; - } else if (GameInteractor_Should(GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, Inventory_HasEmptyBottle() == 0, NULL)) { + } else if (GameInteractor_Should(VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, Inventory_HasEmptyBottle() == 0, NULL)) { return 1; } else { return 2; @@ -174,7 +174,7 @@ s32 EnDs_CheckRupeesAndBottle() { } void EnDs_GiveBluePotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_Talk; } else { @@ -198,7 +198,7 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { GetItemEntry itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); Actor_OfferGetItem(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); gSaveContext.pendingSale = itemEntry.itemId; @@ -225,7 +225,7 @@ void EnDs_Wait(EnDs* this, PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); player->actor.textId = 0x504A; this->actionFunc = EnDs_OfferOddPotion; - } else if (GameInteractor_Should(GI_VB_OFFER_BLUE_POTION, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // Traded odd mushroom + } else if (GameInteractor_Should(VB_OFFER_BLUE_POTION, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // Traded odd mushroom player->actor.textId = 0x500C; this->actionFunc = EnDs_OfferBluePotion; } else { diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index 781c09f79..2c7b1a2bb 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -377,7 +377,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_00; EnDu_SetupAction(this, func_809FE3C0); } else if (play->msgCtx.ocarinaMode >= OCARINA_MODE_06) { - if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaWrongCs); gSaveContext.cutsceneTrigger = 1; } @@ -386,7 +386,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaCorrectCs); gSaveContext.cutsceneTrigger = 1; } @@ -554,7 +554,7 @@ void func_809FEB08(EnDu* this, PlayState* play) { EnDu_SetupAction(this, func_809FE3C0); return; } - if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, CUR_UPG_VALUE(UPG_STRENGTH) <= 0, NULL)) { + if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, CUR_UPG_VALUE(UPG_STRENGTH) <= 0, NULL)) { Flags_SetRandomizerInf(RAND_INF_DARUNIAS_JOY); this->actor.textId = 0x301C; EnDu_SetupAction(this, func_809FEC14); @@ -576,7 +576,7 @@ void func_809FEC14(EnDu* this, PlayState* play) { } void func_809FEC70(EnDu* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_STRENGTH_1, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_STRENGTH_1, true, NULL)) { this->actor.parent = NULL; EnDu_SetupAction(this, func_809FECE4); } else { diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 28e89036d..8b3195d72 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -362,7 +362,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { Math_SmoothStepToS(&this->actor.shape.rot.y, -0x4000, 5, 0x1000, 0); } - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor) && this->timer != 0) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor) && this->timer != 0) { if (this->prizeRotateTimer != 0) { tmpf1 = play->view.lookAt.x - play->view.eye.x; tmpf2 = play->view.lookAt.y - 10.0f - play->view.eye.y; @@ -388,7 +388,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; - if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { + if (!GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { GET_PLAYER(play)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); } @@ -398,7 +398,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { getItemId = GI_BULLET_BAG_50; } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } @@ -407,7 +407,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { } void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { this->actionFunc = EnExItem_TargetPrizeFinish; } else { s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; @@ -416,7 +416,7 @@ void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { } void EnExItem_TargetPrizeFinish(EnExItem* this, PlayState* play) { - if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor) || (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (!GameInteractor_Should(VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor) || (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); Flags_SetItemGetInf(ITEMGETINF_1D); diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 646fc5668..8af56cd79 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -947,7 +947,7 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_RUPEE_PURPLE; } } else { @@ -957,7 +957,7 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; } } else { @@ -967,7 +967,7 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; } } else { @@ -1019,14 +1019,14 @@ void EnFr_Deactivate(EnFr* this, PlayState* play) { this->actionFunc = EnFr_Idle; } else { this->actionFunc = EnFr_GiveReward; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_FROGS, true, this)) { Actor_OfferGetItem(&this->actor, play, this->reward, 30.0f, 100.0f); } } } void EnFr_GiveReward(EnFr* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->actor.parent = NULL; this->actionFunc = EnFr_SetIdle; } else { diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 2086e528f..facd43466 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -134,7 +134,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_GATE_OPERATOR: this->hairstyle = GE1_HAIR_STRAIGHT; - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_CheckGate_GateOp; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -144,7 +144,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_NORMAL: this->hairstyle = GE1_HAIR_STRAIGHT; - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_SetNormalText; } else { this->actionFunc = EnGe1_WatchForAndSensePlayer; @@ -174,7 +174,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { if (gSaveContext.eventInf[0] & 0x100) { this->actionFunc = EnGe1_TalkAfterGame_Archery; - } else if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + } else if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_Wait_Archery; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -184,7 +184,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_TRAINING_GROUNDS_GUARD: this->hairstyle = GE1_HAIR_STRAIGHT; - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_CheckForCard_GTGGuard; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -519,7 +519,7 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; s32 getItemId; - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { this->actionFunc = EnGe1_SetupWait_Archery; if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { @@ -542,7 +542,7 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { getItemId = GI_HEART_PIECE; } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } } @@ -571,7 +571,7 @@ void EnGe1_BeginGiveItem_Archery(EnGe1* this, PlayState* play) { getItemId = GI_HEART_PIECE; } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 0b5b9c09e..9c4db10ac 100644 --- a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -140,14 +140,14 @@ void EnGe2_Init(Actor* thisx, PlayState* play) { switch (this->actor.params & 0xFF) { case GE2_TYPE_PATROLLING: EnGe2_ChangeAction(this, GE2_ACTION_WALK); - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } break; case GE2_TYPE_STATIONARY: EnGe2_ChangeAction(this, GE2_ACTION_STAND); - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -460,7 +460,7 @@ void EnGe2_WaitLookAtPlayer(EnGe2* this, PlayState* play) { } void EnGe2_WaitTillCardGiven(EnGe2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe2_SetActionAfterTalk; } else { @@ -473,7 +473,7 @@ void EnGe2_GiveCard(EnGe2* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe2_WaitTillCardGiven; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -605,7 +605,7 @@ void EnGe2_Update(Actor* thisx, PlayState* play) { } EnGe2_MoveAndBlink(this, play); - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL) && !(this->stateFlags & GE2_STATE_KO)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL) && !(this->stateFlags & GE2_STATE_KO)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -630,7 +630,7 @@ void EnGe2_UpdateStunned(Actor* thisx, PlayState* play2) { } CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); - if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { + if (GameInteractor_Should(VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; this->actor.colorFilterTimer = 0; diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index 1265ba51e..835743b34 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -141,7 +141,7 @@ void EnGe3_WaitLookAtPlayer(EnGe3* this, PlayState* play) { } void EnGe3_WaitTillCardGiven(EnGe3* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe3_Wait; } else { @@ -154,7 +154,7 @@ void EnGe3_GiveCard(EnGe3* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe3_WaitTillCardGiven; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 7174a63f1..2a54cf979 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -97,7 +97,7 @@ void EnGm_Destroy(Actor* thisx, PlayState* play) { s32 func_80A3D7C8(void) { if (LINK_AGE_IN_YEARS == YEARS_CHILD) { return 0; - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, ( + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, ( !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) // Don't have giant's knife ), NULL)) { return 1; @@ -249,7 +249,7 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { Message_ContinueTextbox(play, 0xC8); this->actionFunc = func_80A3DD7C; } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } @@ -265,7 +265,7 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { } void func_80A3DF00(EnGm* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); this->actor.parent = NULL; this->actionFunc = func_80A3DF60; diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 47d1d7b0d..4194e9ee5 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -283,7 +283,7 @@ s32 EnGo2_SpawnDust(EnGo2* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 void EnGo2_GetItem(EnGo2* this, PlayState* play, s32 getItemId) { this->getItemId = getItemId; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_GORON, true, this)) { Actor_OfferGetItem(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } @@ -329,7 +329,7 @@ u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) { u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Flags_GetInfTable(INFTABLE_11E)) { return 0x3013; - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 20, this) + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 20, this) && this->waypoint > 7 && this->waypoint < 12) { return 0x3012; } else { @@ -407,9 +407,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtRollingSmall(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronDmtDcEntrance(PlayState* play, EnGo2* this) { - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { + } else if (GameInteractor_Should(VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE) ? 0x3021 : Flags_GetInfTable(INFTABLE_E0) ? 0x302A : 0x3008; @@ -428,9 +428,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtDcEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityEntrance(PlayState* play, EnGo2* this) { - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { + } else if (GameInteractor_Should(VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F0) ? 0x3015 : 0x3014; @@ -449,9 +449,9 @@ s16 EnGo2_UpdateTalkStateGoronCityEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityIsland(PlayState* play, EnGo2* this) { - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { + } else if (GameInteractor_Should(VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F4) ? 0x3017 : 0x3016; @@ -470,9 +470,9 @@ s16 EnGo2_UpdateTalkStateGoronCityIsland(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityLowestFloor(PlayState* play, EnGo2* this) { - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { + } else if (GameInteractor_Should(VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C @@ -496,13 +496,13 @@ s16 EnGo2_UpdateTalkStateGoronCityLowestFloor(PlayState* play, EnGo2* this) { u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) { // In case a hook neglects to set the override, fall back to the first dialogue u16 overrideTextId = 0x3030; - if (GameInteractor_Should(GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, false, &overrideTextId)) { + if (GameInteractor_Should(VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, false, &overrideTextId)) { return overrideTextId; } - if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL)) { + if (GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL)) { return Flags_GetInfTable(INFTABLE_10F) ? 0x3042 : 0x3041; - } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL)) { + } else if (GameInteractor_Should(VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL)) { return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; } else if (Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { this->unk_20C = 0; @@ -568,7 +568,7 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(PlayState* play, EnGo2* this) { Player* player = GET_PLAYER(play); - if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { + if (GameInteractor_Should(VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { @@ -590,7 +590,7 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { switch (EnGo2_GetDialogState(this, play)) { case TEXT_STATE_DONE: if (this->actor.textId == 0x305E) { - if (!GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { + if (!GameInteractor_Should(VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); EnGo2_GetItem(this, play, GI_SWORD_BGS); this->actionFunc = EnGo2_SetupGetItem; @@ -1022,7 +1022,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { u16 textId; if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { - if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { + if (GameInteractor_Should(VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { this->actor.textId = 0x3003; } else { @@ -1031,18 +1031,18 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { player->actor.textId = this->actor.textId; } else if ( - !GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL) && + !GameInteractor_Should(VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL) && (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) ) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { - if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { + if (GameInteractor_Should(VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x305E; } else { textId = 0x305D; } this->actor.textId = textId; } else { - if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { + if (GameInteractor_Should(VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x3002; } else { textId = 0x305D; @@ -1171,8 +1171,8 @@ s32 EnGo2_IsCameraModified(EnGo2* this, PlayState* play) { (this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) { return true; } else if ( - !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + !GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) ) { return true; } else { @@ -1231,8 +1231,8 @@ void EnGo2_SelectGoronWakingUp(EnGo2* this) { break; case GORON_CITY_LINK: if ( - !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + !GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) ) { EnGo2_WakingUp(this); break; @@ -1561,7 +1561,7 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { case GORON_CITY_LOWEST_FLOOR: case GORON_CITY_STAIRWELL: case GORON_CITY_LOST_WOODS: - if (!GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { + if (!GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { Actor_Kill(&this->actor); } this->actionFunc = EnGo2_CurledUp; @@ -1577,8 +1577,8 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { Path_CopyLastPoint(this->path, &this->actor.world.pos); this->actor.home.pos = this->actor.world.pos; if ( - !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && - GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + !GameInteractor_Should(VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) ) { EnGo2_GetItemAnimation(this, play); } else { @@ -1795,7 +1795,7 @@ void EnGo2_ReverseRolling(EnGo2* this, PlayState* play) { } void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGo2_SetGetItem; } else { @@ -1804,7 +1804,7 @@ void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { } void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; switch (this->getItemId) { case GI_CLAIM_CHECK: @@ -1816,7 +1816,7 @@ void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { EnGo2_GetItemAnimation(this, play); return; case GI_SWORD_BGS: - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_GORON, true, NULL)) { gSaveContext.bgsFlag = true; } break; @@ -1837,12 +1837,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; this->actor.shape.rot.y += 0x5B0; this->trackingMode = NPC_TRACKING_NONE; - this->animTimer = !GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL) ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer + this->animTimer = !GameInteractor_Should(VB_PLAY_EYEDROPS_CS, true, NULL) ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer this->eyeMouthTexState = 2; this->unk_20C = 0; this->goronState++; func_800F483C(0x28, 5); - if (GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_EYEDROPS_CS, true, NULL)) { OnePointCutscene_Init(play, 4190, -99, &this->actor, MAIN_CAM); } break; diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index eb3556a6e..f6e48a913 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -79,7 +79,7 @@ void EnHs_Init(Actor* thisx, PlayState* play) { // "chicken shop (adult era)" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST); func_80A6E3A0(this, func_80A6E9AC); - if (GameInteractor_Should(GI_VB_DESPAWN_GROG, Flags_GetItemGetInf(ITEMGETINF_30), this)) { + if (GameInteractor_Should(VB_DESPAWN_GROG, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // "chicken shop closed" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST); Actor_Kill(&this->actor); @@ -130,7 +130,7 @@ void func_80A6E5EC(EnHs* this, PlayState* play) { void func_80A6E630(EnHs* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (GameInteractor_Should(GI_VB_TRADE_TIMER_ODD_MUSHROOM, true, NULL)) { + if (GameInteractor_Should(VB_TRADE_TIMER_ODD_MUSHROOM, true, NULL)) { func_80088AA0(180); gSaveContext.eventInf[1] &= ~1; } @@ -157,7 +157,7 @@ void func_80A6E70C(EnHs* this, PlayState* play) { } void func_80A6E740(EnHs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_TRADE_COJIRO, true, this)) { this->actor.parent = NULL; Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); func_80A6E3A0(this, func_80A6E630); @@ -173,7 +173,7 @@ void func_80A6E7BC(EnHs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: func_80A6E3A0(this, func_80A6E740); - if (GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { + if (GameInteractor_Should(VB_TRADE_COJIRO, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } break; diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index adb50441e..cbcd03e0e 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -660,7 +660,7 @@ s16 func_80A70058(PlayState* play, Actor* thisx) { gSaveContext.dogParams = 0; break; case 0x709F: - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LOST_DOG, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_LOST_DOG, true, this)) { func_80A6F7CC(this, play, Flags_GetInfTable(INFTABLE_191) ? GI_RUPEE_BLUE : GI_HEART_PIECE); this->actionFunc = func_80A714C4; } diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index 5f1634237..3da5dbe7b 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -1439,7 +1439,7 @@ void func_80A781CC(Actor* thisx, PlayState* play) { if (!Play_InCsMode(play)) { this->actor.update = EnIk_Update; this->actor.draw = EnIk_Draw; - if (GameInteractor_Should(GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, true, this)) { + if (GameInteractor_Should(VB_NABOORU_KNUCKLE_DEATH_SCENE, true, this)) { Cutscene_SetSegment(play, gSpiritBossNabooruKnuckleDefeatCs); gSaveContext.cutsceneTrigger = 1; Actor_SetScale(&this->actor, 0.01f); diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index 1baf3413a..f9e18f315 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -128,7 +128,7 @@ void func_80A8910C(EnJs* this, PlayState* play) { } void func_80A89160(EnJs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) { this->actor.parent = NULL; En_Js_SetupAction(this, func_80A8910C); Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 4e83742c3..ddd197320 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -1027,7 +1027,7 @@ s32 EnKo_CanSpawn(EnKo* this, PlayState* play) { } case SCENE_LOST_WOODS: - return GameInteractor_Should(GI_VB_SPAWN_LW_FADO, ( + return GameInteractor_Should(VB_SPAWN_LW_FADO, ( (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false ), this); default: @@ -1175,7 +1175,7 @@ void func_80A99048(EnKo* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELF, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3); if (ENKO_TYPE == ENKO_TYPE_CHILD_3) { - if (!GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { + if (!GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { this->collider.dim.height += 200; this->actionFunc = func_80A995CC; return; @@ -1211,7 +1211,7 @@ void func_80A99438(EnKo* this, PlayState* play) { } void func_80A99504(EnKo* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_POTION, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_TRADE_ODD_POTION, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index 9ee9f6d0a..24abf54ff 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -73,7 +73,7 @@ static AnimationInfo sAnimationInfo[] = { u16 EnKz_GetTextNoMaskChild(PlayState* play, EnKz* this) { Player* player = GET_PLAYER(play); - if (GameInteractor_Should(GI_VB_KING_ZORA_THANK_CHILD, ( + if (GameInteractor_Should(VB_KING_ZORA_THANK_CHILD, ( CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) ), this)) { return 0x402B; @@ -91,7 +91,7 @@ u16 EnKz_GetTextNoMaskAdult(PlayState* play, EnKz* this) { // this works because both ITEM_NONE and later trade items are > ITEM_FROG if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_FROG) { if (!Flags_GetInfTable(INFTABLE_139)) { - if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, ( + if (!GameInteractor_Should(VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, ( !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ), this)) { return 0x401F; @@ -242,7 +242,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) { Player* player = GET_PLAYER(play); if (func_80A9C95C(play, this, &this->interactInfo.talkState, 340.0f, EnKz_GetText, func_80A9C6C0)) { - if (GameInteractor_Should(GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, (this->actor.textId == 0x401A), this) && + if (GameInteractor_Should(VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, (this->actor.textId == 0x401A), this) && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { if (func_8002F368(play) == EXCH_ITEM_LETTER_RUTO) { @@ -258,7 +258,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) { if (LINK_IS_ADULT) { if ((INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) && (func_8002F368(play) == EXCH_ITEM_PRESCRIPTION)) { - if (GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) { + if (GameInteractor_Should(VB_TRADE_PRESCRIPTION, true, this)) { this->actor.textId = 0x4014; this->sfxPlayed = false; player->actor.textId = this->actor.textId; @@ -273,7 +273,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) { player->actor.textId = this->actor.textId; } else { this->actor.textId = - !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + !GameInteractor_Should(VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)), this) ? 0x401F : 0x4012; @@ -345,7 +345,7 @@ void EnKz_Init(Actor* thisx, PlayState* play) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; Animation_ChangeByInfo(&this->skelanime, sAnimationInfo, ENKZ_ANIM_0); - if (GameInteractor_Should(GI_VB_KING_ZORA_BE_MOVED, ( + if (GameInteractor_Should(VB_KING_ZORA_BE_MOVED, ( Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) ), this)) { EnKz_SetMovedPos(this, play); @@ -448,8 +448,8 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { f32 yRange; if (Actor_HasParent(&this->actor, play) || ( - (this->isTrading && !GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) || - (!this->isTrading && !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, true, this)) + (this->isTrading && !GameInteractor_Should(VB_TRADE_PRESCRIPTION, true, this)) || + (!this->isTrading && !GameInteractor_Should(VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, true, this)) )) { this->actor.parent = NULL; this->interactInfo.talkState = NPC_TALK_STATE_TALKING; @@ -469,7 +469,7 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { void EnKz_StartTimer(EnKz* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && GameInteractor_Should(GI_VB_TRADE_TIMER_FROG, true, NULL)) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && GameInteractor_Should(VB_TRADE_TIMER_FROG, true, NULL)) { func_80088AA0(180); // start timer2 with 3 minutes gSaveContext.eventInf[1] &= ~1; } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 267a49bcd..c9521b133 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -91,8 +91,8 @@ static void* sEyeTextures[] = { }; u16 EnMa1_GetText(PlayState* play, Actor* thisx) { - bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); - bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); + bool malonReturnedFromCastle = GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); u16 faceReaction = Text_GetFaceReaction(play, 0x17); if (faceReaction != 0) { @@ -185,7 +185,7 @@ s16 func_80AA0778(PlayState* play, Actor* thisx) { } s32 func_80AA08C4(EnMa1* this, PlayState* play) { - bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonReturnedFromCastle = GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); if ((this->actor.shape.rot.z == 3) && (gSaveContext.sceneSetupIndex == 5)) { return 1; @@ -269,8 +269,8 @@ void func_80AA0B74(EnMa1* this) { void EnMa1_Init(Actor* thisx, PlayState* play) { EnMa1* this = (EnMa1*)thisx; - bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); - bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); + bool malonReturnedFromCastle = GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); s32 pad; ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 18.0f); @@ -306,8 +306,8 @@ void EnMa1_Destroy(Actor* thisx, PlayState* play) { } void func_80AA0D88(EnMa1* this, PlayState* play) { - bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); - bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); + bool malonReturnedFromCastle = GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (this->skelAnime.animation != &gMalonChildIdleAnim) { @@ -331,7 +331,7 @@ void func_80AA0D88(EnMa1* this, PlayState* play) { } void func_80AA0EA0(EnMa1* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->actor.parent = NULL; this->actionFunc = func_80AA0EFC; } else { @@ -340,7 +340,7 @@ void func_80AA0EA0(EnMa1* this, PlayState* play) { } void func_80AA0EFC(EnMa1* this, PlayState* play) { - if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { + if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN || !GameInteractor_Should(VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->actionFunc = func_80AA0D88; Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index d2e168ab1..280648aac 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -373,7 +373,7 @@ u16 EnMd_GetTextKokiriForest(PlayState* play, EnMd* this) { this->unk_208 = 0; this->unk_209 = TEXT_STATE_NONE; - if (GameInteractor_Should(GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { + if (GameInteractor_Should(VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { return 0x1045; } @@ -723,7 +723,7 @@ void func_80AAB948(EnMd* this, PlayState* play) { } if ( - (GameInteractor_Should(GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, this->interactInfo.talkState == NPC_TALK_STATE_ACTION, this) && play->sceneNum == SCENE_KOKIRI_FOREST) || + (GameInteractor_Should(VB_MOVE_MIDO_IN_KOKIRI_FOREST, this->interactInfo.talkState == NPC_TALK_STATE_ACTION, this) && play->sceneNum == SCENE_KOKIRI_FOREST) || this->interactInfo.talkState == NPC_TALK_STATE_ACTION ) { if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index 64510807c..148882730 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -93,11 +93,11 @@ void func_80AACA40(EnMk* this, PlayState* play) { } void func_80AACA94(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { + if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(VB_TRADE_FROG, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - if (GameInteractor_Should(GI_VB_TRADE_TIMER_EYEDROPS, true, NULL)) { + if (GameInteractor_Should(VB_TRADE_TIMER_EYEDROPS, true, NULL)) { func_80088AA0(240); gSaveContext.eventInf[1] &= ~1; } @@ -109,7 +109,7 @@ void func_80AACA94(EnMk* this, PlayState* play) { void func_80AACB14(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACA94; - if (GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { + if (GameInteractor_Should(VB_TRADE_FROG, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } @@ -137,7 +137,7 @@ void func_80AACC04(EnMk* this, PlayState* play) { if (this->timer > 0) { this->timer--; } else { - this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; + this->timer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; this->actionFunc = func_80AACBAC; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); @@ -150,7 +150,7 @@ void func_80AACCA0(EnMk* this, PlayState* play) { this->timer--; this->actor.shape.rot.y += 0x800; } else { - this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 120 : 0; + this->timer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 120 : 0; this->actionFunc = func_80AACC04; Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f); @@ -166,7 +166,7 @@ void func_80AACD48(EnMk* this, PlayState* play) { this->actionFunc = func_80AACCA0; play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; - this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; + this->timer = GameInteractor_Should(VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); this->flags &= ~2; @@ -200,7 +200,7 @@ void func_80AACEE8(EnMk* this, PlayState* play) { } void func_80AACFA0(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; Flags_SetItemGetInf(ITEMGETINF_10); @@ -212,7 +212,7 @@ void func_80AACFA0(EnMk* this, PlayState* play) { void func_80AAD014(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACFA0; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } @@ -233,7 +233,7 @@ void EnMk_Wait(EnMk* this, PlayState* play) { player->actor.textId = this->actor.textId; this->actionFunc = func_80AACA40; } else { - if (GameInteractor_Should(GI_VB_USE_EYEDROP_DIALOGUE, ( + if (GameInteractor_Should(VB_USE_EYEDROP_DIALOGUE, ( INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS ), this)) { player->actor.textId = 0x4032; diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index 244be5cde..a28f1c19c 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -128,12 +128,12 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } else if (Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, (gSaveContext.rupees >= sPrices[BEANS_BOUGHT]), this)) { + if (!GameInteractor_Should(VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, (gSaveContext.rupees >= sPrices[BEANS_BOUGHT]), this)) { Message_ContinueTextbox(play, 0x4069); // not enough rupees text return; } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_BEAN, 90.0f, 10.0f); this->actionFunc = EnMs_Sell; } diff --git a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c index 9a3990cf8..1cb2d7908 100644 --- a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c +++ b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c @@ -327,7 +327,7 @@ void EnNb_GiveMedallion(EnNb* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xC); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_SPIRIT); } } @@ -345,7 +345,7 @@ void EnNb_SetupChamberCsImpl(EnNb* this, PlayState* play) { this->action = NB_CHAMBER_UNDERGROUND; play->csCtx.segment = &D_80AB431C; gSaveContext.cutsceneTrigger = 2; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_SPIRIT); } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 612abcf0e..a03319dfc 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -204,7 +204,7 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) { EnNiw* currentCucco; s32 phi_s1; - if (GameInteractor_Should(GI_VB_SET_CUCCO_COUNT, true, this)) { + if (GameInteractor_Should(VB_SET_CUCCO_COUNT, true, this)) { this->cuccosInPen = 0; } currentCucco = (EnNiw*)play->actorCtx.actorLists[ACTORCAT_PROP].head; @@ -312,7 +312,7 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) { if (!Flags_GetItemGetInf(ITEMGETINF_0C)) { this->actor.parent = NULL; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) { this->getItemId = GI_BOTTLE; Actor_OfferGetItem(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); } else { @@ -404,7 +404,7 @@ void func_80ABA9B8(EnNiwLady* this, PlayState* play) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); this->actionFunc = func_80ABAC00; } else { @@ -439,7 +439,7 @@ void func_80ABAB08(EnNiwLady* this, PlayState* play) { case 0: Message_CloseTextbox(play); this->actor.parent = NULL; - if (GameInteractor_Should(GI_VB_TRADE_POCKET_CUCCO, true, this)) { + if (GameInteractor_Should(VB_TRADE_POCKET_CUCCO, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); this->actionFunc = func_80ABAC00; } else { @@ -481,7 +481,7 @@ void func_80ABAC84(EnNiwLady* this, PlayState* play) { } osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (LINK_IS_ADULT) { - if (GameInteractor_Should(GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, true, this)) { + if (GameInteractor_Should(VB_ANJU_SET_OBTAINED_TRADE_ITEM, true, this)) { if (!Flags_GetItemGetInf(ITEMGETINF_2C)) { Flags_SetItemGetInf(ITEMGETINF_2C); } else { diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 2a811ee9a..017c3fac1 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -193,7 +193,7 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; - } else if (((this->type != 4) || GameInteractor_Should(GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME), this)) && + } else if (((this->type != 4) || GameInteractor_Should(VB_BE_ELIGIBLE_TO_OPEN_DOT, !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME), this)) && ((this->type != 6) || !Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) && (this->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) { @@ -245,20 +245,20 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN); break; case 2: // Kakariko Windmill - if (GameInteractor_Should(GI_VB_PLAY_DRAIN_WELL_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_DRAIN_WELL_CS, true, this)) { play->csCtx.segment = D_80ABF9D0; gSaveContext.cutsceneTrigger = 1; } func_800F574C(1.18921f, 0x5A); break; case 4: // Door of Time - if (GameInteractor_Should(GI_VB_PLAY_DOOR_OF_TIME_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_DOOR_OF_TIME_CS, true, this)) { play->csCtx.segment = D_80ABFB40; gSaveContext.cutsceneTrigger = 1; } break; case 6: // Royal Family Tomb - if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ROYAL_FAMILY_TOMB_CS, true, this)) { play->csCtx.segment = LINK_IS_ADULT ? SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_003C80) : SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_005020); gSaveContext.cutsceneTrigger = 1; @@ -313,7 +313,7 @@ void func_80ABF7CC(EnOkarinaTag* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - if (GameInteractor_Should(GI_VB_PLAY_SUNS_SONG_CS, !CHECK_QUEST_ITEM(QUEST_SONG_SUN), this)) { + if (GameInteractor_Should(VB_PLAY_SUNS_SONG_CS, !CHECK_QUEST_ITEM(QUEST_SONG_SUN), this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gSunSongGraveSunSongTeachCs); gSaveContext.cutsceneTrigger = 1; } diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index d46424b0b..c5f6acaee 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -283,7 +283,7 @@ s32 EnOwl_CheckInitTalk(EnOwl* this, PlayState* play, u16 textId, f32 targetDist } else { this->actor.textId = textId; distCheck = (flags & 2) ? 200.0f : 1000.0f; - if (GameInteractor_Should(GI_VB_OWL_INTERACTION, this->actor.xzDistToPlayer < targetDist, this)) { + if (GameInteractor_Should(VB_OWL_INTERACTION, this->actor.xzDistToPlayer < targetDist, this)) { this->actor.flags |= ACTOR_FLAG_WILL_TALK; func_8002F1C4(&this->actor, play, targetDist, distCheck, 0); } diff --git a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c index eafa8b82e..e321540af 100644 --- a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c +++ b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c @@ -127,7 +127,7 @@ void func_80AE7590(EnRl* this, PlayState* play) { pos.y = player->actor.world.pos.y + 80.0f; pos.z = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_LIGHT); } this->lightMedallionGiven = 1; diff --git a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c index 93d1fd99c..008e0b6a5 100644 --- a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c +++ b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c @@ -261,7 +261,7 @@ void func_80AF2A38(EnRu2* this, PlayState* play) { f32 posZ = player->actor.world.pos.z; Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 10); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_WATER); } } @@ -276,7 +276,7 @@ void func_80AF2AB4(EnRu2* this, PlayState* play) { this->action = 1; play->csCtx.segment = &D_80AF411C; gSaveContext.cutsceneTrigger = 2; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { Item_Give(play, ITEM_MEDALLION_WATER); } temp = this->actor.world.rot.y + 0x8000; diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index f2b2db3f9..616a4d700 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -391,10 +391,10 @@ s32 func_80AF5DFC(EnSa* this, PlayState* play) { return 1; } if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW && (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER))) { - return GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, !CHECK_QUEST_ITEM(QUEST_SONG_SARIA), NULL) ? 5 : 2; + return GameInteractor_Should(VB_BE_ELIGIBLE_FOR_SARIAS_SONG, !CHECK_QUEST_ITEM(QUEST_SONG_SARIA), NULL) ? 5 : 2; } if (play->sceneNum == SCENE_KOKIRI_FOREST && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - if (GameInteractor_Should(GI_VB_NOT_BE_GREETED_BY_SARIA, Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA), NULL)) { + if (GameInteractor_Should(VB_NOT_BE_GREETED_BY_SARIA, Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA), NULL)) { return 1; } return 4; @@ -626,7 +626,7 @@ void func_80AF683C(EnSa* this, PlayState* play) { if (!(player->actor.world.pos.z >= -2220.0f) && !Play_InCsMode(play)) { // SOH [General] This flag was previously unused, but was named accordingly so we will make use of it. (Normally we should opt for soh_inf) Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); - if (GameInteractor_Should(GI_VB_PLAY_SARIAS_SONG_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_SARIAS_SONG_CS, true, this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730); gSaveContext.cutsceneTrigger = 1; this->actionFunc = func_80AF68E4; @@ -708,7 +708,7 @@ void func_80AF68E4(EnSa* this, PlayState* play) { void func_80AF6B20(EnSa* this, PlayState* play) { if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW) { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) { Item_Give(play, ITEM_SONG_SARIA); } EnSa_ChangeAnim(this, ENSA_ANIM1_6); diff --git a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index 0f300d16f..c6aa6d56a 100644 --- a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -70,7 +70,7 @@ void EnShopnuts_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); Collider_UpdateCylinder(&this->actor, &this->collider); - if (GameInteractor_Should(GI_VB_BUSINESS_SCRUB_DESPAWN, + if (GameInteractor_Should(VB_BUSINESS_SCRUB_DESPAWN, ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) || ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))), diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 8eb669d2d..170eed16e 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -94,7 +94,7 @@ void func_80AFB768(EnSi* this, PlayState* play) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { Item_Give(play, ITEM_SKULL_TOKEN); player->actor.freezeTimer = 10; Message_StartTextbox(play, 0xB4, NULL); @@ -118,7 +118,7 @@ void func_80AFB89C(EnSi* this, PlayState* play) { this->actor.shape.rot.y += 0x400; if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_HOOKSHOT_ATTACHED)) { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { Item_Give(play, ITEM_SKULL_TOKEN); player->actor.freezeTimer = 10; Message_StartTextbox(play, 0xB4, NULL); @@ -131,7 +131,7 @@ void func_80AFB89C(EnSi* this, PlayState* play) { void func_80AFB950(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && GameInteractor_Should(VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 94df7a49f..7398d00c0 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1039,7 +1039,7 @@ void EnSkj_SariaSongTalk(EnSkj* this, PlayState* play) { EnSkj_SetupWaitInRange(this); } else { func_80AFFE24(this); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } @@ -1051,11 +1051,11 @@ void func_80AFFE24(EnSkj* this) { } void func_80AFFE44(EnSkj* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { this->actor.parent = NULL; EnSkj_SetupPostSariasSong(this); } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } @@ -1066,7 +1066,7 @@ void EnSkj_SetupPostSariasSong(EnSkj* this) { } void EnSkj_ChangeModeAfterSong(EnSkj* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { Flags_SetItemGetInf(ITEMGETINF_16); EnSkj_SetNaviId(this); EnSkj_SetupWaitInRange(this); @@ -1541,7 +1541,7 @@ void EnSkj_WaitForOfferResponse(EnSkj* this, PlayState* play) { void EnSkj_WonOcarinaMiniGame(EnSkj* this, PlayState* play) { if (D_80B01EA0) { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, true, this)) { this->actionFunc = EnSkj_WaitToGiveReward; } } else { diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index f8b50d823..c55af5cd4 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -277,14 +277,14 @@ void EnSth_GivePlayerItem(EnSth* this, PlayState* play) { } void EnSth_GiveReward(EnSth* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { this->actor.parent = NULL; EnSth_SetupAction(this, EnSth_RewardObtainedTalk); gSaveContext.eventChkInf[EVENTCHKINF_SKULLTULA_REWARD_INDEX] |= this->eventFlag; if (this->eventFlag != 0) { GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SKULLTULA_REWARD_INDEX << 4) + sEventFlagsShift[this->actor.params]); } - } else if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { + } else if (GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { EnSth_GivePlayerItem(this, play); } EnSth_FacePlayer(this, play); @@ -294,7 +294,7 @@ void EnSth_RewardUnobtainedTalk(EnSth* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); EnSth_SetupAction(this, EnSth_GiveReward); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { EnSth_GivePlayerItem(this, play); } } diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index a406049a9..4928048a3 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -386,7 +386,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->getItemId = GI_RUPEE_PURPLE; } } - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } this->actionFunc = EnSyatekiMan_GivePrize; @@ -418,7 +418,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { this->actionFunc = EnSyatekiMan_FinishPrize; } else { Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); @@ -427,12 +427,12 @@ void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { void EnSyatekiMan_FinishPrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { + if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (!LINK_IS_ADULT) { Flags_SetItemGetInf(ITEMGETINF_0D); - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50), this)) { + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50), this)) { Flags_SetItemGetInf(ITEMGETINF_0E); } this->gameResult = SYATEKI_RESULT_NONE; diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index cdec042bc..0063b7c31 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -467,7 +467,7 @@ void func_80B14B6C(EnTa* this, PlayState* play) { EnTa_SetupAction(this, func_80B14AF4, EnTa_AnimRepeatCurrent); this->unk_2CC = 5; Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_EndCutscene(play, csCamIdx); } Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim); @@ -869,7 +869,7 @@ void EnTa_TalkGeneralInLonLonHouse(EnTa* this, PlayState* play) { } void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { this->actor.parent = NULL; this->actionFunc = EnTa_TalkGeneralInLonLonHouse; if (!(this->unk_2E0 & 0x2)) { @@ -879,7 +879,7 @@ void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { } else if (this->unk_2E0 & 2) { Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } } @@ -891,7 +891,7 @@ void EnTa_TalkAfterCuccoGameFirstWon(EnTa* this, PlayState* play) { Message_CloseTextbox(play); this->unk_2E0 &= ~0x2; EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index 342eed149..68979daca 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -495,7 +495,7 @@ void EnTk_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (GameInteractor_Should(GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD, this)) { + if (GameInteractor_Should(VB_DAMPE_IN_GRAVEYARD_DESPAWN, gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD, this)) { Actor_Kill(&this->actor); return; } @@ -601,7 +601,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->rewardTimer = 0; - if (GameInteractor_Should(GI_VB_BE_VALID_GRAVEDIGGING_SPOT, this->validDigHere == 1, this)) { + if (GameInteractor_Should(VB_BE_VALID_GRAVEDIGGING_SPOT, this->validDigHere == 1, this)) { rewardOrigin.x = 0.0f; rewardOrigin.y = 0.0f; rewardOrigin.z = -40.0f; @@ -615,12 +615,12 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->currentReward = EnTk_ChooseReward(this); - if (GameInteractor_Should(GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, this->currentReward == 3, this)) { + if (GameInteractor_Should(VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, this->currentReward == 3, this)) { /* * Upgrade the purple rupee reward to the heart piece if this * is the first grand prize dig. */ - if (GameInteractor_Should(GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, !Flags_GetItemGetInf(ITEMGETINF_1C), this)) { + if (GameInteractor_Should(VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, !Flags_GetItemGetInf(ITEMGETINF_1C), this)) { Flags_SetItemGetInf(ITEMGETINF_1C); this->currentReward = 4; } diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index 275b62ba1..88eeb6ebd 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -291,7 +291,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { s16 sp32; s16 sp30; - if (this->unk_1E4 == 3 && !GameInteractor_Should(GI_VB_FIX_SAW_SOFTLOCK, false, NULL)) { + if (this->unk_1E4 == 3 && !GameInteractor_Should(VB_FIX_SAW_SOFTLOCK, false, NULL)) { Actor_ProcessTalkRequest(&this->actor, play); Message_ContinueTextbox(play, this->actor.textId); this->unk_1E4 = 1; @@ -312,7 +312,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { } if (this->unk_1E4 == 4) { - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_SAW, true, this)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_TRADE_SAW, true, this)) { this->actor.parent = NULL; this->unk_1E4 = 5; Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index 5aeb0a86b..257ed2f86 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -195,7 +195,7 @@ void func_80B3A3D4(EnWonderTalk2* this, PlayState* play) { this->unk_15A = true; } this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED); - if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { + if (GameInteractor_Should(VB_WONDER_TALK, true, this)) { Player_SetCsActionWithHaltedActors(play, NULL, 7); } this->unk_156 = true; @@ -255,7 +255,7 @@ void func_80B3A4F8(EnWonderTalk2* this, PlayState* play) { } this->unk_158 = 0; if (!this->unk_156) { - if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { + if (GameInteractor_Should(VB_WONDER_TALK, true, this)) { Message_StartTextbox(play, this->actor.textId, NULL); Player_SetCsActionWithHaltedActors(play, NULL, 8); } diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 283283804..b51b7f630 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -298,15 +298,15 @@ s32 EnXc_MinuetCS(EnXc* this, PlayState* play) { if (z < -2225.0f) { if (!Play_InCsMode(play)) { - if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gMinuetCs); gSaveContext.cutsceneTrigger = 1; } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) { Item_Give(play, ITEM_SONG_MINUET); } - if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { return true; } } @@ -335,15 +335,15 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { if ((posRot->pos.x > -784.0f) && (posRot->pos.x < -584.0f) && (posRot->pos.y > 447.0f) && (posRot->pos.y < 647.0f) && (posRot->pos.z > -446.0f) && (posRot->pos.z < -246.0f) && !Play_InCsMode(play)) { - if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gDeathMountainCraterBoleroCs); gSaveContext.cutsceneTrigger = 1; } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) { Item_Give(play, ITEM_SONG_BOLERO); } - if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { return true; } } @@ -354,7 +354,7 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { void EnXc_SetupSerenadeAction(EnXc* this, PlayState* play) { // Player is adult and does not have iron boots and has not learned Serenade - if (GameInteractor_Should(GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT, NULL)) { + if (GameInteractor_Should(VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT, NULL)) { this->action = SHEIK_ACTION_SERENADE; osSyncPrintf("水のセレナーデ シーク誕生!!!!!!!!!!!!!!!!!!\n"); } else { @@ -367,18 +367,18 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { if (this->actor.params == SHEIK_TYPE_SERENADE) { Player* player = GET_PLAYER(play); s32 stateFlags = player->stateFlags1; - if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), NULL) && + if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), NULL) && !(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && !Play_InCsMode(play)) { - if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { Cutscene_SetSegment(play, &gIceCavernSerenadeCs); gSaveContext.cutsceneTrigger = 1; } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag - if (GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) { Item_Give(play, ITEM_SONG_SERENADE); } osSyncPrintf("ブーツを取った!!!!!!!!!!!!!!!!!!\n"); - if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { return true; } } @@ -2185,17 +2185,17 @@ void EnXc_InitTempleOfTime(EnXc* this, PlayState* play) { if (LINK_IS_ADULT) { if (!Flags_GetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL)) { Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); - if (GameInteractor_Should(GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs); gSaveContext.cutsceneTrigger = 1; } func_80B3EBF0(this, play); - } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), NULL)) { + } else if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) { Item_Give(play, ITEM_SONG_PRELUDE); } - if (GameInteractor_Should(GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, true, NULL)) { + if (GameInteractor_Should(VB_PLAY_PRELUDE_OF_LIGHT_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimePreludeCs); gSaveContext.cutsceneTrigger = 1; } diff --git a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c index 9bc53169b..40351399e 100644 --- a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c +++ b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c @@ -634,7 +634,7 @@ void EnZl2_GiveLightArrows(EnZl2* this, PlayState* play) { posY = player->actor.world.pos.y + 80.0f; posZ = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { Item_Give(play, ITEM_ARROW_LIGHT); } this->unk_244 = 1; diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index f2abefd97..215d6400c 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -1108,7 +1108,7 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { Camera_ChangeSetting(GET_ACTIVE_CAM(play), 1); this->talkState = 7; play->talkWithPlayer(play, &this->actor); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } @@ -1117,7 +1117,7 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { } break; case 7: - if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->talkState++; } else { diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index d14862553..358a2efe7 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -179,7 +179,7 @@ void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) { if ( Actor_HasParent(&this->actor, play) || ( - !GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL) && + !GameInteractor_Should(VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL) && (this->actor.xzDistToPlayer < 20.0f) && (fabsf(this->actor.yDistToPlayer) < 10.0f) && GET_PLAYER(play)->stateFlags2 & PLAYER_STATE2_DIVING ) @@ -189,7 +189,7 @@ void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) { this->actionFunc = ItemOcarina_StartSoTCutscene; this->actor.draw = NULL; } else { - if (GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) { + if (GameInteractor_Should(VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) { Actor_OfferGetItem(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); } diff --git a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c index 9463d45af..94416ff5d 100644 --- a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c +++ b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c @@ -57,7 +57,7 @@ void ObjDekujr_Init(Actor* thisx, PlayState* play) { this->unk_19C = 0; this->unk_19B = 1; } - if (!GameInteractor_Should(GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST), this)) { + if (!GameInteractor_Should(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST), this)) { Actor_Kill(thisx); } else { ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f); diff --git a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c index 9220c6be4..e08291480 100644 --- a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c +++ b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c @@ -250,7 +250,7 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) { subType = (this->dyna.actor.params >> 4 & 7); Flags_SetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { if (subType == 0 || subType == 4) { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); } else { @@ -269,7 +269,7 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); if ((this->dyna.actor.params >> 4 & 7) == 1) { - if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); } this->cooldownOn = true; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 43a34c778..0b9b2303d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6866,7 +6866,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { } func_80836898(play, this, func_8083A434); - if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, chest)) { + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_CHEST, true, chest)) { this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; func_8083AE40(this, giEntry.objectId); } @@ -8522,7 +8522,7 @@ void func_80842A88(PlayState* play, Player* this) { s32 func_80842AC4(PlayState* play, Player* this) { if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) { - if (GameInteractor_Should(GI_VB_DEKU_STICK_BREAK, AMMO(ITEM_STICK) != 0, NULL)) { + if (GameInteractor_Should(VB_DEKU_STICK_BREAK, AMMO(ITEM_STICK) != 0, NULL)) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; @@ -10238,7 +10238,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { if ((sp50 == 0) || (sp50 < -1)) { titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart; - if (GameInteractor_Should(GI_VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard, NULL)) { + if (GameInteractor_Should(VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard, NULL)) { if ((gSaveContext.sceneSetupIndex < 4) && (gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field & ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) && @@ -10944,21 +10944,21 @@ static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 }; void Player_UpdateBurningDekuStick(PlayState* play, Player* this) { f32 temp; - if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, this->unk_85C == 0.0f, NULL)) { + if (GameInteractor_Should(VB_DEKU_STICK_BURN_OUT, this->unk_85C == 0.0f, NULL)) { Player_UseItem(play, this, ITEM_NONE); return; } temp = 1.0f; uint8_t vanillaShouldBurnOutCondition = DECR(this->unk_860) == 0; - if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, vanillaShouldBurnOutCondition, NULL)) { + if (GameInteractor_Should(VB_DEKU_STICK_BURN_OUT, vanillaShouldBurnOutCondition, NULL)) { Inventory_ChangeAmmo(ITEM_STICK, -1); this->unk_860 = 1; temp = 0.0f; this->unk_85C = temp; } else if (this->unk_860 > 200) { temp = (210 - this->unk_860) / 10.0f; - } else if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_DOWN, this->unk_860 < 20, NULL)) { + } else if (GameInteractor_Should(VB_DEKU_STICK_BURN_DOWN, this->unk_860 < 20, NULL)) { temp = this->unk_860 / 20.0f; this->unk_85C = temp; } @@ -11260,7 +11260,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { func_80836BEC(this, play); if (this->heldItemAction == PLAYER_IA_DEKU_STICK && - GameInteractor_Should(GI_VB_DEKU_STICK_BE_ON_FIRE, this->unk_860 != 0, NULL)) { + GameInteractor_Should(VB_DEKU_STICK_BE_ON_FIRE, this->unk_860 != 0, NULL)) { Player_UpdateBurningDekuStick(play, this); } else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) { this->unk_860++; @@ -13545,7 +13545,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { play->msgCtx.msgMode = MSGMODE_TEXT_DONE; } else { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { - if (GameInteractor_Should(GI_VB_PLAY_NABOORU_CAPTURED_CS, this->getItemId == GI_GAUNTLETS_SILVER, NULL)) { + if (GameInteractor_Should(VB_PLAY_NABOORU_CAPTURED_CS, this->getItemId == GI_GAUNTLETS_SILVER, NULL)) { play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.nextCutsceneIndex = 0xFFF1; From 4bd0f2d2c1b176217909f10fdadb9c13121bdb06 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 5 May 2024 16:55:56 -0500 Subject: [PATCH 218/300] Port new hook filtering patterns from 2ship (#4117) --- .../game-interactor/GameInteractor.h | 247 +++++++++++++----- .../game-interactor/GameInteractor_Hooks.cpp | 27 ++ 2 files changed, 213 insertions(+), 61 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 3a3a30d18..cca978b2d 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -431,11 +431,17 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state); #include #endif -#define DEFINE_HOOK(name, type) \ - struct name { \ - typedef std::function fn; \ +typedef uint32_t HOOK_ID; + +#define DEFINE_HOOK(name, args) \ + struct name { \ + typedef std::function fn; \ + typedef std::function filter; \ } +#define REGISTER_VB_SHOULD(flag, body) \ + GameInteractor::Instance->RegisterGameHookForID(flag, [](GIVanillaBehavior _, bool* should, void* opt) body) + class GameInteractor { public: static GameInteractor* Instance; @@ -487,11 +493,22 @@ public: static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect); // Game Hooks - uint32_t nextHookId = 1; - template struct RegisteredGameHooks { inline static std::unordered_map functions; }; - template struct HooksToUnregister { inline static std::vector hooks; }; - template uint32_t RegisterGameHook(typename H::fn h) { - // Ensure hook id is unique and not 0, which is reserved for invalid hooks + HOOK_ID nextHookId = 1; + template struct RegisteredGameHooks { + inline static std::unordered_map functions; + inline static std::unordered_map> functionsForID; + inline static std::unordered_map> functionsForPtr; + inline static std::unordered_map> functionsForFilter; + }; + template struct HooksToUnregister { + inline static std::vector hooks; + inline static std::vector hooksForID; + inline static std::vector hooksForPtr; + inline static std::vector hooksForFilter; + }; + + // General Hooks + template HOOK_ID RegisterGameHook(typename H::fn h) { if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1; while (RegisteredGameHooks::functions.find(this->nextHookId) != RegisteredGameHooks::functions.end()) { this->nextHookId++; @@ -500,10 +517,10 @@ public: RegisteredGameHooks::functions[this->nextHookId] = h; return this->nextHookId++; } - template void UnregisterGameHook(uint32_t id) { - HooksToUnregister::hooks.push_back(id); + template void UnregisterGameHook(HOOK_ID hookId) { + if (hookId == 0) return; + HooksToUnregister::hooks.push_back(hookId); } - template void ExecuteHooks(Args&&... args) { for (auto& hookId : HooksToUnregister::hooks) { RegisteredGameHooks::functions.erase(hookId); @@ -514,59 +531,167 @@ public: } } - DEFINE_HOOK(OnLoadGame, void(int32_t fileNum)); - DEFINE_HOOK(OnExitGame, void(int32_t fileNum)); - DEFINE_HOOK(OnGameFrameUpdate, void()); - DEFINE_HOOK(OnItemReceive, void(GetItemEntry itemEntry)); - DEFINE_HOOK(OnSaleEnd, void(GetItemEntry itemEntry)); - DEFINE_HOOK(OnTransitionEnd, void(int16_t sceneNum)); - DEFINE_HOOK(OnSceneInit, void(int16_t sceneNum)); - DEFINE_HOOK(OnSceneFlagSet, void(int16_t sceneNum, int16_t flagType, int16_t flag)); - DEFINE_HOOK(OnSceneFlagUnset, void(int16_t sceneNum, int16_t flagType, int16_t flag)); - DEFINE_HOOK(OnFlagSet, void(int16_t flagType, int16_t flag)); - DEFINE_HOOK(OnFlagUnset, void(int16_t flagType, int16_t flag)); - DEFINE_HOOK(OnSceneSpawnActors, void()); - DEFINE_HOOK(OnPlayerUpdate, void()); - DEFINE_HOOK(OnOcarinaSongAction, void()); - DEFINE_HOOK(OnShopSlotChange, void(uint8_t cursorIndex, int16_t price)); - DEFINE_HOOK(OnActorInit, void(void* actor)); - DEFINE_HOOK(OnActorUpdate, void(void* actor)); - DEFINE_HOOK(OnActorKill, void(void* actor)); - DEFINE_HOOK(OnEnemyDefeat, void(void* actor)); - DEFINE_HOOK(OnPlayerBonk, void()); - DEFINE_HOOK(OnPlayDestroy, void()); - DEFINE_HOOK(OnPlayDrawEnd, void()); + // ID based Hooks + template HOOK_ID RegisterGameHookForID(int32_t id, typename H::fn h) { + if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1; + while (RegisteredGameHooks::functionsForID[id].find(this->nextHookId) != RegisteredGameHooks::functionsForID[id].end()) { + this->nextHookId++; + } - DEFINE_HOOK(OnVanillaBehavior, void(GIVanillaBehavior flag, bool* result, void* opt)); + RegisteredGameHooks::functionsForID[id][this->nextHookId] = h; + return this->nextHookId++; + } + template void UnregisterGameHookForID(HOOK_ID hookId) { + if (hookId == 0) return; + HooksToUnregister::hooksForID.push_back(hookId); + } + template void ExecuteHooksForID(int32_t id, Args&&... args) { + for (auto& hookId : HooksToUnregister::hooksForID) { + for (auto it = RegisteredGameHooks::functionsForID[id].begin(); it != RegisteredGameHooks::functionsForID[id].end(); ) { + if (it->first == hookId) { + it = RegisteredGameHooks::functionsForID[id].erase(it); + HooksToUnregister::hooksForID.erase(std::remove(HooksToUnregister::hooksForID.begin(), HooksToUnregister::hooksForID.end(), hookId), HooksToUnregister::hooksForID.end()); + } else { + ++it; + } + } + } + for (auto& hook : RegisteredGameHooks::functionsForID[id]) { + hook.second(std::forward(args)...); + } + } - DEFINE_HOOK(OnSaveFile, void(int32_t fileNum)); - DEFINE_HOOK(OnLoadFile, void(int32_t fileNum)); - DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum)); - - DEFINE_HOOK(OnDialogMessage, void()); - DEFINE_HOOK(OnPresentTitleCard, void()); - DEFINE_HOOK(OnInterfaceUpdate, void()); - DEFINE_HOOK(OnKaleidoscopeUpdate, void(int16_t inDungeonScene)); - - DEFINE_HOOK(OnPresentFileSelect, void()); - DEFINE_HOOK(OnUpdateFileSelectSelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileSelectConfirmationSelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileCopySelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileCopyConfirmationSelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileEraseSelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileEraseConfirmationSelection, void(uint16_t optionIndex)); - DEFINE_HOOK(OnUpdateFileAudioSelection, void(uint8_t optionIndex)); - DEFINE_HOOK(OnUpdateFileTargetSelection, void(uint8_t optionIndex)); - DEFINE_HOOK(OnUpdateFileLanguageSelection, void(uint8_t optionIndex)); - DEFINE_HOOK(OnUpdateFileQuestSelection, void(uint8_t questIndex)); - DEFINE_HOOK(OnUpdateFileBossRushOptionSelection, void(uint8_t optionIndex, uint8_t optionValue)); - DEFINE_HOOK(OnUpdateFileNameSelection, void(int16_t charCode)); - - DEFINE_HOOK(OnSetGameLanguage, void()); + // PTR based Hooks + template HOOK_ID RegisterGameHookForPtr(uintptr_t ptr, typename H::fn h) { + if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1; + while (RegisteredGameHooks::functionsForPtr[ptr].find(this->nextHookId) != RegisteredGameHooks::functionsForPtr[ptr].end()) { + this->nextHookId++; + } - DEFINE_HOOK(OnFileDropped, void(std::string filePath)); - DEFINE_HOOK(OnAssetAltChange, void()); - DEFINE_HOOK(OnKaleidoUpdate, void()); + RegisteredGameHooks::functionsForPtr[ptr][this->nextHookId] = h; + return this->nextHookId++; + } + template void UnregisterGameHookForPtr(HOOK_ID hookId) { + if (hookId == 0) return; + HooksToUnregister::hooksForPtr.push_back(hookId); + } + template void ExecuteHooksForPtr(uintptr_t ptr, Args&&... args) { + for (auto& hookId : HooksToUnregister::hooksForPtr) { + for (auto it = RegisteredGameHooks::functionsForPtr[ptr].begin(); it != RegisteredGameHooks::functionsForPtr[ptr].end(); ) { + if (it->first == hookId) { + it = RegisteredGameHooks::functionsForPtr[ptr].erase(it); + HooksToUnregister::hooksForPtr.erase(std::remove(HooksToUnregister::hooksForPtr.begin(), HooksToUnregister::hooksForPtr.end(), hookId), HooksToUnregister::hooksForPtr.end()); + } else { + ++it; + } + } + } + for (auto& hook : RegisteredGameHooks::functionsForPtr[ptr]) { + hook.second(std::forward(args)...); + } + } + + // Filter based Hooks + template HOOK_ID RegisterGameHookForFilter(typename H::filter f, typename H::fn h) { + if (this->nextHookId == 0 || this->nextHookId >= UINT32_MAX) this->nextHookId = 1; + while (RegisteredGameHooks::functionsForFilter.find(this->nextHookId) != RegisteredGameHooks::functionsForFilter.end()) { + this->nextHookId++; + } + + RegisteredGameHooks::functionsForFilter[this->nextHookId] = std::make_pair(f, h); + return this->nextHookId++; + } + template void UnregisterGameHookForFilter(HOOK_ID hookId) { + if (hookId == 0) return; + HooksToUnregister::hooksForFilter.push_back(hookId); + } + template void ExecuteHooksForFilter(Args&&... args) { + for (auto& hookId : HooksToUnregister::hooksForFilter) { + RegisteredGameHooks::functionsForFilter.erase(hookId); + } + HooksToUnregister::hooksForFilter.clear(); + for (auto& hook : RegisteredGameHooks::functionsForFilter) { + if (hook.second.first(std::forward(args)...)) { + hook.second.second(std::forward(args)...); + } + } + } + + class HookFilter { + public: + static auto ActorNotPlayer(Actor* actor) { + return actor->id != ACTOR_PLAYER; + } + // For use with Should hooks + static auto SActorNotPlayer(Actor* actor, bool* result) { + return actor->id != ACTOR_PLAYER; + } + static auto ActorMatchIdAndParams(int16_t id, int16_t params) { + return [id, params](Actor* actor) { + return actor->id == id && actor->params == params; + }; + } + // For use with Should hooks + static auto SActorMatchIdAndParams(int16_t id, int16_t params) { + return [id, params](Actor* actor, bool* result) { + return actor->id == id && actor->params == params; + }; + } + }; + + DEFINE_HOOK(OnLoadGame, (int32_t fileNum)); + DEFINE_HOOK(OnExitGame, (int32_t fileNum)); + DEFINE_HOOK(OnGameFrameUpdate, ()); + DEFINE_HOOK(OnItemReceive, (GetItemEntry itemEntry)); + DEFINE_HOOK(OnSaleEnd, (GetItemEntry itemEntry)); + DEFINE_HOOK(OnTransitionEnd, (int16_t sceneNum)); + DEFINE_HOOK(OnSceneInit, (int16_t sceneNum)); + DEFINE_HOOK(OnSceneFlagSet, (int16_t sceneNum, int16_t flagType, int16_t flag)); + DEFINE_HOOK(OnSceneFlagUnset, (int16_t sceneNum, int16_t flagType, int16_t flag)); + DEFINE_HOOK(OnFlagSet, (int16_t flagType, int16_t flag)); + DEFINE_HOOK(OnFlagUnset, (int16_t flagType, int16_t flag)); + DEFINE_HOOK(OnSceneSpawnActors, ()); + DEFINE_HOOK(OnPlayerUpdate, ()); + DEFINE_HOOK(OnOcarinaSongAction, ()); + DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price)); + DEFINE_HOOK(OnActorInit, (void* actor)); + DEFINE_HOOK(OnActorUpdate, (void* actor)); + DEFINE_HOOK(OnActorKill, (void* actor)); + DEFINE_HOOK(OnEnemyDefeat, (void* actor)); + DEFINE_HOOK(OnPlayerBonk, ()); + DEFINE_HOOK(OnPlayDestroy, ()); + DEFINE_HOOK(OnPlayDrawEnd, ()); + + DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, void* opt)); + + DEFINE_HOOK(OnSaveFile, (int32_t fileNum)); + DEFINE_HOOK(OnLoadFile, (int32_t fileNum)); + DEFINE_HOOK(OnDeleteFile, (int32_t fileNum)); + + DEFINE_HOOK(OnDialogMessage, ()); + DEFINE_HOOK(OnPresentTitleCard, ()); + DEFINE_HOOK(OnInterfaceUpdate, ()); + DEFINE_HOOK(OnKaleidoscopeUpdate, (int16_t inDungeonScene)); + + DEFINE_HOOK(OnPresentFileSelect, ()); + DEFINE_HOOK(OnUpdateFileSelectSelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileSelectConfirmationSelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileCopySelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileCopyConfirmationSelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileEraseSelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileEraseConfirmationSelection, (uint16_t optionIndex)); + DEFINE_HOOK(OnUpdateFileAudioSelection, (uint8_t optionIndex)); + DEFINE_HOOK(OnUpdateFileTargetSelection, (uint8_t optionIndex)); + DEFINE_HOOK(OnUpdateFileLanguageSelection, (uint8_t optionIndex)); + DEFINE_HOOK(OnUpdateFileQuestSelection, (uint8_t questIndex)); + DEFINE_HOOK(OnUpdateFileBossRushOptionSelection, (uint8_t optionIndex, uint8_t optionValue)); + DEFINE_HOOK(OnUpdateFileNameSelection, (int16_t charCode)); + + DEFINE_HOOK(OnSetGameLanguage, ()); + + DEFINE_HOOK(OnFileDropped, (std::string filePath)); + DEFINE_HOOK(OnAssetAltChange, ()); + DEFINE_HOOK(OnKaleidoUpdate, ()); // Helpers static bool IsSaveLoaded(bool allowDbgSave = false); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index b0c119798..93c8fc75e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -16,34 +16,44 @@ void GameInteractor_ExecuteOnGameFrameUpdate() { void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry) { GameInteractor::Instance->ExecuteHooks(itemEntry); + GameInteractor::Instance->ExecuteHooksForFilter(itemEntry); } void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry) { GameInteractor::Instance->ExecuteHooks(itemEntry); + GameInteractor::Instance->ExecuteHooksForFilter(itemEntry); } void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum) { GameInteractor::Instance->ExecuteHooks(sceneNum); + GameInteractor::Instance->ExecuteHooksForID(sceneNum, sceneNum); + GameInteractor::Instance->ExecuteHooksForFilter(sceneNum); } void GameInteractor_ExecuteOnSceneInitHooks(int16_t sceneNum) { GameInteractor::Instance->ExecuteHooks(sceneNum); + GameInteractor::Instance->ExecuteHooksForID(sceneNum, sceneNum); + GameInteractor::Instance->ExecuteHooksForFilter(sceneNum); } void GameInteractor_ExecuteOnSceneFlagSet(int16_t sceneNum, int16_t flagType, int16_t flag) { GameInteractor::Instance->ExecuteHooks(sceneNum, flagType, flag); + GameInteractor::Instance->ExecuteHooksForFilter(sceneNum, flagType, flag); } void GameInteractor_ExecuteOnSceneFlagUnset(int16_t sceneNum, int16_t flagType, int16_t flag) { GameInteractor::Instance->ExecuteHooks(sceneNum, flagType, flag); + GameInteractor::Instance->ExecuteHooksForFilter(sceneNum, flagType, flag); } void GameInteractor_ExecuteOnFlagSet(int16_t flagType, int16_t flag) { GameInteractor::Instance->ExecuteHooks(flagType, flag); + GameInteractor::Instance->ExecuteHooksForFilter(flagType, flag); } void GameInteractor_ExecuteOnFlagUnset(int16_t flagType, int16_t flag) { GameInteractor::Instance->ExecuteHooks(flagType, flag); + GameInteractor::Instance->ExecuteHooksForFilter(flagType, flag); } void GameInteractor_ExecuteOnSceneSpawnActors() { @@ -64,18 +74,30 @@ void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t pr void GameInteractor_ExecuteOnActorInit(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor); + GameInteractor::Instance->ExecuteHooksForFilter(actor); } void GameInteractor_ExecuteOnActorUpdate(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor); + GameInteractor::Instance->ExecuteHooksForFilter(actor); } void GameInteractor_ExecuteOnActorKill(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor); + GameInteractor::Instance->ExecuteHooksForFilter(actor); } void GameInteractor_ExecuteOnEnemyDefeat(void* actor) { GameInteractor::Instance->ExecuteHooks(actor); + GameInteractor::Instance->ExecuteHooksForID(((Actor*)actor)->id, actor); + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)actor, actor); + GameInteractor::Instance->ExecuteHooksForFilter(actor); } void GameInteractor_ExecuteOnPlayerBonk() { @@ -92,6 +114,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() { bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) { GameInteractor::Instance->ExecuteHooks(flag, &result, opt); + GameInteractor::Instance->ExecuteHooksForID(flag, flag, &result, opt); + if (opt != nullptr) { + GameInteractor::Instance->ExecuteHooksForPtr((uintptr_t)opt, flag, &result, opt); + } + GameInteractor::Instance->ExecuteHooksForFilter(flag, &result, opt); return result; } From 69eebf09842f58b89c8da288dd329eeb58c6366b Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 5 May 2024 22:27:33 -0700 Subject: [PATCH 219/300] CVar cleanup. --- soh/soh/Enhancements/cheat_hook_handlers.cpp | 8 +- soh/soh/Enhancements/mods.cpp | 2 +- soh/soh/Enhancements/presets.h | 40 +- .../randomizer/3drando/spoiler_log.cpp | 3 +- soh/soh/Enhancements/randomizer/draw.cpp | 26 +- .../Enhancements/randomizer/fishsanity.cpp | 6 +- .../Enhancements/randomizer/hook_handlers.cpp | 10 +- .../Enhancements/randomizer/randomizer.cpp | 2 +- .../randomizer/randomizer_item_tracker.cpp | 26 +- soh/soh/Enhancements/randomizer/settings.cpp | 382 +++++++++--------- .../Enhancements/timesaver_hook_handlers.cpp | 126 +++--- soh/soh/OTRGlobals.cpp | 2 +- soh/soh/SohMenuBar.cpp | 132 +++--- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 2 +- .../ovl_En_Syateki_Itm/z_en_syateki_itm.c | 2 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 2 +- .../overlays/actors/ovl_Fishing/z_fishing.c | 4 +- .../ovl_file_choose/z_file_choose.c | 8 +- 18 files changed, 392 insertions(+), 391 deletions(-) diff --git a/soh/soh/Enhancements/cheat_hook_handlers.cpp b/soh/soh/Enhancements/cheat_hook_handlers.cpp index c8565e8ab..a5a1a0d5a 100644 --- a/soh/soh/Enhancements/cheat_hook_handlers.cpp +++ b/soh/soh/Enhancements/cheat_hook_handlers.cpp @@ -15,13 +15,13 @@ extern PlayState* gPlayState; void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { case VB_DEKU_STICK_BREAK: { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + if (CVarGetInteger(CVAR_CHEAT("DekuStickCheat"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } break; } case VB_DEKU_STICK_BE_ON_FIRE: { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { + if (CVarGetInteger(CVAR_CHEAT("DekuStickCheat"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { Player* player = GET_PLAYER(gPlayState); player->unk_860 = 200; // Keeps the stick's flame lit player->unk_85C = 1.0f; // Ensures the stick is the proper length @@ -30,13 +30,13 @@ void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* op break; } case VB_DEKU_STICK_BURN_OUT: { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + if (CVarGetInteger(CVAR_CHEAT("DekuStickCheat"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } break; } case VB_DEKU_STICK_BURN_DOWN: { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + if (CVarGetInteger(CVAR_CHEAT("DekuStickCheat"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { *should = false; } break; diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index b08a7ef6d..f12b12174 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1695,7 +1695,7 @@ extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void PatchCompasses() { s8 compassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); - s8 isColoredCompassesEnabled = compassesCanBeOutsideDungeon && CVarGetInteger("gRandoEnhancement.MatchCompassColors", 1); + s8 isColoredCompassesEnabled = compassesCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchCompassColors"), 1); if (isColoredCompassesEnabled) { ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_PrimColor", 5, gsDPNoOp()); ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_EnvColor", 6, gsDPNoOp()); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index efe70a7f2..1f2888809 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -278,20 +278,20 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("PermanentHeartLoss"), CVAR_ENHANCEMENT("RemoveExplosiveLimit"), CVAR_ENHANCEMENT("ToggleStrength"), - "gTimeSavers.SkipCutscene.Intro", - "gTimeSavers.SkipCutscene.Entrances", - "gTimeSavers.SkipCutscene.Story", - "gTimeSavers.SkipCutscene.LearnSong", - "gTimeSavers.SkipCutscene.BossIntro", - "gTimeSavers.SkipCutscene.GlitchAiding", - "gTimeSavers.SkipCutscene.OnePoint", - "gTimeSavers.NoForcedDialog", - "gTimeSavers.SkipOwlInteractions", - "gTimeSavers.SkipMiscInteractions", - "gTimeSavers.DisableTitleCard", - "gTimeSavers.SkipGetItemAnimation", - "gTimeSavers.SkipChildStealth", - "gTimeSavers.SkipTowerEscape", + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), + CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), + CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), + CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), + CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), + CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), + CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), + CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), + CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), }; const std::vector cheatCvars = { @@ -391,10 +391,10 @@ const std::vector randomizerCvars = { CVAR_RANDOMIZER_SETTING("ExcludedLocations"), CVAR_RANDOMIZER_SETTING("Forest"), CVAR_RANDOMIZER_SETTING("FullWallets"), - "gRandomizeFishingPoleHint", - "gRandomizeFishsanity", - "gRandomizeFishsanityPondCount", - "gRandomizeFishsanityAgeSplit", + CVAR_RANDOMIZER_SETTING("FishingPoleHint"), + CVAR_RANDOMIZER_SETTING("Fishsanity"), + CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), + CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), CVAR_RANDOMIZER_SETTING("GanonTrial"), CVAR_RANDOMIZER_SETTING("GanonTrialCount"), CVAR_RANDOMIZER_SETTING("GerudoFortress"), @@ -413,7 +413,7 @@ const std::vector randomizerCvars = { CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), CVAR_RANDOMIZER_SETTING("LacsStoneCount"), CVAR_RANDOMIZER_SETTING("LacsTokenCount"), - "gRandomizeGanondorfHint", + CVAR_RANDOMIZER_SETTING("GanondorfHint"), CVAR_RANDOMIZER_SETTING("LAHint"), CVAR_RANDOMIZER_SETTING("LinksPocket"), CVAR_RANDOMIZER_SETTING("LogicRules"), @@ -437,7 +437,7 @@ const std::vector randomizerCvars = { CVAR_RANDOMIZER_SETTING("ShuffleCows"), CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), - "gRandomizeShuffleFishingPole", + CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 303d30574..c40031e74 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "consolevariablebridge.h" @@ -659,7 +660,7 @@ const char* SpoilerLog_Write() { jsonFile << std::setw(4) << jsonString << std::endl; jsonFile.close(); - CVarSetString("gSpoilerLog", (std::string("./Randomizer/") + fileName + std::string(".json")).c_str()); + CVarSetString(CVAR_GENERAL("SpoilerLog"), (std::string("./Randomizer/") + fileName + std::string(".json")).c_str()); // Note: probably shouldn't return this without making sure this string is stored somewhere, but // this return value is currently only used in playthrough.cpp as a true/false. Even if the pointer diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index b386b0226..338bfdb33 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -377,31 +377,31 @@ extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEn extern "C" void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry) { Color_RGB8 aButtonColor = { 80, 150, 255 }; - if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { - aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); - } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { + aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); + } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { aButtonColor = { 80, 255, 150 }; } Color_RGB8 cButtonsColor = { 255, 255, 50 }; - if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) { - cButtonsColor = CVarGetColor24("gCosmetics.Hud_CButtons.Value", cButtonsColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CButtons.Changed"), 0)) { + cButtonsColor = CVarGetColor24(CVAR_COSMETIC("HUD.CButtons.Value"), cButtonsColor); } Color_RGB8 cUpButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) { - cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CUpButton.Changed"), 0)) { + cUpButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CUpButton.Value"), cUpButtonColor); } Color_RGB8 cDownButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) { - cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CDownButton.Changed"), 0)) { + cDownButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CDownButton.Value"), cDownButtonColor); } Color_RGB8 cLeftButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) { - cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CLeftButton.Changed"), 0)) { + cLeftButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CLeftButton.Value"), cLeftButtonColor); } Color_RGB8 cRightButtonColor = cButtonsColor; - if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) { - cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor); + if (CVarGetInteger(CVAR_COSMETIC("HUD.CRightButton.Changed"), 0)) { + cRightButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.CRightButton.Value"), cRightButtonColor); } s16 slot = getItemEntry->drawItemId - RG_OCARINA_A_BUTTON; diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp index 48ca2d703..52789f17e 100644 --- a/soh/soh/Enhancements/randomizer/fishsanity.cpp +++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp @@ -167,9 +167,9 @@ namespace Rando { switch (optionsSource) { // Used in check tracker case FSO_SOURCE_CVARS: - options.mode = CVarGetInteger("gRandomizeFishsanity", RO_FISHSANITY_OFF); - options.numFish = CVarGetInteger("gRandomizeFishsanityPondCount", 0); - options.ageSplit = CVarGetInteger("gRandomizeFishsanityAgeSplit", 0) == 1; + options.mode = CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_OFF); + options.numFish = CVarGetInteger(CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), 0); + options.ageSplit = CVarGetInteger(CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), 0) == 1; break; case FSO_SOURCE_RANDO: default: diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 8360ece10..257666a61 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -250,9 +250,9 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { // Always show ItemGet animation for ice traps !(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) && ( - CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_ALL || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_ALL || ( - CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_JUNK && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) == SGIA_JUNK && ( getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || @@ -311,7 +311,7 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { } } - if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { static uint32_t updateHook; updateHook = GameInteractor::Instance->RegisterGameHook([]() { Player* player = GET_PLAYER(gPlayState); @@ -355,7 +355,7 @@ void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) { } void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) { - f32 mtxScale = CVarGetFloat("gTimeSavers.SkipGetItemAnimationScale", 10.0f); + f32 mtxScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 10.0f); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); EnItem00_CustomItemsParticles(&enItem00->actor, play, enItem00->itemEntry); GetItemEntry_Draw(play, enItem00->itemEntry); @@ -1205,7 +1205,7 @@ void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) { } else if (Rand_ZeroOne() < 0.5f) { params = -1; } - if (params >= 0 && !CVarGetInteger("gNoRandomDrops", 0)) { + if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) { Item_DropCollectible(play, &objComb->actor.world.pos, params); } } diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index a35762354..77f1e7888 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1819,7 +1819,7 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (ImGui::BeginTabItem("Items")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - ImGui::BeginDisabled(CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); + ImGui::BeginDisabled(CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA); if (mSettings->GetOptionGroup(RSG_ITEMS_IMGUI_TABLE).RenderImGui()) { mNeedsUpdate = true; } diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 940b62079..6371708d6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -1127,15 +1127,15 @@ void UpdateVectors() { } // if misc is separate and fishing pole isn't added, add fishing pole to misc - if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && - CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW && + CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Misc"), SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) { if (std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item) { return item.id == ITEM_FISHING_POLE; })) miscItems.insert(miscItems.end(), fishingPoleItems.begin(), fishingPoleItems.end()); } else { miscItems.erase(std::remove_if(miscItems.begin(), miscItems.end(), [](ItemTrackerItem i) { return i.id == ITEM_FISHING_POLE; }), miscItems.end()); } // add fishing pole to main window - if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) { if (!newRowAdded) { while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); @@ -1147,7 +1147,7 @@ void UpdateVectors() { } //If we're adding boss souls to the main window... - if (CVarGetInteger("gItemTrackerBossSoulsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { //...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce pieces) while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); @@ -1158,7 +1158,7 @@ void UpdateVectors() { } //If we're adding ocarina buttons to the main window... - if (CVarGetInteger("gItemTrackerOcarinaButtonsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { //...add empty items on the main window to get the buttons on their own row. (Too many to sit with Greg/Triforce pieces/boss souls) while (mainWindowItems.size() % 6) { mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); @@ -1212,7 +1212,7 @@ void ItemTrackerWindow::DrawElement() { (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Greg"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) || - (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || + (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) || (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) ) { BeginFloatingWindows("Item Tracker##main window"); @@ -1289,19 +1289,19 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerBossSoulsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Boss Soul Tracker"); DrawItemsInRows(bossSoulItems); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerOcarinaButtonsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { BeginFloatingWindows("Ocarina Button Tracker"); DrawItemsInRows(ocarinaButtonItems); EndFloatingWindows(); } - if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { BeginFloatingWindows("Fishing Pole Tracker"); DrawItemsInRows(fishingPoleItems); EndFloatingWindows(); @@ -1443,19 +1443,19 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", "gItemTrackerTriforcePiecesDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Boss Souls", "gItemTrackerBossSoulsDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Boss Souls", CVAR_TRACKER_ITEM("DisplayType.BossSouls"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Ocarina Buttons", "gItemTrackerOcarinaButtonsDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; } - if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Fishing Pole", "gItemTrackerFishingPoleDisplayType", extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Fishing Pole", CVAR_TRACKER_ITEM("DisplayType.FishingPole"), extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_HIDDEN)) { shouldUpdateVectors = true; } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 76cda498a..11a42aefb 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -42,171 +42,171 @@ Settings::Settings() : mExcludeLocationsOptionsGroups(SPOILER_COLLECTION_GROUP_C void Settings::CreateOptions() { CreateOptionDescriptions(); // clang-format off - mOptions[RSK_FOREST] = Option::U8("Forest", {"Closed", "Closed Deku", "Open"}, OptionCategory::Setting, "gRandomizeForest", mOptionDescriptions[RSK_FOREST], WidgetType::Combobox, RO_FOREST_CLOSED); - mOptions[RSK_KAK_GATE] = Option::U8("Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, "gRandomizeKakarikoGate", mOptionDescriptions[RSK_KAK_GATE]); - mOptions[RSK_DOOR_OF_TIME] = Option::U8("Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, "gRandomizeDoorOfTime", mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); - mOptions[RSK_ZORAS_FOUNTAIN] = Option::U8("Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, "gRandomizeZorasFountain", mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); - mOptions[RSK_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress", {"Normal", "Fast", "Open"}, OptionCategory::Setting, "gRandomizeGerudoFortress", mOptionDescriptions[RSK_GERUDO_FORTRESS]); - mOptions[RSK_RAINBOW_BRIDGE] = Option::U8("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, "gRandomizeRainbowBridge", mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, "gRandomizeStoneCount", "", WidgetType::Slider, 3, true); - mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = Option::U8("Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, "gRandomizeMedallionCount", "", WidgetType::Slider, 6, true); - mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = Option::U8("Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, "gRandomizeRewardCount", "", WidgetType::Slider, 9, true); - mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = Option::U8("Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, "gRandomizeDungeonCount", "", WidgetType::Slider, 8, true); - mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = Option::U8("Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, "gRandomizeTokenCount", "", WidgetType::Slider, 100, true); - mOptions[RSK_BRIDGE_OPTIONS] = Option::U8("Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, "gRandomizeBridgeRewardOptions", mOptionDescriptions[RSK_BRIDGE_OPTIONS], WidgetType::Combobox, RO_BRIDGE_STANDARD_REWARD, false, IMFLAG_NONE); - mOptions[RSK_GANONS_TRIALS] = Option::U8("Ganon's Trials", {"Skip", "Set Number", "Random Number"}, OptionCategory::Setting, "gRandomizeGanonTrial", mOptionDescriptions[RSK_GANONS_TRIALS], WidgetType::Combobox, RO_GANONS_TRIALS_SET_NUMBER); - mOptions[RSK_TRIAL_COUNT] = Option::U8("Ganon's Trials Count", {NumOpts(0, 6)}, OptionCategory::Setting, "gRandomizeGanonTrialCount", mOptionDescriptions[RSK_TRIAL_COUNT], WidgetType::Slider, 6, true); - mOptions[RSK_STARTING_AGE] = Option::U8("Starting Age", {"Child", "Adult", "Random"}, OptionCategory::Setting, "gRandomizeStartingAge", mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD); + mOptions[RSK_FOREST] = Option::U8("Forest", {"Closed", "Closed Deku", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Forest"), mOptionDescriptions[RSK_FOREST], WidgetType::Combobox, RO_FOREST_CLOSED); + mOptions[RSK_KAK_GATE] = Option::U8("Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("KakarikoGate"), mOptionDescriptions[RSK_KAK_GATE]); + mOptions[RSK_DOOR_OF_TIME] = Option::U8("Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); + mOptions[RSK_ZORAS_FOUNTAIN] = Option::U8("Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); + mOptions[RSK_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress", {"Normal", "Fast", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoFortress"), mOptionDescriptions[RSK_GERUDO_FORTRESS]); + mOptions[RSK_RAINBOW_BRIDGE] = Option::U8("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true); + mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = Option::U8("Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WidgetType::Slider, 6, true); + mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = Option::U8("Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WidgetType::Slider, 9, true); + mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = Option::U8("Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WidgetType::Slider, 8, true); + mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = Option::U8("Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WidgetType::Slider, 100, true); + mOptions[RSK_BRIDGE_OPTIONS] = Option::U8("Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), mOptionDescriptions[RSK_BRIDGE_OPTIONS], WidgetType::Combobox, RO_BRIDGE_STANDARD_REWARD, false, IMFLAG_NONE); + mOptions[RSK_GANONS_TRIALS] = Option::U8("Ganon's Trials", {"Skip", "Set Number", "Random Number"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrial"), mOptionDescriptions[RSK_GANONS_TRIALS], WidgetType::Combobox, RO_GANONS_TRIALS_SET_NUMBER); + mOptions[RSK_TRIAL_COUNT] = Option::U8("Ganon's Trials Count", {NumOpts(0, 6)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrialCount"), mOptionDescriptions[RSK_TRIAL_COUNT], WidgetType::Slider, 6, true); + mOptions[RSK_STARTING_AGE] = Option::U8("Starting Age", {"Child", "Adult", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD); mOptions[RSK_SHUFFLE_ENTRANCES] = Option::Bool("Shuffle Entrances"); - mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES] = Option::U8("Dungeon Entrances", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, "gRandomizeShuffleDungeonsEntrances", mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], WidgetType::Combobox, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); - mOptions[RSK_SHUFFLE_BOSS_ENTRANCES] = Option::U8("Boss Entrances", {"Off", "Age Restricted", "Full"}, OptionCategory::Setting, "gRandomizeShuffleBossEntrances", mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES], WidgetType::Combobox, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); - mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = Option::Bool("Overworld Entrances", "gRandomizeShuffleOverworldEntrances", mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES]); - mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES] = Option::U8("Interior Entrances", {"Off", "Simple", "All"}, OptionCategory::Setting, "gRandomizeShuffleInteriorsEntrances", mOptionDescriptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], WidgetType::Combobox, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); - mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] = Option::Bool("Grottos Entrances", "gRandomizeShuffleGrottosEntrances", mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]); - mOptions[RSK_SHUFFLE_OWL_DROPS] = Option::Bool("Owl Drops", "gRandomizeShuffleOwlDrops", mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]); - mOptions[RSK_SHUFFLE_WARP_SONGS] = Option::Bool("Warp Songs", "gRandomizeShuffleWarpSongs", mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]); - mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", "gRandomizeShuffleOverworldSpanws", mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]); - mOptions[RSK_MIXED_ENTRANCE_POOLS] = Option::Bool("Mixed Entrance Pools", "gRandomizeMixedEntrances", mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]); - mOptions[RSK_MIX_DUNGEON_ENTRANCES] = Option::Bool("Mix Dungeons", "gRandomizeMixDungeons", mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE); - mOptions[RSK_MIX_BOSS_ENTRANCES] = Option::Bool("Mix Bosses", "gRandomizeMixBosses", mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE); - mOptions[RSK_MIX_OVERWORLD_ENTRANCES] = Option::Bool("Mix Overworld", "gRandomizeMixOverworld", mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE); - mOptions[RSK_MIX_INTERIOR_ENTRANCES] = Option::Bool("Mix Interiors", "gRandomizeMixInteriors", mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE); - mOptions[RSK_MIX_GROTTO_ENTRANCES] = Option::Bool("Mix Grottos", "gRandomizeMixGrottos", mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]); - mOptions[RSK_DECOUPLED_ENTRANCES] = Option::Bool("Decouple Entrances", "gRandomizeDecoupleEntrances", mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]); - mOptions[RSK_BOMBCHUS_IN_LOGIC] = Option::Bool("Bombchus in Logic", "gRandomizeBombchusInLogic", mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC]); - mOptions[RSK_ENABLE_BOMBCHU_DROPS] = Option::U8("Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, "gRandomizeEnableBombchuDrops", mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON); + mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES] = Option::U8("Dungeon Entrances", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], WidgetType::Combobox, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + mOptions[RSK_SHUFFLE_BOSS_ENTRANCES] = Option::U8("Boss Entrances", {"Off", "Age Restricted", "Full"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES], WidgetType::Combobox, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = Option::Bool("Overworld Entrances", CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES]); + mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES] = Option::U8("Interior Entrances", {"Off", "Simple", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), mOptionDescriptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], WidgetType::Combobox, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] = Option::Bool("Grottos Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]); + mOptions[RSK_SHUFFLE_OWL_DROPS] = Option::Bool("Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]); + mOptions[RSK_SHUFFLE_WARP_SONGS] = Option::Bool("Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]); + mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpanws"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]); + mOptions[RSK_MIXED_ENTRANCE_POOLS] = Option::Bool("Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances"), mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]); + mOptions[RSK_MIX_DUNGEON_ENTRANCES] = Option::Bool("Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons"), mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE); + mOptions[RSK_MIX_BOSS_ENTRANCES] = Option::Bool("Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses"), mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE); + mOptions[RSK_MIX_OVERWORLD_ENTRANCES] = Option::Bool("Mix Overworld", CVAR_RANDOMIZER_SETTING("MixOverworld"), mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE); + mOptions[RSK_MIX_INTERIOR_ENTRANCES] = Option::Bool("Mix Interiors", CVAR_RANDOMIZER_SETTING("MixInteriors"), mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE); + mOptions[RSK_MIX_GROTTO_ENTRANCES] = Option::Bool("Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos"), mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]); + mOptions[RSK_DECOUPLED_ENTRANCES] = Option::Bool("Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]); + mOptions[RSK_BOMBCHUS_IN_LOGIC] = Option::Bool("Bombchus in Logic", CVAR_RANDOMIZER_SETTING("BombchusInLogic"), mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC]); + mOptions[RSK_ENABLE_BOMBCHU_DROPS] = Option::U8("Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON); // TODO: AmmoDrops and/or HeartDropRefill, combine with/separate Ammo Drops from Bombchu Drops? - mOptions[RSK_TRIFORCE_HUNT] = Option::Bool("Triforce Hunt", "gRandomizeTriforceHunt", mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE); - mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = Option::U8("Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, "gRandomizeTriforceHuntTotalPieces", mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE); - mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = Option::U8("Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, "gRandomizeTriforceHuntRequiredPieces", mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19); - mOptions[RSK_MQ_DUNGEON_RANDOM] = Option::U8("MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, "gRandomizeMqDungeons", mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WidgetType::Combobox, RO_MQ_DUNGEONS_NONE, true, IMFLAG_NONE); - mOptions[RSK_MQ_DUNGEON_COUNT] = Option::U8("MQ Dungeon Count", {NumOpts(0, 12)}, OptionCategory::Setting, "gRandomizeMqDungeonCount", "", WidgetType::Slider, 12, true, IMFLAG_NONE); - mOptions[RSK_MQ_DUNGEON_SET] = Option::Bool("Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, "gRandomizeMqDungeonsSelection", mOptionDescriptions[RSK_MQ_DUNGEON_SET], WidgetType::Checkbox, false, false, IMFLAG_NONE); - mOptions[RSK_MQ_DEKU_TREE] = Option::U8("Deku Tree", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsDekuTree", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_DODONGOS_CAVERN] = Option::U8("Dodongo's Cavern", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsDodongosCavern", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_JABU_JABU] = Option::U8("Jabu-Jabu's Belly", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsJabuJabu", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_FOREST_TEMPLE] = Option::U8("Forest Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsForestTemple", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_FIRE_TEMPLE] = Option::U8("Fire Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsFireTemple", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_WATER_TEMPLE] = Option::U8("Water Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsWaterTemple", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_SPIRIT_TEMPLE] = Option::U8("Spirit Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsSpiritTemple", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_SHADOW_TEMPLE] = Option::U8("Shadow Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsShadowTemple", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsBottomOfTheWell", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_ICE_CAVERN] = Option::U8("Ice Cavern", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsIceCavern", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_GTG] = Option::U8("Gerudo Training Grounds", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsGTG", "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); - mOptions[RSK_MQ_GANONS_CASTLE] = Option::U8("Ganon's Castle", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, "gRandomizeMqDungeonsGanonsCastle", "", WidgetType::Combobox, RO_MQ_SET_VANILLA); - mOptions[RSK_SHUFFLE_DUNGEON_REWARDS] = Option::U8("Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeShuffleDungeonReward", mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON); - mOptions[RSK_LINKS_POCKET] = Option::U8("Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, "gRandomizeLinksPocket", "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD); - mOptions[RSK_SHUFFLE_SONGS] = Option::U8("Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, "gRandomizeShuffleSongs", mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS); - mOptions[RSK_SHOPSANITY] = Option::U8("Shopsanity", {"Off", "0 Items", "1 Item", "2 Items", "3 Items", "4 Items", "Random"}, OptionCategory::Setting, "gRandomizeShopsanity", mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF); - mOptions[RSK_SHOPSANITY_PRICES] = Option::U8("Shopsanity Prices", {"Balanced", "Starting Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet"}, OptionCategory::Setting, "gRandomizeShopsanityPrices", mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_SHOPSANITY_PRICE_BALANCED, false, IMFLAG_NONE); - mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = Option::Bool("Affordable Prices", "gRandomizeShopsanityPricesAffordable", mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]); - mOptions[RSK_SHUFFLE_TOKENS] = Option::U8("Tokensanity", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, "gRandomizeShuffleTokens", mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF); - mOptions[RSK_SHUFFLE_SCRUBS] = Option::U8("Scrub Shuffle", {"Off", "Affordable", "Expensive", "Random Prices"}, OptionCategory::Setting, "gRandomizeShuffleScrubs", mOptionDescriptions[RSK_SHUFFLE_SCRUBS], WidgetType::Combobox, RO_SCRUBS_OFF); - mOptions[RSK_SHUFFLE_BEEHIVES] = Option::Bool("Shuffle Beehives", "gRandomizeShuffleBeehives", mOptionDescriptions[RSK_SHUFFLE_BEEHIVES]); - mOptions[RSK_SHUFFLE_COWS] = Option::Bool("Shuffle Cows", "gRandomizeShuffleCows", mOptionDescriptions[RSK_SHUFFLE_COWS]); - mOptions[RSK_SHUFFLE_KOKIRI_SWORD] = Option::Bool("Shuffle Kokiri Sword", "gRandomizeShuffleKokiriSword", mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]); - mOptions[RSK_SHUFFLE_MASTER_SWORD] = Option::Bool("Shuffle Master Sword", "gRandomizeShuffleMasterSword", mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]); - mOptions[RSK_SHUFFLE_CHILD_WALLET] = Option::Bool("Shuffle Child's Wallet", "gRandomizeShuffleChildWallet", mOptionDescriptions[RSK_SHUFFLE_CHILD_WALLET]); - mOptions[RSK_SHUFFLE_OCARINA] = Option::Bool("Shuffle Ocarinas", "gRandomizeShuffleOcarinas", mOptionDescriptions[RSK_SHUFFLE_OCARINA]); - mOptions[RSK_SHUFFLE_OCARINA_BUTTONS] = Option::Bool("Shuffle Ocarina Buttons", "gRandomizeShuffleOcarinaButtons", mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); - mOptions[RSK_SHUFFLE_SWIM] = Option::Bool("Shuffle Swim", "gRandomizeShuffleSwim", mOptionDescriptions[RSK_SHUFFLE_SWIM]); - mOptions[RSK_SHUFFLE_WEIRD_EGG] = Option::Bool("Shuffle Weird Egg", "gRandomizeShuffleWeirdEgg", mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); - mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = Option::Bool("Shuffle Gerudo Membership Card", "gRandomizeShuffleGerudoToken", mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); - mOptions[RSK_SHUFFLE_FISHING_POLE] = Option::Bool("Shuffle Fishing Pole", "gRandomizeShuffleFishingPole", mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); - mOptions[RSK_SHUFFLE_MAGIC_BEANS] = Option::Bool("Shuffle Magic Beans", "gRandomizeShuffleBeans", mOptionDescriptions[RSK_SHUFFLE_MAGIC_BEANS]); - mOptions[RSK_SHUFFLE_MERCHANTS] = Option::U8("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, OptionCategory::Setting, "gRandomizeShuffleMerchants", mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF); - mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES] = Option::Bool("Shuffle Frog Song Rupees", "gRandomizeShuffleFrogSongRupees", mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]); - mOptions[RSK_SHUFFLE_ADULT_TRADE] = Option::Bool("Shuffle Adult Trade", "gRandomizeShuffleAdultTrade", mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]); + mOptions[RSK_TRIFORCE_HUNT] = Option::Bool("Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE); + mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = Option::U8("Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE); + mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = Option::U8("Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19); + mOptions[RSK_MQ_DUNGEON_RANDOM] = Option::U8("MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeons"), mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WidgetType::Combobox, RO_MQ_DUNGEONS_NONE, true, IMFLAG_NONE); + mOptions[RSK_MQ_DUNGEON_COUNT] = Option::U8("MQ Dungeon Count", {NumOpts(0, 12)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonCount"), "", WidgetType::Slider, 12, true, IMFLAG_NONE); + mOptions[RSK_MQ_DUNGEON_SET] = Option::Bool("Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), mOptionDescriptions[RSK_MQ_DUNGEON_SET], WidgetType::Checkbox, false, false, IMFLAG_NONE); + mOptions[RSK_MQ_DEKU_TREE] = Option::U8("Deku Tree", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_DODONGOS_CAVERN] = Option::U8("Dodongo's Cavern", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_JABU_JABU] = Option::U8("Jabu-Jabu's Belly", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_FOREST_TEMPLE] = Option::U8("Forest Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_FIRE_TEMPLE] = Option::U8("Fire Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_WATER_TEMPLE] = Option::U8("Water Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_SPIRIT_TEMPLE] = Option::U8("Spirit Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_SHADOW_TEMPLE] = Option::U8("Shadow Temple", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_ICE_CAVERN] = Option::U8("Ice Cavern", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_GTG] = Option::U8("Gerudo Training Grounds", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); + mOptions[RSK_MQ_GANONS_CASTLE] = Option::U8("Ganon's Castle", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA); + mOptions[RSK_SHUFFLE_DUNGEON_REWARDS] = Option::U8("Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON); + mOptions[RSK_LINKS_POCKET] = Option::U8("Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD); + mOptions[RSK_SHUFFLE_SONGS] = Option::U8("Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS); + mOptions[RSK_SHOPSANITY] = Option::U8("Shopsanity", {"Off", "0 Items", "1 Item", "2 Items", "3 Items", "4 Items", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF); + mOptions[RSK_SHOPSANITY_PRICES] = Option::U8("Shopsanity Prices", {"Balanced", "Starting Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_SHOPSANITY_PRICE_BALANCED, false, IMFLAG_NONE); + mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = Option::Bool("Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]); + mOptions[RSK_SHUFFLE_TOKENS] = Option::U8("Tokensanity", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF); + mOptions[RSK_SHUFFLE_SCRUBS] = Option::U8("Scrub Shuffle", {"Off", "Affordable", "Expensive", "Random Prices"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), mOptionDescriptions[RSK_SHUFFLE_SCRUBS], WidgetType::Combobox, RO_SCRUBS_OFF); + mOptions[RSK_SHUFFLE_BEEHIVES] = Option::Bool("Shuffle Beehives", CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), mOptionDescriptions[RSK_SHUFFLE_BEEHIVES]); + mOptions[RSK_SHUFFLE_COWS] = Option::Bool("Shuffle Cows", CVAR_RANDOMIZER_SETTING("ShuffleCows"), mOptionDescriptions[RSK_SHUFFLE_COWS]); + mOptions[RSK_SHUFFLE_KOKIRI_SWORD] = Option::Bool("Shuffle Kokiri Sword", CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]); + mOptions[RSK_SHUFFLE_MASTER_SWORD] = Option::Bool("Shuffle Master Sword", CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]); + mOptions[RSK_SHUFFLE_CHILD_WALLET] = Option::Bool("Shuffle Child's Wallet", CVAR_RANDOMIZER_SETTING("ShuffleChildWallet"), mOptionDescriptions[RSK_SHUFFLE_CHILD_WALLET]); + mOptions[RSK_SHUFFLE_OCARINA] = Option::Bool("Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]); + mOptions[RSK_SHUFFLE_OCARINA_BUTTONS] = Option::Bool("Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); + mOptions[RSK_SHUFFLE_SWIM] = Option::Bool("Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); + mOptions[RSK_SHUFFLE_WEIRD_EGG] = Option::Bool("Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); + mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = Option::Bool("Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); + mOptions[RSK_SHUFFLE_FISHING_POLE] = Option::Bool("Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); + mOptions[RSK_SHUFFLE_MAGIC_BEANS] = Option::Bool("Shuffle Magic Beans", CVAR_RANDOMIZER_SETTING("ShuffleBeans"), mOptionDescriptions[RSK_SHUFFLE_MAGIC_BEANS]); + mOptions[RSK_SHUFFLE_MERCHANTS] = Option::U8("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF); + mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES] = Option::Bool("Shuffle Frog Song Rupees", CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]); + mOptions[RSK_SHUFFLE_ADULT_TRADE] = Option::Bool("Shuffle Adult Trade", CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]); mOptions[RSK_SHUFFLE_CHEST_MINIGAME] = Option::U8("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}); - mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward", "gRandomizeShuffle100GSReward", mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); - mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, "gRandomizeShuffleBossSouls", mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox); - mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, "gRandomizeFishsanity", mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); - mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, "gRandomizeFishsanityPondCount", mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE); - mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", "gRandomizeFishsanityAgeSplit", mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]); - mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeStartingMapsCompasses", mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - mOptions[RSK_KEYSANITY] = Option::U8("Small Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeKeysanity", mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - mOptions[RSK_GERUDO_KEYS] = Option::U8("Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeGerudoKeys", mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA); - mOptions[RSK_BOSS_KEYSANITY] = Option::U8("Boss Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeBossKeysanity", mOptionDescriptions[RSK_BOSS_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); - mOptions[RSK_GANONS_BOSS_KEY] = Option::U8("Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "Triforce Hunt"}, OptionCategory::Setting, "gRandomizeShuffleGanonBossKey", mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA); - mOptions[RSK_LACS_STONE_COUNT] = Option::U8("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, "gRandomizeLacsStoneCount", "", WidgetType::Slider, 3, true); - mOptions[RSK_LACS_MEDALLION_COUNT] = Option::U8("Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, "gRandomizeLacsMedallionCount", "", WidgetType::Slider, 6, true); - mOptions[RSK_LACS_REWARD_COUNT] = Option::U8("Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, "gRandomizeLacsRewardCount", "", WidgetType::Slider, 9, true); - mOptions[RSK_LACS_DUNGEON_COUNT] = Option::U8("Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, "gRandomizeLacsDungeonCount", "", WidgetType::Slider, 8, true); - mOptions[RSK_LACS_TOKEN_COUNT] = Option::U8("Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, "gRandomizeLacsTokenCount", "", WidgetType::Slider, 100, true); - mOptions[RSK_LACS_OPTIONS] = Option::U8("LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, "gRandomizeLacsRewardOptions", "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD); - mOptions[RSK_KEYRINGS] = Option::U8("Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, "gRandomizeShuffleKeyRings", mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF); - mOptions[RSK_KEYRINGS_RANDOM_COUNT] = Option::U8("Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, "gRandomizeShuffleKeyRingsRandomCount", "", WidgetType::Slider, 8); - mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::Bool("Gerudo Fortress", "gRandomizeShuffleKeyRingsGerudoFortress", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::Bool("Forest Temple", "gRandomizeShuffleKeyRingsForestTemple", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::Bool("Fire Temple", "gRandomizeShuffleKeyRingsFireTemple", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::Bool("Water Temple", "gRandomizeShuffleKeyRingsWaterTemple", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::Bool("Spirit Temple", "gRandomizeShuffleKeyRingsSpiritTemple", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::Bool("Shadow Temple", "gRandomizeShuffleKeyRingsShadowTemple", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::Bool("Bottom of the Well", "gRandomizeShuffleKeyRingsBottomOfTheWell", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_GTG] = Option::Bool("Gerudo Training Grounds", "gRandomizeShuffleKeyRingsGTG", "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", "gRandomizeShuffleKeyRingsGanonsCastle"); - mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildStealth", mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); - mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildZelda", mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); - mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipEponaRace", mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); - mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", "gRandomizeSkipScarecrowsSong", mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); - mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, "gRandomizeBigPoeTargetCount", mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); - mOptions[RSK_CUCCO_COUNT] = Option::U8("Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, "gRandomizeCuccosToReturn", mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7); - mOptions[RSK_COMPLETE_MASK_QUEST] = Option::Bool("Complete Mask Quest", "gRandomizeCompleteMaskQuest", mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]); - mOptions[RSK_ENABLE_GLITCH_CUTSCENES] = Option::Bool("Enable Glitch-Useful Cutscenes", "gRandomizeEnableGlitchCutscenes", mOptionDescriptions[RSK_ENABLE_GLITCH_CUTSCENES]); - mOptions[RSK_GOSSIP_STONE_HINTS] = Option::U8("Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, "gRandomizeGossipStoneHints", mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE); - mOptions[RSK_HINT_CLARITY] = Option::U8("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, "gRandomizeHintClarity", mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT); - mOptions[RSK_HINT_DISTRIBUTION] = Option::U8("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, "gRandomizeHintDistribution", mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT); - mOptions[RSK_TOT_ALTAR_HINT] = Option::Bool("ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeAltarHint", mOptionDescriptions[RSK_TOT_ALTAR_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_INDENT); - mOptions[RSK_GANONDORF_HINT] = Option::Bool("Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeGanondorfHint", mOptionDescriptions[RSK_GANONDORF_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); - mOptions[RSK_SHEIK_LA_HINT] = Option::Bool("Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, "gRandomizeSheikLAHint", mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); - mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", "gRandomizeDampeHint", mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE); - mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", "gRandomizeGregHint", mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); - mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", "gRandomizeSariaHint", mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); - mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", "gRandomizeFishingPoleHint", mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE); - mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", "gRandomizeFrogsHint", mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); - mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", "gRandomizeBiggoronHint", mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE); - mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", "gRandomizeBigPoesHint", mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE); - mOptions[RSK_CHICKENS_HINT] = Option::Bool("Chickens Hint", "gRandomizeChickensHint", mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE); - mOptions[RSK_MALON_HINT] = Option::Bool("Malon Hint", "gRandomizeMalonHint", mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE); - mOptions[RSK_HBA_HINT] = Option::Bool("Horseback Archery Hint", "gRandomizeHBAHint", mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE); - mOptions[RSK_WARP_SONG_HINTS] = Option::Bool("Warp Song Hints", "gRandomizeWarpSongText", mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WidgetType::Checkbox, RO_GENERIC_ON); - mOptions[RSK_SCRUB_TEXT_HINT] = Option::Bool("Scrub Hint Text", "gRandomizeScrubText", mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_10_SKULLS_HINT] = Option::Bool("10 GS Hint", "gRandomize10GSHint", mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_20_SKULLS_HINT] = Option::Bool("20 GS Hint", "gRandomize20GSHint", mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", "gRandomize30GSHint", mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", "gRandomize40GSHint", mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", "gRandomize50GSHint", mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", "gRandomize100GSHint", mOptionDescriptions[RSK_KAK_100_SKULLS_HINT]); + mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox); + mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); + mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE); + mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]); + mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + mOptions[RSK_KEYSANITY] = Option::U8("Small Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + mOptions[RSK_GERUDO_KEYS] = Option::U8("Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA); + mOptions[RSK_BOSS_KEYSANITY] = Option::U8("Boss Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BossKeysanity"), mOptionDescriptions[RSK_BOSS_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + mOptions[RSK_GANONS_BOSS_KEY] = Option::U8("Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "Triforce Hunt"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA); + mOptions[RSK_LACS_STONE_COUNT] = Option::U8("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsStoneCount"), "", WidgetType::Slider, 3, true); + mOptions[RSK_LACS_MEDALLION_COUNT] = Option::U8("Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), "", WidgetType::Slider, 6, true); + mOptions[RSK_LACS_REWARD_COUNT] = Option::U8("Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true); + mOptions[RSK_LACS_DUNGEON_COUNT] = Option::U8("Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true); + mOptions[RSK_LACS_TOKEN_COUNT] = Option::U8("Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true); + mOptions[RSK_LACS_OPTIONS] = Option::U8("LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD); + mOptions[RSK_KEYRINGS] = Option::U8("Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF); + mOptions[RSK_KEYRINGS_RANDOM_COUNT] = Option::U8("Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8); + mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::Bool("Gerudo Fortress", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::Bool("Forest Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::Bool("Fire Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::Bool("Water Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::Bool("Spirit Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::Bool("Shadow Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::Bool("Bottom of the Well", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_GTG] = Option::Bool("Gerudo Training Grounds", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", IMFLAG_NONE); + mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle")); + mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); + mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); + mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); + mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); + mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); + mOptions[RSK_CUCCO_COUNT] = Option::U8("Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7); + mOptions[RSK_COMPLETE_MASK_QUEST] = Option::Bool("Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]); + mOptions[RSK_ENABLE_GLITCH_CUTSCENES] = Option::Bool("Enable Glitch-Useful Cutscenes", CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), mOptionDescriptions[RSK_ENABLE_GLITCH_CUTSCENES]); + mOptions[RSK_GOSSIP_STONE_HINTS] = Option::U8("Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE); + mOptions[RSK_HINT_CLARITY] = Option::U8("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintClarity"), mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT); + mOptions[RSK_HINT_DISTRIBUTION] = Option::U8("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintDistribution"), mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT); + mOptions[RSK_TOT_ALTAR_HINT] = Option::Bool("ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AltarHint"), mOptionDescriptions[RSK_TOT_ALTAR_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_INDENT); + mOptions[RSK_GANONDORF_HINT] = Option::Bool("Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanondorfHint"), mOptionDescriptions[RSK_GANONDORF_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); + mOptions[RSK_SHEIK_LA_HINT] = Option::Bool("Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SheikLAHint"), mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); + mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", CVAR_RANDOMIZER_SETTING("DampeHint"), mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE); + mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); + mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); + mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE); + mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); + mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", CVAR_RANDOMIZER_SETTING("BiggoronHint"), mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE); + mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", CVAR_RANDOMIZER_SETTING("BigPoesHint"), mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE); + mOptions[RSK_CHICKENS_HINT] = Option::Bool("Chickens Hint", CVAR_RANDOMIZER_SETTING("ChickensHint"), mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE); + mOptions[RSK_MALON_HINT] = Option::Bool("Malon Hint", CVAR_RANDOMIZER_SETTING("MalonHint"), mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE); + mOptions[RSK_HBA_HINT] = Option::Bool("Horseback Archery Hint", CVAR_RANDOMIZER_SETTING("HBAHint"), mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE); + mOptions[RSK_WARP_SONG_HINTS] = Option::Bool("Warp Song Hints", CVAR_RANDOMIZER_SETTING("WarpSongText"), mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WidgetType::Checkbox, RO_GENERIC_ON); + mOptions[RSK_SCRUB_TEXT_HINT] = Option::Bool("Scrub Hint Text", CVAR_RANDOMIZER_SETTING("ScrubText"), mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_10_SKULLS_HINT] = Option::Bool("10 GS Hint", CVAR_RANDOMIZER_SETTING("10GSHint"), mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_20_SKULLS_HINT] = Option::Bool("20 GS Hint", CVAR_RANDOMIZER_SETTING("20GSHint"), mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", CVAR_RANDOMIZER_SETTING("30GSHint"), mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", CVAR_RANDOMIZER_SETTING("40GSHint"), mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", CVAR_RANDOMIZER_SETTING("50GSHint"), mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT]); // TODO: Compasses show rewards/woth, maps show dungeon mode - mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", "gRandomizeBlueFireArrows", mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); - mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", "gRandomizeSunlightArrows", mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); - mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, "gRandomizeItemPool", mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); - mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, "gRandomizeIceTraps", mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); + mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); + mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); + mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); + mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); // TODO: Remove Double Defense, Progressive Goron Sword - mOptions[RSK_STARTING_OCARINA] = Option::U8("Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, "gRandomizeStartingOcarina", "", WidgetType::Combobox, RO_STARTING_OCARINA_OFF); - mOptions[RSK_STARTING_DEKU_SHIELD] = Option::Bool("Start with Deku Shield", "gRandomizeStartingDekuShield"); - mOptions[RSK_STARTING_KOKIRI_SWORD] = Option::Bool("Start with Kokiri Sword", "gRandomizeStartingKokiriSword"); - mOptions[RSK_STARTING_MASTER_SWORD] = Option::Bool("Start with Master Sword", "gRandomizeStartingMasterSword"); - mOptions[RSK_STARTING_CONSUMABLES] = Option::Bool("Start with Consumables", {"No", "Yes"}, OptionCategory::Setting, "gRandomizeStartingConsumables", "", WidgetType::Checkbox, RO_GENERIC_OFF); - mOptions[RSK_FULL_WALLETS] = Option::Bool("Full Wallets", {"No", "Yes"}, OptionCategory::Setting, "gRandomizeFullWallets", mOptionDescriptions[RSK_FULL_WALLETS], WidgetType::Checkbox, RO_GENERIC_OFF); - mOptions[RSK_STARTING_ZELDAS_LULLABY] = Option::Bool("Start with Zelda's Lullaby", "gRandomizeStartingZeldasLullaby", "", IMFLAG_NONE); - mOptions[RSK_STARTING_EPONAS_SONG] = Option::Bool("Start with Epona's Song", "gRandomizeStartingEponasSong", "", IMFLAG_NONE); - mOptions[RSK_STARTING_SARIAS_SONG] = Option::Bool("Start with Saria's Song", "gRandomizeStartingSariasSong", "", IMFLAG_NONE); - mOptions[RSK_STARTING_SUNS_SONG] = Option::Bool("Start with Sun's Song", "gRandomizeStartingSunsSong", "", IMFLAG_NONE); - mOptions[RSK_STARTING_SONG_OF_TIME] = Option::Bool("Start with Song of Time", "gRandomizeStartingSongOfTime", "", IMFLAG_NONE); - mOptions[RSK_STARTING_SONG_OF_STORMS] = Option::Bool("Start with Song of Storms", "gRandomizeStartingSongOfStorms", "", IMFLAG_NONE); - mOptions[RSK_STARTING_MINUET_OF_FOREST] = Option::Bool("Start with Minuet of Forest", "gRandomizeStartingMinuetOfForest", "", IMFLAG_NONE); - mOptions[RSK_STARTING_BOLERO_OF_FIRE] = Option::Bool("Start with Bolero of Fire", "gRandomizeStartingBoleroOfFire", "", IMFLAG_NONE); - mOptions[RSK_STARTING_SERENADE_OF_WATER] = Option::Bool("Start with Serenade of Water", "gRandomizeStartingSerenadeOfWater", "", IMFLAG_NONE); - mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT] = Option::Bool("Start with Requiem of Spirit", "gRandomizeStartingRequiemOfSpirit", "", IMFLAG_NONE); - mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW] = Option::Bool("Start with Nocturne of Shadow", "gRandomizeStartingNocturneOfShadow", "", IMFLAG_NONE); - mOptions[RSK_STARTING_PRELUDE_OF_LIGHT] = Option::Bool("Start with Prelude of Light", "gRandomizeStartingPreludeOfLight"); - mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, "gRandomizeStartingSkulltulaToken", "", WidgetType::Slider); + mOptions[RSK_STARTING_OCARINA] = Option::U8("Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingOcarina"), "", WidgetType::Combobox, RO_STARTING_OCARINA_OFF); + mOptions[RSK_STARTING_DEKU_SHIELD] = Option::Bool("Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield")); + mOptions[RSK_STARTING_KOKIRI_SWORD] = Option::Bool("Start with Kokiri Sword", CVAR_RANDOMIZER_SETTING("StartingKokiriSword")); + mOptions[RSK_STARTING_MASTER_SWORD] = Option::Bool("Start with Master Sword", CVAR_RANDOMIZER_SETTING("StartingMasterSword")); + mOptions[RSK_STARTING_CONSUMABLES] = Option::Bool("Start with Consumables", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingConsumables"), "", WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_FULL_WALLETS] = Option::Bool("Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_STARTING_ZELDAS_LULLABY] = Option::Bool("Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_EPONAS_SONG] = Option::Bool("Start with Epona's Song", CVAR_RANDOMIZER_SETTING("StartingEponasSong"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_SARIAS_SONG] = Option::Bool("Start with Saria's Song", CVAR_RANDOMIZER_SETTING("StartingSariasSong"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_SUNS_SONG] = Option::Bool("Start with Sun's Song", CVAR_RANDOMIZER_SETTING("StartingSunsSong"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_SONG_OF_TIME] = Option::Bool("Start with Song of Time", CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_SONG_OF_STORMS] = Option::Bool("Start with Song of Storms", CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_MINUET_OF_FOREST] = Option::Bool("Start with Minuet of Forest", CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_BOLERO_OF_FIRE] = Option::Bool("Start with Bolero of Fire", CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_SERENADE_OF_WATER] = Option::Bool("Start with Serenade of Water", CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT] = Option::Bool("Start with Requiem of Spirit", CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW] = Option::Bool("Start with Nocturne of Shadow", CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), "", IMFLAG_NONE); + mOptions[RSK_STARTING_PRELUDE_OF_LIGHT] = Option::Bool("Start with Prelude of Light", CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight")); + mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WidgetType::Slider); mOptions[RSK_STARTING_HEARTS] = Option::U8("Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, "", "", WidgetType::Slider, 2); // TODO: Remainder of Starting Items - mOptions[RSK_LOGIC_RULES] = Option::U8("Logic", {"Glitchless", "Glitched", "No Logic", "Vanilla"}, OptionCategory::Setting, "gRandomizeLogicRules", mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); - mOptions[RSK_ALL_LOCATIONS_REACHABLE] = Option::Bool("All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, "gRandomizeAllLocationsReachable", mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON); - mOptions[RSK_SKULLS_SUNS_SONG] = Option::Bool("Night Skulltula's Expect Sun's Song", "gRandomizeGsExpectSunsSong", mOptionDescriptions[RSK_SKULLS_SUNS_SONG]); + mOptions[RSK_LOGIC_RULES] = Option::U8("Logic", {"Glitchless", "Glitched", "No Logic", "Vanilla"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); + mOptions[RSK_ALL_LOCATIONS_REACHABLE] = Option::Bool("All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON); + mOptions[RSK_SKULLS_SUNS_SONG] = Option::Bool("Night Skulltula's Expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), mOptionDescriptions[RSK_SKULLS_SUNS_SONG]); mOptions[RSK_DAMAGE_MULTIPLIER] = Option::U8("Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WidgetType::Slider, RO_DAMAGE_MULTIPLIER_DEFAULT); // clang-format on @@ -1299,7 +1299,7 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Hide(); mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Hide(); mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Hide(); - if (CVarGetInteger("gRandomizeLogicRules", RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) == RO_LOGIC_VANILLA) { mOptionGroups[RSG_AREA_ACCESS_IMGUI].Disable(); mOptions[RSK_STARTING_AGE].Disable(""); mOptions[RSK_GERUDO_FORTRESS].Disable(""); @@ -1322,9 +1322,9 @@ void Settings::UpdateOptionProperties() { } else { mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable(); // Starting Age - Disabled when Forest is set to Closed or under very specific conditions - if (CVarGetInteger("gRandomizeForest", RO_FOREST_CLOSED) == RO_FOREST_CLOSED || - (CVarGetInteger("gRandomizeDoorOfTime", RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && - CVarGetInteger("gRandomizeShuffleOcarinas", RO_GENERIC_OFF) == RO_GENERIC_OFF)) /* closed door of time with ocarina shuffle off */ { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_CLOSED) == RO_FOREST_CLOSED || + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == RO_GENERIC_OFF)) /* closed door of time with ocarina shuffle off */ { mOptions[RSK_STARTING_AGE].Disable("This option is disabled due to other options making the game unbeatable"); } else { mOptions[RSK_STARTING_AGE].Enable(); @@ -1337,8 +1337,8 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Enable(); mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Enable(); mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Enable(); - const uint8_t bridgeOpt = CVarGetInteger("gRandomizeBridgeRewardOptions", RO_BRIDGE_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeRainbowBridge", RO_BRIDGE_VANILLA)) { + const uint8_t bridgeOpt = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA)) { case RO_BRIDGE_STONES: // Show Bridge Options and Stone Count slider mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1411,7 +1411,7 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_GANONS_TRIALS].Enable(); mOptions[RSK_TRIAL_COUNT].Enable(); // Only show the trial count slider if Trials is set to Set Number - if (CVarGetInteger("gRandomizeGanonTrial", RO_GANONS_TRIALS_SKIP) == RO_GANONS_TRIALS_SET_NUMBER) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SKIP) == RO_GANONS_TRIALS_SET_NUMBER) { mOptions[RSK_GANONS_TRIALS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_TRIAL_COUNT].Unhide(); } else { @@ -1422,7 +1422,7 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Enable(); mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Enable(); // Remove the pieces required/total sliders and add a separator after Tirforce Hunt if Triforce Hunt is off - if (CVarGetInteger("gRandomizeTriforceHunt", RO_GENERIC_OFF) == RO_GENERIC_OFF) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), RO_GENERIC_OFF) == RO_GENERIC_OFF) { mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Hide(); mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Hide(); mOptions[RSK_TRIFORCE_HUNT].AddFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1432,14 +1432,14 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_TRIFORCE_HUNT].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); } // Update triforce pieces required to be capped at the current value for pieces total. - const uint8_t triforceTotal = CVarGetInteger("gRandomizeTriforceHuntTotalPieces", 30); + const uint8_t triforceTotal = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30); if (mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].GetOptionCount() != triforceTotal + 1) { mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].ChangeOptions(NumOpts(1, triforceTotal + 1)); } mOptionGroups[RSG_ITEMS_IMGUI_TABLE].Enable(); mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE].Enable(); // Link's Pocket - Disabled when Dungeon Rewards are shuffled to End of Dungeon - if (CVarGetInteger("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON) { mOptions[RSK_LINKS_POCKET].Disable("This option is disabled because \"Dungeon Rewards\" are shuffled to \"End of Dungeons\"."); } else { mOptions[RSK_LINKS_POCKET].Enable(); @@ -1467,7 +1467,7 @@ void Settings::UpdateOptionProperties() { } else { // If any MQ Options are available, show the MQ Dungeon Randomization Combobox mOptions[RSK_MQ_DUNGEON_RANDOM].Unhide(); - switch(CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE)) { + switch(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE)) { // If No MQ Dungeons, add a separator after the combobx and hide // the count slider and the toggle for individual dungeon selections. case RO_MQ_DUNGEONS_NONE: @@ -1494,8 +1494,8 @@ void Settings::UpdateOptionProperties() { break; } // Controls whether or not to show the selectors for individual dungeons. - if (CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE && - CVarGetInteger("gRandomizeMqDungeonsSelection", RO_GENERIC_OFF) == RO_GENERIC_ON) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeonsSelection"), RO_GENERIC_OFF) == RO_GENERIC_ON) { // if showing the dungeon selectors, remove the separator after the Set Dungeons checkbox. mOptions[RSK_MQ_DUNGEON_SET].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MQ_DEKU_TREE].Unhide(); @@ -1528,13 +1528,13 @@ void Settings::UpdateOptionProperties() { } } // Disable interaction with Set Dungeons checkbox if MQ Dungeon Randomization is set to Selection Only. - if (CVarGetInteger("gRandomizeMqDungeons", RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { mOptions[RSK_MQ_DUNGEON_SET].Disable("This option is force-enabled because Master Quest Dungeons is set to Selection Only", UIWidgets::CheckboxGraphics::Checkmark); } else { mOptions[RSK_MQ_DUNGEON_SET].Enable(); } // Show mixed entrance pool options if mixed entrance pools are enabled at all. - if (CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF)) { mOptions[RSK_MIXED_ENTRANCE_POOLS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MIX_DUNGEON_ENTRANCES].Unhide(); mOptions[RSK_MIX_BOSS_ENTRANCES].Unhide(); @@ -1550,13 +1550,13 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_MIX_GROTTO_ENTRANCES].Hide(); } // Shuffle Weird Egg - Disabled when Skip Child Zelda is active - if (CVarGetInteger("gRandomizeSkipChildZelda", RO_GENERIC_DONT_SKIP)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), RO_GENERIC_DONT_SKIP)) { mOptions[RSK_SHUFFLE_WEIRD_EGG].Disable("This option is disabled because \"Skip Child Zelda\" is enabled."); } else { mOptions[RSK_SHUFFLE_WEIRD_EGG].Enable(); } // Hide shopsanity prices if shopsanity is off or zero - switch (CVarGetInteger("gRandomizeShopsanity", RO_SHOPSANITY_OFF)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF)) { case RO_SHOPSANITY_OFF: case RO_SHOPSANITY_ZERO_ITEMS: mOptions[RSK_SHOPSANITY].AddFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1570,7 +1570,7 @@ void Settings::UpdateOptionProperties() { break; } // Hide fishing pond settings if we aren't shuffling the fishing pond - switch (CVarGetInteger("gRandomizeFishsanity", RO_FISHSANITY_OFF)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_OFF)) { case RO_FISHSANITY_POND: case RO_FISHSANITY_BOTH: mOptions[RSK_FISHSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1583,13 +1583,13 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_FISHSANITY_AGE_SPLIT].Hide(); } // Disable fishing pole hint if the fishing pole is not shuffled - if (CVarGetInteger("gRandomizeShuffleFishingPole", RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), RO_GENERIC_OFF)) { mOptions[RSK_FISHING_POLE_HINT].Enable(); } else { mOptions[RSK_FISHING_POLE_HINT].Disable("This option is disabled since the fishing pole is not shuffled."); } // Shuffle 100 GS Reward - Force-Enabled if Ganon's Boss Key is on the 100 GS Reward - if (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS) { mOptions[RSK_SHUFFLE_100_GS_REWARD].Disable("This option is force-enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\"", UIWidgets::CheckboxGraphics::Checkmark); } else { mOptions[RSK_SHUFFLE_100_GS_REWARD].Enable(); @@ -1606,7 +1606,7 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Hide(); mOptions[RSK_KEYRINGS_GTG].Hide(); mOptions[RSK_KEYRINGS_GANONS_CASTLE].Hide(); - switch (CVarGetInteger("gRandomizeShuffleKeyRings", RO_KEYRINGS_OFF)) { + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_OFF)) { case RO_KEYRINGS_COUNT: // Show count slider. mOptions[RSK_KEYRINGS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1627,20 +1627,20 @@ void Settings::UpdateOptionProperties() { default: break; } - const uint8_t maxKeyringCount = (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) == RO_GF_NORMAL && - CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; + const uint8_t maxKeyringCount = (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) == RO_GF_NORMAL && + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA) ? 9 : 8; if (mOptions[RSK_KEYRINGS_RANDOM_COUNT].GetOptionCount() != maxKeyringCount + 1) { mOptions[RSK_KEYRINGS_RANDOM_COUNT].ChangeOptions(NumOpts(0, maxKeyringCount)); } - if (CVarGetInteger("gRandomizeGerudoFortress", RO_GF_NORMAL) != RO_GF_NORMAL || - CVarGetInteger("gRandomizeGerudoKeys", RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL) != RO_GF_NORMAL || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA) { mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Disable("Disabled because the currently selected Gerudo Fortress Carpenters\n" "setting and/or Gerudo Fortress Keys setting is incompatible with\n" "having a Gerudo Fortress Keyring."); } else { mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Enable(); } - if (CVarGetInteger("gRandomizeTriforceHunt", RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), RO_GENERIC_OFF)) { mOptions[RSK_GANONS_BOSS_KEY].Disable("This option is disabled because Triforce Hunt is enabled." "Ganon's Boss key\nwill instead be given to you after Triforce Hunt completion."); } else { @@ -1653,8 +1653,8 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_LACS_REWARD_COUNT].Hide(); mOptions[RSK_LACS_DUNGEON_COUNT].Hide(); mOptions[RSK_LACS_TOKEN_COUNT].Hide(); - const uint8_t lacsOpts = CVarGetInteger("gRandomizeLacsRewardOptions", RO_LACS_STANDARD_REWARD); - switch (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA)) { + const uint8_t lacsOpts = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD); + switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA)) { case RO_GANON_BOSS_KEY_LACS_STONES: mOptions[RSK_LACS_OPTIONS].Unhide(); mOptions[RSK_LACS_STONE_COUNT].Unhide(); @@ -1715,12 +1715,12 @@ void Settings::UpdateOptionProperties() { break; } // Skip Child Stealth - Disabled when Skip Child Zelda is active - if (CVarGetInteger("gRandomizeSkipChildZelda", RO_GENERIC_DONT_SKIP)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), RO_GENERIC_DONT_SKIP)) { mOptions[RSK_SKIP_CHILD_STEALTH].Disable("This option is disabled because \"Skip Child Zelda\" is enabled."); } else { mOptions[RSK_SKIP_CHILD_STEALTH].Enable(); } - if (CVarGetInteger("gRandomizeGossipStoneHints", RO_GOSSIP_STONES_NEED_NOTHING) == RO_GOSSIP_STONES_NONE) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) == RO_GOSSIP_STONES_NONE) { mOptions[RSK_HINT_CLARITY].Hide(); mOptions[RSK_HINT_DISTRIBUTION].Hide(); } else { @@ -1728,19 +1728,19 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_HINT_DISTRIBUTION].Unhide(); } - if (CVarGetInteger("gRandomizeShuffleCows", RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), RO_GENERIC_OFF)) { mOptions[RSK_MALON_HINT].Enable(); } else { mOptions[RSK_MALON_HINT].Disable("Malon's hint points to a cow, so requires cows to be shuffled."); } - if (CVarGetInteger("gRandomizeShuffle100GSReward", RO_GENERIC_OFF)) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), RO_GENERIC_OFF)) { mOptions[RSK_KAK_100_SKULLS_HINT].Enable(); } else { mOptions[RSK_KAK_100_SKULLS_HINT].Disable("There is no point to hinting 100 skulls if it is not shuffled"); } - if (CVarGetInteger("gRandomizeCuccosToReturn", 7) == 0) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7) == 0) { mOptions[RSK_CHICKENS_HINT].Disable("Anju will just give you the item instead with 0 chickens"); } else { mOptions[RSK_CHICKENS_HINT].Enable(); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index ad612a82e..569459c67 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -96,7 +96,7 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { // todo: figure out a better way to handle toggling so we don't // need to double check cvars like this - if(!(IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if(!(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnDntDemo_Judge(enDntDemo, play); return; } @@ -141,12 +141,12 @@ void TimeSaverOnGameFrameUpdateHandler() { void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { case VB_PLAY_TRANSITION_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.cutsceneIndex = 0; *should = false; } - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { // Song of Time if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) { gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_16; @@ -184,7 +184,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } } - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { uint8_t isBlueWarp = 0; // Deku Tree Blue warp if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { @@ -278,7 +278,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } if (gSaveContext.entranceIndex == ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0) { - if (CVarGetInteger("gTimeSavers.SkipTowerEscape", false) || IS_BOSS_RUSH) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), false) || IS_BOSS_RUSH) { Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; *should = false; @@ -286,7 +286,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) { - if (CVarGetInteger("gTimeSavers.SkipChildStealth", false)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), false)) { gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0; *should = false; } @@ -295,13 +295,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } case VB_PLAY_ENTRANCE_CS: { s32* entranceFlag = static_cast(opt); - if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { *should = false; } break; } case VB_PLAY_ONEPOINT_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) { s16* csId = static_cast(opt); switch (*csId) { case 4180: @@ -317,7 +317,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_PLAY_ONEPOINT_ACTOR_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) { Actor* actor = static_cast(opt); // there are a few checks throughout the game (such as chest spawns) that rely on this @@ -404,18 +404,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_SHOW_TITLE_CARD: - if (CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO)) { *should = false; } break; case VB_WONDER_TALK: { - if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), IS_RANDO)) { *should = false; } break; } case VB_NAVI_TALK: { - if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), IS_RANDO)) { ElfMsg* naviTalk = static_cast(opt); Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F); Actor_Kill(&naviTalk->actor); @@ -424,14 +424,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_NOT_BE_GREETED_BY_SARIA: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); *should = true; } break; case VB_MOVE_MIDO_IN_KOKIRI_FOREST: if ( - CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) @@ -441,7 +441,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case VB_PLAY_DEKU_TREE_INTRO_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { BgTreemouth* treeMouth = static_cast(opt); Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -453,7 +453,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { // We're overriding this so that the Deku JR doesn't despawn after skipping the forest temple blue warp cutscene. // It typically relies on the forest medallion being obtained, but that isn't given yet until after scene init - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); } break; @@ -462,18 +462,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: case VB_GIVE_ITEM_FAIRY_OCARINA: case VB_GIVE_ITEM_LIGHT_ARROW: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { *should = false; } break; case VB_PLAY_NABOORU_CAPTURED_CS: - if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (*should == true && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA); *should = false; } break; case VB_PLAY_PULL_MASTER_SWORD_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { // Normally, these would be done in the cutscene, but we're skipping it Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); @@ -488,7 +488,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case VB_OWL_INTERACTION: { - if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && *should) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) && *should) { EnOwl* enOwl = static_cast(opt); s32 owlType = (enOwl->actor.params & 0xFC0) >> 6; @@ -502,7 +502,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { u16* textId = static_cast(opt); // If the doors are not open yet, prioritize opening them if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { @@ -516,12 +516,12 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case VB_PLAY_EYEDROPS_CS: case VB_PLAY_DROP_FISH_FOR_JABU_CS: case VB_PLAY_DARUNIAS_JOY_CS: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { *should = false; } break; case VB_PLAY_ZELDAS_LULLABY_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { DemoIm* demoIm = static_cast(opt); Player* player = GET_PLAYER(gPlayState); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -532,7 +532,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* static uint32_t demoImKillHook = 0; demoImUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* actorRef) mutable { Actor* actor = static_cast(actorRef); - if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO)) { DemoIm* demoIm = static_cast(actorRef); Player* player = GET_PLAYER(gPlayState); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; @@ -571,7 +571,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_PLAY_SARIAS_SONG_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { EnSa* enSa = static_cast(opt); enSa->actionFunc = func_80AF6B20; *should = false; @@ -579,13 +579,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_DESPAWN_HORSE_RACE_COW: { - if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger("gCowOfTime", 0)) { + if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger(CVAR_ENHANCEMENT("CowOfTime"), 0)) { *should = false; } break; } case VB_PLAY_DRAIN_WELL_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { *should = false; Flags_SetSwitch(gPlayState, 0x2); Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); @@ -594,7 +594,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_PLAY_SUNS_SONG_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { *should = false; Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG); // SoH [Randomizer] TODO: Increment time X amount (find out X) @@ -603,19 +603,19 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; case VB_PLAY_ROYAL_FAMILY_TOMB_CS: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { *should = false; } break; } case VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { *should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); } break; } case VB_PLAY_DOOR_OF_TIME_CS: { - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { *should = false; Flags_SetEnv(gPlayState, 2); func_80078884(NA_SE_SY_CORRECT_CHIME); @@ -638,41 +638,41 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* case VB_PLAY_BOLERO_OF_FIRE_CS: case VB_PLAY_SERENADE_OF_WATER_CS: case VB_PLAY_PRELUDE_OF_LIGHT_CS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { *should = false; } break; case VB_DAMPE_IN_GRAVEYARD_DESPAWN: - if (CVarGetInteger("gDampeAllNight", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeAllNight"), 0)) { *should = LINK_IS_ADULT || gPlayState->sceneNum != SCENE_GRAVEYARD; } break; case VB_BE_VALID_GRAVEDIGGING_SPOT: - if (CVarGetInteger("gDampeWin", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { EnTk *enTk = static_cast(opt); enTk->validDigHere = true; *should = true; } break; case VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: - if (CVarGetInteger("gDampeWin", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DampeWin"), 0)) { EnTk *enTk = static_cast(opt); enTk->currentReward = 3; *should = true; } break; case VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE: - if (CVarGetInteger("gGravediggingTourFix", 0) || IS_RANDO) { + if (CVarGetInteger(CVAR_ENHANCEMENT("GravediggingTourFix"), 0) || IS_RANDO) { *should = !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE); } break; case VB_FIX_SAW_SOFTLOCK: // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. - *should = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should; + *should = (CVarGetInteger(CVAR_ENHANCEMENT("FixSawSoftlock"), 0) != 0 || CVarGetInteger(CVAR_ENHANCEMENT("SkipText"), 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should; break; case VB_BIGGORON_CONSIDER_SWORD_FORGED: - *should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3); + *should = Environment_GetBgsDayCount() >= CVarGetInteger(CVAR_ENHANCEMENT("ForgeTime"), 3); break; case VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD: { BgDyYoseizo* bgDyYoseizo = static_cast(opt); @@ -704,7 +704,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } } - if (flag != RAND_INF_MAX && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (flag != RAND_INF_MAX && (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { if (IS_RANDO || *should) { Flags_SetRandomizerInf(flag); gSaveContext.healthAccumulator = 0x140; @@ -716,14 +716,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } case VB_PLAY_RAINBOW_BRIDGE_CS: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { *should = false; func_800F595C(NA_BGM_BRIDGE_TO_GANONS); } break; } case VB_PHANTOM_GANON_DEATH_SCENE: { - if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO || IS_BOSS_RUSH)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), IS_RANDO || IS_BOSS_RUSH)) { *should = false; BossGanondrof* pg = static_cast(opt); Player* player = GET_PLAYER(gPlayState); @@ -749,7 +749,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } case VB_NABOORU_KNUCKLE_DEATH_SCENE: { EnIk* ik = static_cast(opt); - if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), IS_RANDO)) { // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor if ((ik->actor.colChkInfo.health <= 10)) { s32 i; @@ -791,7 +791,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) { enKoUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || IS_RANDO)) { EnKo* enKo = static_cast(innerActorRef); // They haven't moved yet, wrap their update function so we check every frame if (enKo->actionFunc == func_80A995CC) { @@ -817,7 +817,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } - if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { itemOcarinaframesSinceSpawn = 0; itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); @@ -835,7 +835,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) { enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO)) { EnMa1* enMa1 = static_cast(innerActorRef); if (enMa1->actionFunc == func_80AA106C) { enMa1->actionFunc = EnMa1_EndTeachSong; @@ -863,7 +863,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_FU) { enFuUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO)) { EnFu* enFu = static_cast(innerActorRef); if (enFu->actionFunc == EnFu_TeachSong) { enFu->actionFunc = EnFu_EndTeachSong; @@ -885,7 +885,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) { bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { BgSpot02Objects* bgSpot02 = static_cast(innerActorRef); if (bgSpot02->actionFunc == func_808ACC34) { bgSpot02->actionFunc = func_808AC908; @@ -904,14 +904,14 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } - if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { EnZl4* enZl4 = static_cast(actorRef); if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; } - if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnDntDemo* enDntDemo = static_cast(actorRef); enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; } @@ -921,7 +921,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { // or poes from which the cutscene is triggered until we can have a "BeforeActorInit" hook. // So for now we're just going to set the flag before they get to the room the cutscene is in if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && actor->id == ACTOR_EN_ST && !Flags_GetSwitch(gPlayState, 0x1B)) { - if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { Flags_SetSwitch(gPlayState, 0x1B); } } @@ -930,7 +930,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { if (actor->id == ACTOR_EN_PO_SISTERS && actor->params == 28) { enPoSistersUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_PO_SISTERS && innerActor->params == 28 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (innerActor->id == ACTOR_EN_PO_SISTERS && innerActor->params == 28 && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnPoSisters* enPoSisters = static_cast(innerActorRef); if (enPoSisters->actionFunc == func_80ADB338) { enPoSisters->unk_19C = 0; @@ -947,7 +947,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { // Fire Temple Darunia cutscene if (actor->id == ACTOR_EN_DU && gPlayState->sceneNum == SCENE_FIRE_TEMPLE) { - if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); Actor_Kill(actor); } @@ -957,63 +957,63 @@ void TimeSaverOnActorInitHandler(void* actorRef) { void TimeSaverOnSceneInitHandler(int16_t sceneNum) { switch (sceneNum) { case SCENE_HYRULE_CASTLE: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); } break; case SCENE_LON_LON_RANCH: - if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); } break; case SCENE_DEKU_TREE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); } } break; case SCENE_DODONGOS_CAVERN_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); } } break; case SCENE_JABU_JABU_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); } } break; case SCENE_FOREST_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); } } break; case SCENE_FIRE_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); } } break; case SCENE_WATER_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); } } break; case SCENE_SPIRIT_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); @@ -1022,7 +1022,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { } break; case SCENE_SHADOW_TEMPLE_BOSS: - if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO)) { if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE)) { Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); } @@ -1034,7 +1034,7 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) { static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { - if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) return; + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) return; switch (flagType) { case FLAG_EVENT_CHECK_INF: diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 657c51f79..41878bcce 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2362,7 +2362,7 @@ extern "C" int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSi } extern "C" void Randomizer_ParseSpoiler(const char* fileLoc) { - OTRGlobals::Instance->gRandoContext->ParseSpoiler(fileLoc, CVarGetInteger("gPlandoMode", 0)); + OTRGlobals::Instance->gRandoContext->ParseSpoiler(fileLoc, CVarGetInteger(CVAR_GENERAL("PlandoMode"), 0)); } extern "C" void Randomizer_LoadHintMessages() { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 8309ffc9a..7ac3e1e20 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -568,85 +568,85 @@ void DrawEnhancementsMenu() { ImGui::Text("Speed-ups:"); UIWidgets::PaddedSeparator(); bool allChecked = - CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) && - CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && - CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO); bool someChecked = - CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) || - CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) || - CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) || - CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) || + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO); ImGuiContext* g = ImGui::GetCurrentContext(); ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; if (!allChecked && someChecked) g->CurrentItemFlags |= ImGuiItemFlags_MixedValue; if (ImGui::Checkbox("All", &allChecked)) { if (allChecked) { - CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 1); - CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1); - CVarSetInteger("gTimeSavers.NoForcedDialog", 1); - CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1); - CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1); - CVarSetInteger("gTimeSavers.DisableTitleCard", 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), 1); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), 1); } else { - CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 0); - CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0); - CVarSetInteger("gTimeSavers.NoForcedDialog", 0); - CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0); - CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0); - CVarSetInteger("gTimeSavers.DisableTitleCard", 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), 0); + CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), 0); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } g->CurrentItemFlags = backup_item_flags; - UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Quick Boss Deaths", "gTimeSavers.SkipCutscene.QuickBossDeaths", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Intro", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Quick Boss Deaths", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", CVAR_ENHANCEMENT("TimeSavers.NoForcedDialog"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs"); - UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); + UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); - UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", "gTimeSavers.SkipChildStealth", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); - UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", "gTimeSavers.SkipTowerEscape", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("Skip the tower escape sequence between Ganondorf and Ganon."); UIWidgets::PaddedText("Skip Get Item Animations", true, false); - UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED); - if (CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) != SGIA_DISABLED) { - UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", "gTimeSavers.SkipGetItemAnimationScale", 5.0f, 15.0f, "", 10.0f, false); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), skipGetItemAnimationOptions, SGIA_DISABLED); + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED) != SGIA_DISABLED) { + UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 5.0f, 15.0f, "", 10.0f, false); UIWidgets::Tooltip("The size of the item when it is picked up"); } @@ -931,9 +931,9 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", CVAR_ENHANCEMENT("FishNeverEscape"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Once a hook has been set, fish will never let go while being reeled in."); - UIWidgets::PaddedEnhancementCheckbox("Loaches Always Appear", "gLoachesAlwaysAppear", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Loaches Always Appear", CVAR_ENHANCEMENT("LoachesAlwaysAppear"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("Loaches will always appear in the fishing pond instead of every four visits."); - UIWidgets::PaddedEnhancementCheckbox("Skip Keep Confirmation", "gSkipKeepConfirmation", true, false, disabled, disabledTooltip); + UIWidgets::PaddedEnhancementCheckbox("Skip Keep Confirmation", CVAR_ENHANCEMENT("SkipKeepConfirmation"), true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The pond owner will not ask to confirm if you want to keep a smaller fish."); UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3, 10, "", 10, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child"); @@ -1968,7 +1968,7 @@ extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void DrawRandomizerMenu() { if (ImGui::BeginMenu("Randomizer")) { - UIWidgets::EnhancementCheckbox("Plando Mode", "gPlandoMode"); + UIWidgets::EnhancementCheckbox("Plando Mode", CVAR_GENERAL("PlandoMode")); UIWidgets::Tooltip( "When dropping a spoiler file on the game window, parse the full spoiler file instead of just the " "necessary " @@ -2072,7 +2072,7 @@ void DrawRandomizerMenu() { "This setting is disabled because a savefile is loaded without the compass\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; - if (UIWidgets::PaddedEnhancementCheckbox("Compass Colors Match Dungeon", "gRandoEnhancement.MatchCompassColors", true, false, + if (UIWidgets::PaddedEnhancementCheckbox("Compass Colors Match Dungeon", CVAR_RANDOMIZER_ENHANCEMENT("MatchCompassColors"), true, false, disableCompassColors, disableCompassColorsText, UIWidgets::CheckboxGraphics::Cross, true)) { PatchCompasses(); } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 6df2802f8..409a0d837 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -69,7 +69,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { Actor_SetScale(&this->actor, 0.013f); for (i = 0; i < 2; i++) { - if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco") : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco"), : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), 0)) { continue; } diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c index dbd6007a2..ec19d6503 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c @@ -112,7 +112,7 @@ void EnSyatekiItm_Idle(EnSyatekiItm* this, PlayState* play) { 0; s32 ammunition = 15; if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->roundNum = this->hitCount = 0; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index eca7cc18c..500c60c51 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -395,7 +395,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->timer = 20; s32 ammunition = 15; if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->actionFunc = EnSyatekiMan_RestartGame; diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 1ff08fa96..a0ead103c 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -2943,12 +2943,12 @@ bool getFishNeverEscape() { } bool getShouldSpawnLoaches() { - return (CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gLoachesAlwaysAppear", 0)) + return (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("LoachesAlwaysAppear"), 0)) || ((KREG(1) == 1) || ((sFishGameNumber & 3) == 3)); } bool getShouldConfirmKeep() { - return !CVarGetInteger("gCustomizeFishing", 0) || !CVarGetInteger("gSkipKeepConfirmation", 0); + return !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) || !CVarGetInteger(CVAR_ENHANCEMENT("SkipKeepConfirmation"), 0); } void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 81c6c7b71..dcf3209cb 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1025,7 +1025,7 @@ void FileChoose_UpdateRandomizer() { return; } - if (!SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), "")) && !CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) { + if (!SpoilerFileExists(CVarGetString(CVAR_GENERAL("SpoilerLog"), "")) && !CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { CVarSetString(CVAR_GENERAL("SpoilerLog"), ""); } @@ -1343,18 +1343,18 @@ void FileChoose_GenerateRandoSeed(GameState* thisx) { this->prevConfigMode = this->configMode; this->configMode = CM_ROTATE_TO_NAME_ENTRY; this->logoAlpha = 0; - CVarSetInteger("gOnFileSelectNameEntry", 1); + CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 1); this->kbdButton = FS_KBD_BTN_NONE; this->charPage = FS_CHAR_PAGE_ENG; this->kbdX = 0; this->kbdY = 0; this->charIndex = 0; this->charBgAlpha = 0; - this->newFileNameCharCount = CVarGetInteger("gLinkDefaultName", 0) ? 4 : 0; + this->newFileNameCharCount = CVarGetInteger(CVAR_GENERAL("LinkDefaultName"), 0) ? 4 : 0; this->nameEntryBoxPosX = 120; this->nameEntryBoxAlpha = 0; memcpy(Save_GetSaveMetaInfo(this->buttonIndex)->playerName, - CVarGetInteger("gLinkDefaultName", 0) ? &linkName : &emptyName, 8); + CVarGetInteger(CVAR_GENERAL("LinkDefaultName"), 0) ? &linkName : &emptyName, 8); return; } if (!generating) { From f354460d042c1a58f62f0747de4eff088de72a85 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 5 May 2024 22:43:11 -0700 Subject: [PATCH 220/300] Make it build. --- .../Enhancements/randomizer/hook_handlers.cpp | 12 +- soh/soh/Enhancements/randomizer/option.cpp | 10 +- .../Enhancements/randomizer/randomizer.cpp | 6 +- .../randomizer/randomizer_check_tracker.cpp | 16 +- soh/src/code/z_parameter.c | 149 +++++++++--------- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 2 +- .../ovl_En_Syateki_Itm/z_en_syateki_itm.c | 2 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 2 +- 8 files changed, 100 insertions(+), 99 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 257666a61..db388ae1c 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -193,7 +193,7 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); if (loc == nullptr || loc->HasObtained()) return; - SPDLOG_INFO("Queuing RC: {}", rc); + SPDLOG_INFO("Queuing RC: {}", static_cast(rc)); randomizerQueuedChecks.push(rc); } @@ -211,7 +211,7 @@ void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); if (loc == nullptr || loc->HasObtained()) return; - SPDLOG_INFO("Queuing RC: {}", rc); + SPDLOG_INFO("Queuing RC: {}", static_cast(rc)); randomizerQueuedChecks.push(rc); } @@ -235,11 +235,11 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); if (loc->HasObtained()) { - SPDLOG_INFO("RC {} already obtained, skipping", rc); + SPDLOG_INFO("RC {} already obtained, skipping", static_cast(rc)); } else { randomizerQueuedCheck = rc; randomizerQueuedItemEntry = getItemEntry; - SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, rc); + SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, static_cast(rc)); if ( // Skipping ItemGet animation incompatible with checks that require closing a text box to finish rc != RC_HF_OCARINA_OF_TIME_ITEM && @@ -276,7 +276,7 @@ void RandomizerOnPlayerUpdateForItemQueueHandler() { return; } - SPDLOG_INFO("Attempting to give Item mod {} item {} from RC {}", randomizerQueuedItemEntry.modIndex, randomizerQueuedItemEntry.itemId, randomizerQueuedCheck); + SPDLOG_INFO("Attempting to give Item mod {} item {} from RC {}", randomizerQueuedItemEntry.modIndex, randomizerQueuedItemEntry.itemId, static_cast(randomizerQueuedCheck)); GiveItemEntryWithoutActor(gPlayState, randomizerQueuedItemEntry); if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { // Allow the player to receive the item while swimming @@ -290,7 +290,7 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { auto loc = Rando::Context::GetInstance()->GetItemLocation(randomizerQueuedCheck); if (randomizerQueuedItemEntry.modIndex == receivedItemEntry.modIndex && randomizerQueuedItemEntry.itemId == receivedItemEntry.itemId) { - SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, randomizerQueuedCheck); + SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, static_cast(randomizerQueuedCheck)); loc->MarkAsObtained(); randomizerQueuedCheck = RC_UNKNOWN_CHECK; randomizerQueuedItemEntry = GET_ITEM_NONE; diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp index 950fa96cf..acccb9c5b 100644 --- a/soh/soh/Enhancements/randomizer/option.cpp +++ b/soh/soh/Enhancements/randomizer/option.cpp @@ -1,7 +1,7 @@ #include "option.h" #include "libultraship/bridge.h" #include -#include +#include #include "soh/UIWidgets.hpp" namespace Rando { @@ -198,7 +198,7 @@ bool Option::RenderCheckbox() const { if (CustomCheckbox(name.c_str(), &val, disabled, disabledGraphic)) { CVarSetInteger(cvarName.c_str(), val); changed = true; - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (!description.empty()) { UIWidgets::InsertHelpHoverText(description.c_str()); @@ -220,7 +220,7 @@ bool Option::RenderCombobox() const { selected--; CVarSetInteger(cvarName.c_str(), selected); changed = true; - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } if (!description.empty()) { UIWidgets::InsertHelpHoverText(description.c_str()); @@ -233,7 +233,7 @@ bool Option::RenderCombobox() const { CVarSetInteger(cvarName.c_str(), static_cast(i)); changed = true; selected = i; - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } } @@ -296,7 +296,7 @@ bool Option::RenderSlider() const { } if (changed) { CVarSetInteger(cvarName.c_str(), val); - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } return changed; } diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 77f1e7888..6f5820952 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2321,11 +2321,11 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += ","; } if (enabledTrickString == "") { - CVarClear(CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); + CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); } else { - CVarSetString(CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); } - LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } Rando::Tricks::DrawTagChips(option.GetTags()); ImGui::SameLine(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index c49c56c7b..772d4d747 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -144,8 +144,8 @@ RandomizerCheckArea currentArea = RCAREA_INVALID; OSContPad* trackerButtonsPressed; std::unordered_map checkNameOverrides; -bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheckObject rcObject); -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); +bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheck check); +bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0); bool CompareChecks(RandomizerCheck, RandomizerCheck); bool CheckByArea(RandomizerCheckArea); @@ -1056,7 +1056,7 @@ void CheckTrackerWindow::DrawElement() { doAreaScroll = false; } for (auto rc : checks) { - if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rc) && passesTextFilter(checkSearch, rcObject)) { + if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rc) && passesTextFilter(checkSearch, rc)) { DrawLocation(rc); } } @@ -1076,7 +1076,7 @@ void CheckTrackerWindow::DrawElement() { } } -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { +bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); if (!shouldHideFilteredAreas) { return false; @@ -1091,10 +1091,10 @@ bool shouldHideArea(ImGuiTextFilter& checkSearch, std::mapGetArea()).c_str()) || + checkSearch.PassFilter(Rando::StaticData::GetLocation(check)->GetShortName().c_str()) ); } @@ -1425,7 +1425,7 @@ void DrawLocation(RandomizerCheck rc) { mainColor = !IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO ? CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default) - : CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor", Color_Main_Default); + : CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor"), Color_Main_Default); extraColor = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor"), Color_Skipped_Extra_Default); } else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) { if (!showHidden && CVarGetInteger(CVAR_TRACKER_CHECK("Seen.Hide"), 0)) { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 002521eaa..934b9486d 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -5178,83 +5178,84 @@ void Interface_Draw(PlayState* play) { Gfx_SetupDL_39Overlay(play->state.gfxCtx); if (fullUi) { - //when not having a wallet in rando, don't calculate the ruppe icon - if (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { - // Rupee Icon - if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { - switch (CUR_UPG_VALUE(UPG_WALLET)) { - case 0: - if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0)) { - rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); - } else { - rColor = rupeeWalletColors[0]; - } - break; - case 1: - if (CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0)) { - rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), rupeeWalletColors[1]); - } else { - rColor = rupeeWalletColors[1]; - } - break; - case 2: - if (CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0)) { - rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), rupeeWalletColors[2]); - } else { - rColor = rupeeWalletColors[2]; - } - break; - case 3: - if (CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0)) { - rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), rupeeWalletColors[3]); - } else { - rColor = rupeeWalletColors[3]; - } - break; - } - } else { - if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), rupeeWalletColors)) { - rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); - } else { - rColor = rupeeWalletColors[0]; - } - - //Rupee icon & counter - s16 X_Margins_RC; - s16 Y_Margins_RC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 0) {X_Margins_RC = Left_HUD_Margin;}; - Y_Margins_RC = Bottom_HUD_Margin; - } else { - X_Margins_RC = 0; - Y_Margins_RC = 0; - } - s16 PosX_RC_ori = OTRGetRectDimensionFromLeftEdge(26+X_Margins_RC); - s16 PosY_RC_ori = 206+Y_Margins_RC; s16 PosX_RC; s16 PosY_RC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) != 0) { - PosY_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosY"), 0)+Y_Margins_RC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Left_HUD_Margin;}; - PosX_RC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Right_HUD_Margin;}; - PosX_RC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 3) {//Anchor None - PosX_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 4) {//Hidden - PosX_RC = -9999; + //when not having a wallet in rando, don't calculate the ruppe icon + if (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { + // Rupee Icon + if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { + switch (CUR_UPG_VALUE(UPG_WALLET)) { + case 0: + if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); + } else { + rColor = rupeeWalletColors[0]; + } + break; + case 1: + if (CVarGetInteger(CVAR_COSMETIC("Consumable.BlueRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.BlueRupee.Value"), rupeeWalletColors[1]); + } else { + rColor = rupeeWalletColors[1]; + } + break; + case 2: + if (CVarGetInteger(CVAR_COSMETIC("Consumable.RedRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.RedRupee.Value"), rupeeWalletColors[2]); + } else { + rColor = rupeeWalletColors[2]; + } + break; + case 3: + if (CVarGetInteger(CVAR_COSMETIC("Consumable.PurpleRupee.Changed"), 0)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.PurpleRupee.Value"), rupeeWalletColors[3]); + } else { + rColor = rupeeWalletColors[3]; + } + break; + } + } else { + if (CVarGetInteger(CVAR_COSMETIC("Consumable.GreenRupee.Changed"), rupeeWalletColors)) { + rColor = CVarGetColor24(CVAR_COSMETIC("Consumable.GreenRupee.Value"), rupeeWalletColors[0]); + } else { + rColor = rupeeWalletColors[0]; + } + } + + //Rupee icon & counter + s16 X_Margins_RC; + s16 Y_Margins_RC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 0) {X_Margins_RC = Left_HUD_Margin;}; + Y_Margins_RC = Bottom_HUD_Margin; + } else { + X_Margins_RC = 0; + Y_Margins_RC = 0; + } + s16 PosX_RC_ori = OTRGetRectDimensionFromLeftEdge(26+X_Margins_RC); + s16 PosY_RC_ori = 206+Y_Margins_RC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) != 0) { + PosY_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosY"), 0)+Y_Margins_RC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Left_HUD_Margin;}; + PosX_RC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.UseMargins"), 0) != 0) {X_Margins_RC = Right_HUD_Margin;}; + PosX_RC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0)+X_Margins_RC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 3) {//Anchor None + PosX_RC = CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Rupees.PosType"), 0) == 4) {//Hidden + PosX_RC = -9999; + } + } else { + PosY_RC = PosY_RC_ori; + PosX_RC = PosX_RC_ori; + } + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor.r, rColor.g, rColor.b, interfaceCtx->magicAlpha); + // Draw Rupee icon. Hide in Boss Rush. + if (!IS_BOSS_RUSH) { + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10); } - } else { - PosY_RC = PosY_RC_ori; - PosX_RC = PosX_RC_ori; - } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor.r, rColor.g, rColor.b, interfaceCtx->magicAlpha); - // Draw Rupee icon. Hide in Boss Rush. - if (!IS_BOSS_RUSH) { - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10); - } } switch (play->sceneNum) { diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 409a0d837..6df2802f8 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -69,7 +69,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { Actor_SetScale(&this->actor, 0.013f); for (i = 0; i < 2; i++) { - if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco"), : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), 0)) { + if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco") : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), 0)) { continue; } diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c index ec19d6503..dbd6007a2 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.c @@ -112,7 +112,7 @@ void EnSyatekiItm_Idle(EnSyatekiItm* this, PlayState* play) { 0; s32 ammunition = 15; if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->roundNum = this->hitCount = 0; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 500c60c51..eca7cc18c 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -395,7 +395,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->timer = 20; s32 ammunition = 15; if(CVarGetInteger(CVAR_ENHANCEMENT("CustomizeShootingGallery"), 0)) { - ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult"), : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); + ammunition = CVarGetInteger(LINK_IS_ADULT ? CVAR_ENHANCEMENT("ShootingGalleryAmmoAdult") : CVAR_ENHANCEMENT("ShootingGalleryAmmoChild"), 15); } func_8008EF44(play, ammunition); this->actionFunc = EnSyatekiMan_RestartGame; From 89f119c566075cfceed104223a6254e2c60313eb Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 11:13:30 -0700 Subject: [PATCH 221/300] Fix ambiguity. --- soh/soh/SaveManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index a3b2ff9a5..0aaf32e7c 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -445,7 +445,7 @@ void SaveManager::LoadRandomizerVersion3() { SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) { auto hint = RandomizerHint(i); - nlohmann::ordered_json json; + nlohmann::json json; SaveManager::Instance->LoadData("", json); randoContext->AddHint(hint, Rando::Hint(hint, json)); }); From d0627dc73706305fa527ee112c8c6b77666f5319 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Mon, 6 May 2024 20:10:00 +0100 Subject: [PATCH 222/300] fix a V2 compatibility crash (#4119) * Attempt to fix ambiguity issues and a V2 compatibility crash * oops * remove explicit call as it is fixed elsewhere --- soh/soh/SaveManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 0aaf32e7c..50d77917e 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -102,7 +102,7 @@ std::vector Rando::StaticData::oldVerHintOrder { RH_ZR_OPEN_GROTTO_GOSSIP_STONE, }; -uint16_t Rando::StaticData::oldVerGossipStoneStart = 740; +uint16_t Rando::StaticData::oldVerGossipStoneStart = 706; SaveManager::SaveManager() { coreSectionIDsByName["base"] = SECTION_ID_BASE; @@ -188,7 +188,7 @@ void SaveManager::LoadRandomizerVersion1() { for (int j = 0; j < ARRAY_COUNT(hintText); j++) { SaveManager::Instance->LoadData("ht" + std::to_string(i) + "-" + std::to_string(j), hintText[j]); } - RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[Rando::StaticData::oldVerGossipStoneStart]; + RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[i - Rando::StaticData::oldVerGossipStoneStart]; randoContext->AddHint(stoneHint, Rando::Hint(stoneHint, {CustomMessage(hintText)})); } @@ -294,7 +294,7 @@ void SaveManager::LoadRandomizerVersion2() { if (rc != RC_UNKNOWN_CHECK) { std::string hintText; SaveManager::Instance->LoadData("hintText", hintText); - RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[Rando::StaticData::oldVerGossipStoneStart]; + RandomizerHint stoneHint = Rando::StaticData::oldVerHintOrder[rc - Rando::StaticData::oldVerGossipStoneStart]; randoContext->AddHint(stoneHint, Rando::Hint(stoneHint, {CustomMessage(hintText)})); } }); From 27dd303a57da376847fae6d223ba6f2dfe5cd351 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Mon, 6 May 2024 15:10:22 -0400 Subject: [PATCH 223/300] Limit crawl speed to modifier to 4 (#4113) --- soh/soh/SohMenuBar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index b847988dc..f56c23c7f 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -572,7 +572,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", CVAR_ENHANCEMENT("MweepSpeed"), 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", CVAR_ENHANCEMENT("ClimbSpeed"), 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", CVAR_ENHANCEMENT("FasterBlockPush"), 0, 5, "", 0, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 4, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", CVAR_ENHANCEMENT("FasterHeavyBlockLift"), false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", CVAR_ENHANCEMENT("FastDrops"), true, false); From 438dede792b236c12d37d3d67c54d0765f758a1e Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 15:10:06 -0700 Subject: [PATCH 224/300] Change "AnubixFix" back to "AnubisFix". (#4124) --- soh/soh/Enhancements/presets.h | 6 +++--- soh/soh/SohMenuBar.cpp | 2 +- .../overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index aea4bb1fd..a502dc3da 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -163,7 +163,7 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("GravediggingTourFix"), CVAR_ENHANCEMENT("DekuNutUpgradeFix"), CVAR_ENHANCEMENT("NaviTextFix"), - CVAR_ENHANCEMENT("AnubixFix"), + CVAR_ENHANCEMENT("AnubisFix"), CVAR_ENHANCEMENT("CrouchStabHammerFix"), CVAR_ENHANCEMENT("CrouchStabFix"), CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), @@ -682,7 +682,7 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), @@ -808,7 +808,7 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f56c23c7f..c396de738 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1201,7 +1201,7 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", CVAR_ENHANCEMENT("NaviTextFix"), true, false); UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubixFix"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubisFix"), true, false); UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); if (UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", CVAR_ENHANCEMENT("CrouchStabHammerFix"), true, false)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { diff --git a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c index 0b1a2b0b7..a26f5a08b 100644 --- a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c +++ b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c @@ -116,7 +116,7 @@ void func_809B27D8(EnAnubiceFire* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); this->cylinder.base.atFlags &= 0xFFE9; this->cylinder.base.atFlags |= 8; - this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubixFix"), 0) ? 0x800 : 2; + this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubisFix"), 0) ? 0x800 : 2; this->unk_15A = 30; this->actor.params = 1; this->actor.velocity.x *= -1.0f; From f3b948226b11bca9c59715b27b404b3c1ec32c51 Mon Sep 17 00:00:00 2001 From: Lywx Date: Mon, 6 May 2024 17:19:15 -0600 Subject: [PATCH 225/300] Bump lus and fixed PatchGfx (#4125) * Bump lus and fixed PatchGfx * Bump libultraship to main --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libultraship b/libultraship index 7d71a2906..a5d84b294 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 7d71a290657a2d3b09a83e8b33025e807f4fb38e +Subproject commit a5d84b29429dcd9b32fb1d8b169b6dd269e6c979 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0a0b83d4a..b61bb65cc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1791,7 +1791,7 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch } Gfx* destinationGfx = (Gfx*)&res->Instructions[destinationIndex]; - Gfx sourceGfx = res->Instructions[sourceIndex]; + Gfx sourceGfx = *(Gfx*)&res->Instructions[sourceIndex]; if (!originalGfx.contains(path) || !originalGfx[path].contains(patchName)) { originalGfx[path][patchName] = { From b3d51441eb8759f607a9448c535c46f6a9cddecd Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 17:17:08 -0700 Subject: [PATCH 226/300] Rando Enhancement: Mysterious Shuffled Items (#3227) * Add rando enhancement "Mysterious Shuffled Items", which obfuscates shuffled freestanding/drawn-in-world items (PoH, tokens, shop items) with a custom question mark model (thanks Hato), and uses the "mysterious item" functionality of `GetMerchantMessage` for everything that supports it, regardless of hint status on generation. * Reverted back to rando enhancement, but added condition for Mysterious Shuffle not being on for the gem rotation fix to apply. * First attempt at changing to fake GetItemEntry instead of directly calling the mystery draw function. Needs more work. * Updated CVar to reflect CVar rework values. Added `IsCheckShuffled` as preliminary function for checking *only* if a check is shuffled, not necessarily if it is just visible on the tracker. This accounts for the difference between tokensanity and "Always Show GS On Tracker", where you don't want to obfuscate the latter. * Bit of cleanup. * Cross-platform building edits. If anyone has a better idea of how to handle this fake GIE, I'm all ears. * Update to CVar macros. * Fix freestanding item gives. Fix mysterious item model colors. * Fix bombchu bowling mystery. * Remove bowling bomchus check obfuscation (unused, removed in v3). --- .../object_mystery_item/gMysteryItemDL | 16 + .../object_mystery_item/gMysteryItemDL_tri_0 | 56 +++ .../object_mystery_item/gMysteryItemDL_tri_1 | 120 +++++ .../object_mystery_item/gMysteryItemDL_vtx_0 | 119 +++++ .../object_mystery_item/gMysteryItemDL_vtx_1 | 416 ++++++++++++++++++ .../gMysteryItemDL_vtx_cull | 10 + ...yItemDL_f3dlite_mysteryItem_light_material | 21 + ...MysteryItemDL_f3dlite_mysteryItem_material | 21 + .../objects/object_mystery_item/noise_tex | Bin 0 -> 1116 bytes soh/assets/soh_assets.h | 3 + soh/include/variables.h | 3 +- .../cosmetics/CosmeticsEditor.cpp | 1 + soh/soh/Enhancements/randomizer/draw.cpp | 25 +- soh/soh/Enhancements/randomizer/draw.h | 4 + .../Enhancements/randomizer/randomizer.cpp | 20 +- soh/soh/Enhancements/randomizer/randomizer.h | 1 + .../randomizer/randomizer_check_tracker.cpp | 19 +- .../randomizer/randomizer_check_tracker.h | 1 + soh/soh/OTRGlobals.cpp | 9 + soh/soh/OTRGlobals.h | 2 + soh/soh/SohMenuBar.cpp | 5 + soh/src/code/z_en_item00.c | 28 +- .../actors/ovl_Demo_Effect/z_demo_effect.c | 3 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 11 +- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 3 +- .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 4 +- .../ovl_Item_Etcetera/z_item_etcetera.c | 7 +- .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 2 +- 29 files changed, 896 insertions(+), 41 deletions(-) create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material create mode 100644 soh/assets/custom/objects/object_mystery_item/noise_tex diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL new file mode 100644 index 000000000..939042daa --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 new file mode 100644 index 000000000..8c320d243 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 new file mode 100644 index 000000000..0990859d5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 new file mode 100644 index 000000000..37e6186e9 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 new file mode 100644 index 000000000..4360eedc5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull new file mode 100644 index 000000000..cedf6351d --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material new file mode 100644 index 000000000..4dc39e811 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material new file mode 100644 index 000000000..6941bb55f --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/noise_tex b/soh/assets/custom/objects/object_mystery_item/noise_tex new file mode 100644 index 0000000000000000000000000000000000000000..aaf4e331f15f797a3b1122b58c57b3767e66bc0f GIT binary patch literal 1116 zcma)5S&rmH5G^FcIk*X5eDlKxBf5LKx?JVw&9uYY}ZlKyY|id266pZ|L)_-3^t z{^e>VIz`u(`^dKQ%g2w`bDu%x{^r%I8%i=wg`pMy&>oT`wvAwTeqNf)RT*l1cl(+W z4O3wm5FDBuCz%Uiv0TQ&*Cj#VNy!7F8h~R}KQ9uTqZsmTyW<5x_pt+H9l4&R zNV*$EuA#8o9Vc?s{bsv;)Pm5GMBTP6z|sQ5v2V)EX1(5QHV?AIOLmqzz`$u>%G@KX zAm1U#Q1`b#-cdY`0zWyHA&UB`uvJOq1z;j%s@!gUchADQtBSnLBiuZ{ObIeINsvAl zKp>GPf~X&wGE1T`oqzfLxlOSLfeJL;gpe$uxkXczdF&C0F2DWpa%!p~b}e0&RKxLI z%T231NzwpnD1Z9&={oddS76r=ISB@l@A&(Ji`>A~6jZ+b`Tf)mbH67OcwTj)5Scc{ zK!pLxobvMFI`+$@k4zv-0AY+25fE@S6z$W{&&H?oX}(_jP*+sLjS^qu9wmr;+rj%{ zAEy-|@BH@CVH4;m%+kORMa{#BXIWla6lGO6!#wp(?ire4hv`1{96uqtA;^bi)3$9t zo$9i#W2i_9OzJvM;xx4+nwI?IFm%JTj73}=LclXD2+J}FLmcRYNZGH3zUij9O&r(N zIC{GkOwTb52m2bcW%RfiySf=qM4ckHqqfwB78L>#iUN&&l-#mE4Q;=iy9hjP)*G6p zcAUU-vK4wNFT$)pja`3!_q^mt=2&vXvP9&Xrb8$zFlv{%J+_yZm#3OgWf__(%K$o# zDT@+s;Ci{tRaQ>d>(W(+JVHPr6kC2^iS&+v`RR%Lt01bUX&g>t6B|4yh?4GjP~1K+ zRyjYNyVUUyr+Hf5EKR78{fMr0WJ>e{hl cosmeticOptions = { COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4(0, 60, 100, 255), false, true, false), COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 4fbe489d2..7a970b895 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -248,7 +248,7 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get if (triforcePieceScale < 0.0001f) { triforcePieceScale += 0.00003f; } - + // Animation. When not the completed triforce, create delay before showing the piece to bypass interpolation. // If the completed triforce, make it grow slowly. if (current != required) { @@ -275,5 +275,28 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get } else if (current == required && triforcePieceScale > 0.00008f) { gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gTriforcePieceCompletedDL); } + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry) { + Color_RGB8 color = { 0, 60, 100 }; + if (CVarGetInteger(CVAR_COSMETIC("World.MysteryItem.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("World.MysteryItem.Value"), color); + } + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255); + gSPGrayscale(POLY_XLU_DISP++, true); + + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gMysteryItemDL); + + gSPGrayscale(POLY_XLU_DISP++, false); + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index d9134573d..8c152a4f9 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -16,6 +16,10 @@ void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); +void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry); + +#define GET_ITEM_MYSTERY \ + { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, Randomizer_DrawMysteryItem } #ifdef __cplusplus }; #endif diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index f5c522ddc..107e23e83 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -5412,12 +5412,20 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf); RandomizerGet shopItemGet = this->itemLocations[rc].rgID; std::array shopItemName; - if (mysterious) { - shopItemName = { - "mysterious item", - "mysteriösen Gegenstand", - "objet mystérieux" - }; + if (mysterious || CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + if (randomizerInf >= RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1 && randomizerInf <= RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8) { + shopItemName = { + "Mysterious Item", + "Mysteriösen Gegenstand", + "Objet Mystérieux" + }; + } else { + shopItemName = { + "mysterious item", + "mysteriösen Gegenstand", + "objet mystérieux" + }; + } // TODO: This should eventually be replaced with a full fledged trick model & trick name system } else if (shopItemGet == RG_ICE_TRAP) { shopItemGet = this->itemLocations[rc].fakeRgID; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a726cecde..ce8f5c45b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/randomizer/randomizer_check_objects.h" +#include "soh/Enhancements/randomizer/randomizer_check_tracker.h" #include "soh/Enhancements/randomizer/randomizer_tricks.h" #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 4ca8c7993..a53b838f3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1223,7 +1223,7 @@ void LoadSettings() { } } -bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { +bool IsCheckShuffled(RandomizerCheckObject rcObj) { if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { return (rcObj.rcArea != RCAREA_INVALID) && // don't show Invalid locations @@ -1236,7 +1236,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) || rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ) && - (rcObj.rcType != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && rcObj.actorParams > 0x03))) && + (rcObj.rcType != RCTYPE_SHOP || (showShops && rcObj.actorParams > 0x03)) && (rcObj.rcType != RCTYPE_SCRUB || showScrubs || rcObj.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || // The 3 scrubs that are always randomized @@ -1245,7 +1245,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { ) && (rcObj.rcType != RCTYPE_MERCHANT || showMerchants) && (rcObj.rcType != RCTYPE_OCARINA || showOcarinas) && - (rcObj.rcType != RCTYPE_SKULL_TOKEN || alwaysShowGS || + (rcObj.rcType != RCTYPE_SKULL_TOKEN || (showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) || (showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea)) ) && @@ -1265,6 +1265,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { (rcObj.rcType != RCTYPE_BOSS_KEY || showBossKeysanity) && (rcObj.rcType != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) && (rcObj.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || show100SkullReward) && + (rcObj.rc != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) && (rcObj.rcType != RCTYPE_GF_KEY && rcObj.rc != RC_GF_GERUDO_MEMBERSHIP_CARD || (showGerudoCard && rcObj.rc == RC_GF_GERUDO_MEMBERSHIP_CARD) || (fortressNormal && showGerudoFortressKeys && rcObj.rcType == RCTYPE_GF_KEY) || @@ -1280,6 +1281,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { return false; } +bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { + return IsCheckShuffled(rcObj) || (rcObj.rcType == RCTYPE_SKULL_TOKEN && alwaysShowGS) || (rcObj.rcType == RCTYPE_SHOP && (showShops && (!hideShopRightChecks))); +} + void UpdateInventoryChecks() { //For all the areas with maps, if you have one, spoil the area for (auto [scene, area] : DungeonRCAreasBySceneID) { @@ -1444,6 +1449,8 @@ void DrawLocation(RandomizerCheckObject rcObj) { //Draw the extra info txt = ""; + bool mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && OTRGlobals::Instance->gRandomizer->merchantPrices.contains(rcObj.rc); + if (checkData.hintItem != 0) { // TODO hints } else if (status != RCSHOW_UNCHECKED) { @@ -1466,16 +1473,16 @@ void DrawLocation(RandomizerCheckObject rcObj) { case RCSHOW_IDENTIFIED: case RCSHOW_SEEN: if (IS_RANDO) { - if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP) { + if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP && !mystery) { if (status == RCSHOW_IDENTIFIED) { txt = gSaveContext.itemLocations[rcObj.rc].get.trickName; } else { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.fakeRgID][gSaveContext.language]; } - } else { + } else if (!mystery) { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.rgID][gSaveContext.language]; } - if (status == RCSHOW_IDENTIFIED) { + if (!IsVisibleInCheckTracker(rcObj) && status == RCSHOW_IDENTIFIED && !mystery) { txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rcObj.rc].price); } } else { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 216da367f..be1ae441c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -47,6 +47,7 @@ void DefaultCheckData(RandomizerCheck rc); void Teardown(); void UpdateAllOrdering(); bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj); +bool IsCheckShuffled(RandomizerCheckObject check); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b61bb65cc..518e9c1f3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -84,6 +84,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" +#include "Enhancements/randomizer/draw.h" #include // Resource Types/Factories @@ -2437,6 +2438,14 @@ extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck( return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck); } +extern "C" bool Randomizer_IsCheckShuffled(RandomizerCheck randomizerCheck) { + return CheckTracker::IsCheckShuffled(RandomizerCheckObjects::GetAllRCObjects().find(randomizerCheck)->second); +} + +extern "C" GetItemEntry GetItemMystery() { + return { ITEM_NONE_FE, 0, 0, 0, 0, 0, 0, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, NULL, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem }; +} + CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) { s16 giid; if (player->getItemEntry.objectId != OBJECT_INVALID) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 73cb58d97..e0b5c7a38 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -179,6 +179,8 @@ GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorPar GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId); +bool Randomizer_IsCheckShuffled(RandomizerCheck check); +GetItemEntry GetItemMystery(); ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); int CustomMessage_RetrieveIfExists(PlayState* play); void Overlay_DisplayText(float duration, const char* text); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c396de738..35274e5ac 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1972,6 +1972,11 @@ void DrawRandomizerMenu() { "Play unique fanfares when obtaining quest items " "(medallions/stones/songs). Note that these fanfares are longer than usual." ); + UIWidgets::PaddedEnhancementCheckbox("Mysterious Shuffled Items", CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), true, false); + UIWidgets::Tooltip( + "Displays a \"Mystery Item\" model in place of any freestanding/GS/shop items that were shuffled, " + "and replaces item names for them and scrubs and merchants, regardless of hint settings, " + "so you never know what you're getting."); ImGui::EndMenu(); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index db344d39e..772817716 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1366,17 +1366,19 @@ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { RandomizerCheck randoCheck = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = - Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; } - - f32 mtxScale = 10.67f; + + f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); @@ -1460,17 +1462,19 @@ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { if (IS_RANDO) { RandomizerCheck randoCheck = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = - Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; } f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else { s32 pad; diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 149c176c7..edab23ae8 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -2088,7 +2088,8 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { return; } if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_BARINADE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); this->getItem.drawId = getItemEntry.gid; func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index a3a196e31..b2d23984c 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -515,14 +515,17 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { switch (this->type) { case EXITEM_BOMB_BAG_BOWLING: case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE)) + ? GetItemMystery() + : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); break; case EXITEM_BOMBCHUS_BOWLING: case EXITEM_BOMBCHUS_COUNTER: randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); break; case EXITEM_BULLET_BAG: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LW_TARGET_IN_WOODS)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); break; } @@ -540,8 +543,8 @@ void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); GetItemEntry_Draw(play, randoGetItem); } else { diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 11c29227f..0382735a3 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -1286,8 +1286,8 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) { this->basePrice = shopItemIdentity.itemPrice; this->giDrawId = getItemEntry.gid; - // Correct the rotation for spiritual stones - if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) { + // Correct the rotation for spiritual stones, but only if mysterious shuffle isn't on, else it's obvious what's there in shops + if (!CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE)) { this->actor.shape.rot.y = this->actor.shape.rot.y + 20000; } } @@ -1332,7 +1332,8 @@ void EnGirlA_Draw(Actor* thisx, PlayState* play) { if (this->actor.params == SI_RANDOMIZED_ITEM) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && this->actor.params == SI_RANDOMIZED_ITEM) ? GetItemMystery() : + Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); EnItem00_CustomItemsParticles(&this->actor, play, getItemEntry); GetItemEntry_Draw(play, getItemEntry); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 185a39c51..98e8f4116 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -214,7 +214,8 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (!IS_RANDO) { GetItem_Draw(play, GID_SKULL_TOKEN_2); } else { - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + getItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_SKULL_TOKEN); EnItem00_CustomItemsParticles(&this->actor, play, getItem); if (getItem.itemId != ITEM_SKULL_TOKEN) { f32 mtxScale = 1.5f; diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index abb65c191..bea2f608f 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -99,8 +99,8 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { } if (IS_RANDO) { - GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id, - play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + GetItemEntry_Draw(play, (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_HEART_CONTAINER_2)); } else { if (flag) { Gfx_SetupDL_25Xlu(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index b12d7b4b0..fb93702ab 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -230,7 +230,8 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { func_8002ED80(&this->actor, play, 0); if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); + RandomizerCheck check = RC_MAX; + GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); //TODO Rando: add mysterious shuffle when chest minigame keys get shuffled EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); if (randoGetItem.itemId != ITEM_NONE) { GetItemEntry_Draw(play, randoGetItem); @@ -249,9 +250,9 @@ void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { if (IS_RANDO) { GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_SUN)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); } else if (type == ITEM_ETC_LETTER) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_UNDERWATER_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); } EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index a9cd36446..c1a0d67ec 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -215,7 +215,7 @@ void ItemOcarina_Draw(Actor* thisx, PlayState* play) { func_8002ED80(thisx, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_HF_OCARINA_OF_TIME_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); GetItemEntry_Draw(play, randoGetItem); return; From 8d3902a256cb07b9f8e65e9ba90b3f0c20c89a45 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 17:27:35 -0700 Subject: [PATCH 227/300] Remove unnecessary and redundant checks and references. (#4111) Stop passing checksByArea to functions in the same namespace. Only get value of `HideFilteredAreas` once per frame. Gate area and check evaluations behind checks being visible and search filter size greater than 0. Proper function capitalization. --- .../randomizer/randomizer_check_tracker.cpp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index a53b838f3..aca75ef93 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -133,8 +133,8 @@ RandomizerCheckArea previousArea = RCAREA_INVALID; RandomizerCheckArea currentArea = RCAREA_INVALID; OSContPad* trackerButtonsPressed; -bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheckObject rcObject); -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); +bool ShouldShowCheck(RandomizerCheckObject rcObject); +bool ShouldHideArea(RandomizerCheckArea rcArea); void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0); bool CompareChecks(RandomizerCheckObject, RandomizerCheckObject); bool CheckByArea(RandomizerCheckArea); @@ -202,6 +202,7 @@ Color_RGBA8 Color_Saved_Extra = { 0, 185, 0, 255 }; // Green std::vector buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT, BTN_L, BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; +static ImGuiTextFilter checkSearch; void DefaultCheckData(RandomizerCheck rc) { gSaveContext.checkTrackerData[rc].status = RCSHOW_UNCHECKED; @@ -930,9 +931,9 @@ void CheckTrackerWindow::DrawElement() { optCollapseAll = true; } ImGui::SameLine(); - static ImGuiTextFilter checkSearch; if (ImGui::Button("Clear")) { checkSearch.Clear(); + doAreaScroll = true; } UIWidgets::Tooltip("Clear the search field"); checkSearch.Draw(); @@ -970,6 +971,8 @@ void CheckTrackerWindow::DrawElement() { Color_RGBA8 extraColor; std::string stemp; + bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); + for (auto& [rcArea, objs] : checksByArea) { RandomizerCheckArea thisArea = currentArea; @@ -983,7 +986,7 @@ void CheckTrackerWindow::DrawElement() { previousShowHidden = showHidden; doAreaScroll = true; } - if (shouldHideArea(checkSearch, checksByArea, rcArea) || + if ((shouldHideFilteredAreas && ShouldHideArea(rcArea)) || (!showHidden && ((hideComplete && thisAreaFullyChecked) || (hideIncomplete && !thisAreaFullyChecked))) ) { doDraw = false; @@ -1046,7 +1049,8 @@ void CheckTrackerWindow::DrawElement() { } for (auto rcObject : objs) { - if (IsVisibleInCheckTracker(rcObject) && passesTextFilter(checkSearch, rcObject) && doDraw && + if (ShouldShowCheck(rcObject) && + doDraw && isThisAreaSpoiled) { DrawLocation(rcObject); } @@ -1067,14 +1071,12 @@ void CheckTrackerWindow::DrawElement() { } } -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { - bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); - if (!shouldHideFilteredAreas) { +bool ShouldHideArea(RandomizerCheckArea rcArea) { + if (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { return false; } - for (auto check : checksByArea[rcArea]) { - if (IsVisibleInCheckTracker(check) && passesTextFilter(checkSearch, check)) { + if (ShouldShowCheck(check)) { return false; } } @@ -1082,10 +1084,12 @@ bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map Date: Mon, 6 May 2024 22:08:11 -0400 Subject: [PATCH 228/300] support lus thread_pool changes (#4127) --- libultraship | 2 +- soh/soh/SaveManager.cpp | 4 ++-- soh/soh/SaveManager.h | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libultraship b/libultraship index a5d84b294..c2555d1cc 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit a5d84b29429dcd9b32fb1d8b169b6dd269e6c979 +Subproject commit c2555d1cca2b7921c5b6790bbf0f6e66fe0433fb diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 0a96f9f19..b6fd0cb07 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1000,7 +1000,7 @@ void SaveManager::SaveSection(int fileNum, int sectionID, bool threaded) { auto saveContext = new SaveContext; memcpy(saveContext, &gSaveContext, sizeof(gSaveContext)); if (threaded) { - smThreadPool->push_task_back(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, sectionID); + smThreadPool->detach_task(std::bind(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, sectionID)); } else { SaveFileThreaded(fileNum, saveContext, sectionID); } @@ -1091,7 +1091,7 @@ void SaveManager::LoadFile(int fileNum) { void SaveManager::ThreadPoolWait() { if (smThreadPool) { - smThreadPool->wait_for_tasks(); + smThreadPool->wait(); } } diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 310ecda7d..817fc6fbf 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -39,7 +39,10 @@ typedef struct { #include #include #include -#include "thread-pool/BS_thread_pool.hpp" + +#define BS_THREAD_POOL_ENABLE_PRIORITY +#define BS_THREAD_POOL_ENABLE_PAUSE +#include #include "z64save.h" From 8e520e490cc4a56d72a67c847842da521e40b233 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 7 May 2024 15:29:17 +0200 Subject: [PATCH 229/300] Spoiler name removal (#3814) * Initial pass * Rename "MK" to "Market" * Remove more spoiler names * Update location_list.cpp * Replace vector with array * Update location_list.cpp * Re-run build * Fix spacing --- soh/soh/Enhancements/randomizer/location.cpp | 155 ++ soh/soh/Enhancements/randomizer/location.h | 118 +- .../Enhancements/randomizer/location_list.cpp | 1676 ++++++++--------- soh/soh/util.cpp | 41 + soh/soh/util.h | 2 + 5 files changed, 1153 insertions(+), 839 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index 24d6ac9cb..ddc9f7fc2 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -108,6 +108,17 @@ Rando::Location Rando::Location::Base(RandomizerCheck rc, RandomizerCheckQuest q isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, + uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Base, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -121,6 +132,19 @@ Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest collectionCheckGroup}; } +Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, + int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + const RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Chest, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, + SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene_, flag_), + collectionCheckGroup}; +} + Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -133,6 +157,18 @@ Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, + int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + const RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Chest, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::Collectable( RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -145,6 +181,18 @@ Rando::Location Rando::Location::Collectable( collectionCheckGroup}; } +Rando::Location Rando::Location::Collectable( + RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, + SpoilerCollectionCheck(SPOILER_CHK_COLLECTABLE, scene_, flag_), + collectionCheckGroup}; +} + Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -160,6 +208,21 @@ Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheck collectionCheckGroup}; } +Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, + const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem, + std::vector&& categories, const uint8_t collectFlag_, + SpoilerCollectionCheckGroup collectionCheckGroup, + bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, + SpoilerCollectionCheck(SPOILER_CHK_COLLECTABLE, scene_, collectFlag_), + collectionCheckGroup}; +} + Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -173,6 +236,19 @@ Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheck isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, + const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, + bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey, @@ -185,6 +261,18 @@ Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQues collectionCheckGroup}; } +Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + std::vector&& categories, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, RCTYPE_SKULL_TOKEN, area_, LocationType::GSToken, ACTOR_EN_SI, scene_, actorParams_, + flag_, std::move(shortName_), hintKey, RG_GOLD_SKULLTULA_TOKEN, + std::move(categories), isVanillaCompletion_, + SpoilerCollectionCheck(SPOILER_CHK_GOLD_SKULLTULA, scene_, flag_), + collectionCheckGroup}; +} + Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey, @@ -197,6 +285,18 @@ Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQues collectionCheckGroup}; } +Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + std::vector&& categories, const uint8_t skullScene_, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, RCTYPE_SKULL_TOKEN, area_, LocationType::GSToken, ACTOR_EN_SI, scene_, actorParams_, + flag_, std::move(shortName_), hintKey, RG_GOLD_SKULLTULA_TOKEN, + std::move(categories), isVanillaCompletion_, + SpoilerCollectionCheck(SPOILER_CHK_GOLD_SKULLTULA, skullScene_, flag_), + collectionCheckGroup}; +} + Rando::Location Rando::Location::GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -210,6 +310,19 @@ Rando::Location Rando::Location::GrottoScrub(RandomizerCheck rc, RandomizerCheck isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, + const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, + bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::GrottoScrub, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -222,6 +335,18 @@ Rando::Location Rando::Location::Delayed(RandomizerCheck rc, RandomizerCheckQues isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + const RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::Delayed, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -234,6 +359,18 @@ Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest isVanillaCompletion_, collectionCheck, collectionCheckGroup}; } +Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, + int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + const RandomizerHintTextKey hintKey, + const RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheck collectionCheck, + SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::TempleReward, actorId_, scene_, actorParams_, flag_, + std::move(shortName_), hintKey, vanillaItem, std::move(categories), + isVanillaCompletion_, collectionCheck, collectionCheckGroup}; +} + Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, @@ -243,6 +380,15 @@ Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQu std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, {}, isVanillaCompletion_}; } +Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, + uint8_t scene_, + std::string&& shortName_, + bool isVanillaCompletion_) { + return {rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, 0x00, 0x00, + std::move(shortName_), RHT_NONE, RG_NONE, {}, isVanillaCompletion_}; +} + Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, @@ -251,3 +397,12 @@ Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQu std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, std::move(categories), isVanillaCompletion_}; } + +Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, + std::vector&& categories, bool isVanillaCompletion_) { + return {rc, quest_, RCTYPE_GOSSIP_STONE, area_, LocationType::Base, ACTOR_EN_GS, scene_, actorParams_, flag_, + std::move(shortName_), RHT_NONE, RG_NONE, std::move(categories), + isVanillaCompletion_}; +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index 1731067cf..bd7f69a8b 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -10,6 +10,7 @@ #include "randomizerTypes.h" #include "z64actor_enum.h" #include "z64scene.h" +#include "../../util.h" namespace Rando { class SpoilerCollectionCheck { @@ -110,6 +111,24 @@ class Location { isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), collectionCheckGroup(collectionCheckGroup_) { } + Location(const RandomizerCheck rc_, const RandomizerCheckQuest quest_, const RandomizerCheckType checkType_, + const RandomizerCheckArea area_, const LocationType locationType_, const ActorID actorId_, const uint8_t scene_, + const int32_t actorParams_, const uint8_t flag_, std::string shortName_, + const RandomizerHintTextKey hintKey_, const RandomizerGet vanillaItem_, std::vector categories_, + const bool isVanillaCompletion_ = false, const SpoilerCollectionCheck collectionCheck_ = SpoilerCollectionCheck(), + const SpoilerCollectionCheckGroup collectionCheckGroup_ = GROUP_NO_GROUP) + : rc(rc_), quest(quest_), checkType(checkType_), area(area_), locationType(locationType_), actorId(actorId_), + scene(scene_), actorParams(actorParams_), flag(flag_), shortName(shortName_), + spoilerName(SpoilerNameFromShortName(shortName_, area_)), hintKey(hintKey_), vanillaItem(vanillaItem_), categories(std::move(categories_)), + isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), + collectionCheckGroup(collectionCheckGroup_) {} + + static std::string SpoilerNameFromShortName(std::string shortName, RandomizerCheckArea area) { + if (area < 0 || area >= RCAREA_INVALID) { + return shortName; + } + return SohUtils::GetRandomizerCheckAreaPrefix(area) + " " + shortName; + } RandomizerCheck GetRandomizerCheck() const; SpoilerCollectionCheck GetCollectionCheck() const; @@ -144,6 +163,15 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, + uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + std::vector&& categories, + SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -152,6 +180,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + std::vector&& categories, + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -160,6 +196,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -168,6 +212,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -176,6 +228,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, std::vector&& categories, uint8_t collectFlag_, + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -185,6 +245,15 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -192,8 +261,15 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = true); + static Location + GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, std::vector&& categories, + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = true); + /// @brief For certain scenes, the sceneId and the "Scene" in spoiler collection check later used to check the - /// GS flags don't necessarily match. Use this constructor for those. scene_ should be the actual scene where + /// GS flags don't necessarily match. Use this constructor (or the next one) for those. scene_ should be the actual scene where /// the GS is located, skullScene_ is the value passed to GET_GS_FLAGS to get the correct skulltula. It is normal /// and expected that these don't always match, and the naming is a holdover from 3drando. /// @param rc @@ -218,6 +294,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = true); + static Location + GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, std::vector&& categories, + uint8_t skullScene_, + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = true); + static Location GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, @@ -227,6 +311,15 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, std::vector&& categories, + SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -235,6 +328,14 @@ class Location { SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, + bool isVanillaCompletion_ = false); + static Location Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, @@ -242,14 +343,29 @@ class Location { std::vector&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location + Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, + ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + std::vector&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), + SpoilerCollectionCheckGroup collectionCheckGroup = GROUP_NO_GROUP, bool isVanillaCompletion_ = false); + static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, std::string&& shortName_, std::string&& spoilerName_, bool isVanillaCompletion_ = false); + static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, + RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, + std::string&& shortName_, bool isVanillaCompletion_ = false); + static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, std::vector&& categories, bool isVanillaCompletion_ = false); + static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene_, + int32_t actorParams_, uint8_t flag_, std::string&& shortName_, + std::vector&& categories, bool isVanillaCompletion_ = false); + private: RandomizerCheck rc; RandomizerCheckQuest quest; diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 92a91f32a..454520d48 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -603,778 +603,778 @@ typedef enum { using namespace Rando; -void Rando::StaticData::InitLocationTable() { // Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression +void Rando::StaticData::InitLocationTable() { // Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // clang-format off - locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); + locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); // Kokiri Forest - locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", "KF Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", "KF Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", "KF Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", "KF Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", "KF Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", "KF Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", "LW Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(22), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", "LW Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", "LW Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(49), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", "LW Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(23), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", "LW Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right", "LW Deku Scrub Near Deku Theater Right", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(22), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(49), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(23), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); // Sacred Forest Meadow - locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", "HF Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", "HF Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", "HF Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", "HF Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", "HF Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); // Lake Hylia - locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", "LH Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", "LH Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", "LH Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", "LH Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", "LH Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", "LH Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", "GV Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", "GV Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", "GV Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_190), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_190), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // RandoTodo: Do we replace these with the RC_HIDEOUT keys or keep these? - locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // Haunted Wasteland - locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", "Wasteland Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", "Wasteland Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Desert Colossus - locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", "Colossus Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Market - locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", "MK Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(27), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_191), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Item", "MK Chest Game First Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Item", "MK Chest Game Second Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Item", "MK Chest Game Third Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Item", "MK Chest Game Fourth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Item", "MK Chest Game Fifth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Key", "MK Chest Game First Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Key", "MK Chest Game Second Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Key", "MK Chest Game Third Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Key", "MK Chest Game Fourth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Key", "MK Chest Game Fifth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(27), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_191), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Hyrule Castle - locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); // Kakariko - locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", "Kak Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", "Kak Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", "Kak 10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", "Kak 20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0E), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", "Kak Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(12), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", "Kak Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(46), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0E), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(12), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(46), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Graveyard - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 21824, 0x00, "Shield Grave Chest", "GY Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", "GY Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", "GY Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", "GY Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", "GY Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x19, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 21824, 0x00, "Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x19, "Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Death Mountain - locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", "DMT Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", "DMT Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", "DMT Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", "DMT Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", "DMT Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", "DMT Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); // Goron City - locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(INFTABLE_11E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DARUNIAS_JOY), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", "GC Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MEDIGORON), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(INFTABLE_11E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DARUNIAS_JOY), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MEDIGORON), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Death Mountain Crater - locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", "DMC Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", "DMC Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", "DMC Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); // Zoras River - locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", "ZR Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", "ZR Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", "ZR Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", "ZR Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", "ZR Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", "ZR Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", "ZR Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", "ZR Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zoras Domain - locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", "ZD Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", "ZD Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", "ZD King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KING_ZORA_THAWED), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", "ZD Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KING_ZORA_THAWED), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Zora's Fountain - locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", "ZF Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", "ZF Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Lon Lon Ranch - locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", "LLR Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(2), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", "LLR Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(2), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); // Dungeons // Deku Tree Vanilla - locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", "Deku Tree Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", "Deku Tree Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", "Deku Tree Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", "Deku Tree Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", "Deku Tree Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", "Deku Tree Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Deku Tree MQ - locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", "Deku Tree MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", "Deku Tree MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", "Deku Tree MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", "Deku Tree MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", "Deku Tree MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Dodongo's Cavern Shared - locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", "Dodongos Cavern Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern Vanilla - locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", "Dodongos Cavern Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", "Dodongos Cavern Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern MQ - locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", "Dodongos Cavern MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Jabu-Jabu's Belly Vanilla - locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", "Jabu Jabus Belly Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", "Jabu Jabus Belly Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", "Jabu Jabus Belly Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); // Jabu-Jabu's Belly MQ - locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", "Jabu Jabus Belly MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", "Jabu Jabus Belly MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", "Jabu Jabus Belly MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", "Jabu Jabus Belly MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", "Jabu Jabus Belly MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", "Jabu Jabus Belly MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", "Jabu Jabus Belly MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", "Jabu Jabus Belly MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); // Forest Temple Vanilla - locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", "Forest Temple First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", "Forest Temple First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", "Forest Temple Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", "Forest Temple Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", "Forest Temple Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", "Forest Temple Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", "Forest Temple Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", "Forest Temple Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", "Forest Temple Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", "Forest Temple Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", "Forest Temple Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", "Forest Temple Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", "Forest Temple Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Forest Temple MQ - locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", "Forest Temple MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", "Forest Temple MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", "Forest Temple MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", "Forest Temple MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", "Forest Temple MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", "Forest Temple MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", "Forest Temple MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", "Forest Temple MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", "Forest Temple MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", "Forest Temple MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", "Forest Temple MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", "Forest Temple MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); // Fire Temple Vanilla - locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", "Fire Temple Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", "Fire Temple Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", "Fire Temple Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", "Fire Temple Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", "Fire Temple Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", "Fire Temple Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", "Fire Temple Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", "Fire Temple Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", "Fire Temple Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", "Fire Temple Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", "Fire Temple Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", "Fire Temple Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", "Fire Temple Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", "Fire Temple Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); // Fire Temple MQ - locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", "Fire Temple MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", "Fire Temple MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", "Fire Temple MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", "Fire Temple MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", "Fire Temple MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", "Fire Temple MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", "Fire Temple MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", "Fire Temple MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", "Fire Temple MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", "Fire Temple MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", "Fire Temple MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", "Fire Temple MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); // Water Temple Vanilla - locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", "Water Temple Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", "Water Temple Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", "Water Temple Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", "Water Temple Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", "Water Temple Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", "Water Temple Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", "Water Temple Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", "Water Temple Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", "Water Temple Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", "Water Temple River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); // Water Temple MQ - locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", "Water Temple MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Water Temple MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", "Water Temple MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Water Temple MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", "Water Temple MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", "Water Temple MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); // Spirit Temple Shared - locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple Vanilla - locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", "Spirit Temple Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", "Spirit Temple Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", "Spirit Temple Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", "Spirit Temple First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", "Spirit Temple First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", "Spirit Temple Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", "Spirit Temple Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", "Spirit Temple Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", "Spirit Temple Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", "Spirit Temple Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", "Spirit Temple Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", "Spirit Temple Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", "Spirit Temple Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", "Spirit Temple Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", "Spirit Temple Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", "Spirit Temple Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple MQ - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", "Spirit Temple MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", "Spirit Temple MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", "Spirit Temple MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", "Spirit Temple MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", "Spirit Temple MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", "Spirit Temple MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", "Spirit Temple MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", "Spirit Temple MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", "Spirit Temple MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", "Spirit Temple MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", "Spirit Temple MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", "Spirit Temple MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", "Spirit Temple MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", "Spirit Temple MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", "Spirit Temple MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", "Spirit Temple MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", "Spirit Temple MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", "Spirit Temple MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Spirit Temple MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", "Spirit Temple MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Shadow Temple Vanilla - locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", "Shadow Temple Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", "Shadow Temple Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", "Shadow Temple Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", "Shadow Temple Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", "Shadow Temple Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", "Shadow Temple Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", "Shadow Temple Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", "Shadow Temple Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", "Shadow Temple Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", "Shadow Temple Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", "Shadow Temple Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", "Shadow Temple After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", "Shadow Temple After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", "Shadow Temple Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", "Shadow Temple Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", "Shadow Temple Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", "Shadow Temple Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); // Shadow Temple MQ - locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Shadow Temple MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", "Shadow Temple MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", "Shadow Temple MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", "Shadow Temple MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", "Shadow Temple MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", "Shadow Temple MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", "Shadow Temple MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", "Shadow Temple MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", "Shadow Temple MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", "Shadow Temple MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", "Shadow Temple MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", "Shadow Temple MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", "Shadow Temple MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", "Shadow Temple MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", "Shadow Temple MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", "Shadow Temple MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", "Shadow Temple MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", "Shadow Temple MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", "Shadow Temple MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", "Shadow Temple MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); // Bottom of the Well Vanilla - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", "Bottom of the Well Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", "Bottom of the Well Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", "Bottom of the Well Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", "Bottom of the Well Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", "Bottom of the Well Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", "Bottom of the Well Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", "Bottom of the Well Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", "Bottom of the Well Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", "Bottom of the Well Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", "Bottom of the Well Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", "Bottom of the Well Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", "Bottom of the Well Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", "Bottom of the Well Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", "Bottom of the Well Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); // Bottom of the Well Master Quest - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", "Bottom of the Well MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", "Bottom of the Well MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", "Bottom of the Well MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", "Bottom of the Well MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", "Bottom of the Well MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); // Ice Cavern Vanilla - locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", "Ice Cavern Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", "Ice Cavern Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", "Ice Cavern Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", "Ice Cavern Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); // Ice Cavern Master Quest - locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", "Ice Cavern MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", "Ice Cavern MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", "Ice Cavern MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", "Ice Cavern MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); // Gerudo Training Grounds Vanilla - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", "Gerudo Training Grounds Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", "Gerudo Training Grounds Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", "Gerudo Training Grounds Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", "Gerudo Training Grounds Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", "Gerudo Training Grounds Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", "Gerudo Training Grounds Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", "Gerudo Training Grounds Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", "Gerudo Training Grounds Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", "Gerudo Training Grounds Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", "Gerudo Training Grounds Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", "Gerudo Training Grounds Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", "Gerudo Training Grounds Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", "Gerudo Training Grounds Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", "Gerudo Training Grounds Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", "Gerudo Training Grounds Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", "Gerudo Training Grounds Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", "Gerudo Training Grounds Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", "Gerudo Training Grounds Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", "Gerudo Training Grounds Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", "Gerudo Training Grounds Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", "Gerudo Training Grounds Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", "Gerudo Training Grounds Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); // Gerudo Training Grounds Master Quest - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", "Gerudo Training Grounds MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", "Gerudo Training Grounds MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", "Gerudo Training Grounds MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", "Gerudo Training Grounds MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", "Gerudo Training Grounds MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", "Gerudo Training Grounds MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", "Gerudo Training Grounds MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", "Gerudo Training Grounds MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", "Gerudo Training Grounds MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", "Gerudo Training Grounds MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", "Gerudo Training Grounds MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", "Gerudo Training Grounds MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", "Gerudo Training Grounds MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", "Gerudo Training Grounds MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", "Gerudo Training Grounds MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", "Gerudo Training Grounds MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); // Ganon's Castle Shared - locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Boss Key Chest", "Ganon's Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); // Ganon's Castle Vanilla - locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", "Ganon's Castle Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", "Ganon's Castle Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", "Ganon's Castle Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", "Ganon's Castle Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", "Ganon's Castle Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", "Ganon's Castle Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", "Ganon's Castle Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", "Ganon's Castle Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", "Ganon's Castle Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Ganon's Castle MQ - locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", "Ganon's Castle MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", "Ganon's Castle MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", "Ganon's Castle MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", "Ganon's Castle MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", "Ganon's Castle MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", "Ganon's Castle MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", "Ganon's Castle MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Gold Skulltula Tokens // Dungeons // Deku Tree - locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", "Deku Tree GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", "Deku Tree GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", "Deku Tree GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", "Deku Tree GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", "Deku Tree MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", "Deku Tree MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", "Deku Tree MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", "Deku Tree MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Dodongo's Cavern - locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", "Dodongos Cavern GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", "Dodongos Cavern GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", "Dodongos Cavern GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", "Dodongos Cavern MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", "Dodongos Cavern MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", "Dodongos Cavern MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", "Dodongos Cavern MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", "Dodongos Cavern MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", "Jabu Jabus Belly GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", "Jabu Jabus Belly GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", "Jabu Jabus Belly GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", "Jabu Jabus Belly GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", "Jabu Jabus Belly MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", "Jabu Jabus Belly MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", "Jabu Jabus Belly MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", "Jabu Jabus Belly MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", "Forest Temple GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", "Forest Temple GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", "Forest Temple GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", "Forest Temple GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", "Forest Temple GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", "Forest Temple MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", "Forest Temple MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", "Forest Temple MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", "Forest Temple MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", "Forest Temple MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Fire Temple - locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", "Fire Temple GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", "Fire Temple GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", "Fire Temple GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", "Fire Temple GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", "Fire Temple GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", "Fire Temple MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", "Fire Temple MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", "Fire Temple MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", "Fire Temple MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", "Fire Temple MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); // Water Temple - locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", "Water Temple GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", "Water Temple GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", "Water Temple GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", "Water Temple GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", "Water Temple GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", "Water Temple MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", "Water Temple MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", "Water Temple MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", "Water Temple MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", "Water Temple MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); // Spirit Temple - locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", "Spirit Temple GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", "Spirit Temple GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", "Spirit Temple GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", "Spirit Temple GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", "Spirit Temple GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", "Spirit Temple MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", "Spirit Temple MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", "Spirit Temple MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", "Spirit Temple MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", "Spirit Temple MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); // Shadow Temple - locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", "Shadow Temple GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", "Shadow Temple GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", "Shadow Temple GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", "Shadow Temple GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", "Shadow Temple GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", "Shadow Temple MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", "Shadow Temple MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", "Shadow Temple MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", "Shadow Temple MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", "Shadow Temple MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); // Bottom of the Well - locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", "Bottom of the Well GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", "Bottom of the Well GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", "Bottom of the Well GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", "Bottom of the Well MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", "Bottom of the Well MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", "Bottom of the Well MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); // Ice Cavern - locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", "Ice Cavern GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", "Ice Cavern GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", "Ice Cavern GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", "Ice Cavern MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", "Ice Cavern MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", "Ice Cavern MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); // Overworld // Kokiri Forest - locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", "KF GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", "KF GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", "KF GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", "LW GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", "LW GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", "SFM GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", "HF GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", "HF GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); // Lake Hylia - locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", "LH GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", "LH GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", "LH GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", "LH GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", "LH GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", "GV GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", "GV GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", "GV GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", "GV GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", "GF GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", "GF GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Wasteland & Desert Colossus - locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", "Wasteland GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", "Colossus GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", "Colossus GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", "Colossus GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Hyrule Castle, Market, and Outside Ganon's Castle - locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, 11777, 0x01, "OGC GS", "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", "HC GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", "HC GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, 11777, 0x01, "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Kakariko - locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", "Kak GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", "Kak GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", "Kak GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", "Kak GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", "Kak GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", "Kak GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Graveyard - locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", "Graveyard GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", "Graveyard GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Death Mountain - locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 28417, 0x01, "GS Bean Patch", "DMC GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, -28800, 0x80, "GS Crate", "DMC GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", "DMT GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", "DMT GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", "DMT GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", "DMT GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", "GC GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", "GC GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 28417, 0x01, "GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, -28800, 0x80, "GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Zora's River, Domain, and Fountain - locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", "ZR GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", "ZR GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", "ZR GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", "ZR GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", "ZD GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", "ZF GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", "ZF GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", "ZF GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Lon Lon Ranch - locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", "LLR GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", "LLR GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", "LLR GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", "LLR GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); // Bosses - locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_NONE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LINKS_POCKET), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0xC9), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); + locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_NONE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LINKS_POCKET), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0xC9), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); // Heart Containers - locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", "Deku Tree Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", "Dodongos Cavern King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", "Jabu Jabus Belly Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", "Forest Temple Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", "Fire Temple Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", "Water Temple Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", "Spirit Temple Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", "Shadow Temple Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); // Cutscenes - locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::EventChkInf(0x45), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::EventChkInf(0xC4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_OGC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::EventChkInf(0x45), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::EventChkInf(0xC4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_OGC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); // Songs - locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x55), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x55), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); //Beehives - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", "KF Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", "LW Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", "LW Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", "LW Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", "SFM Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", "HF Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", "HF Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", "HF Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", "HF Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", "HF Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", "HF Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", "HF Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", "LLR Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", "Kak Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", "Kak Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", "DMT Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", "DMT Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", "DMT Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", "GC Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", "DMC Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", "DMC Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", "DMC Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", "ZR Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", "ZR Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", "ZR Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", "ZD In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", "ZD In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", "ZD Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", "LH Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", "GV Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", "Colossus Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Cows - locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", "KF Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", "HF Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", "LLR Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", "LLR Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", "LLR Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", "LLR Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", "Kak Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", "DMT Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); /*------------------------------- --- SHOPS --- @@ -1383,189 +1383,189 @@ void Rando::StaticData::InitLocationTable() { // 7 5 1 3 -------------------------------*/ // Kokiri Forest - locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", "KF Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", "KF Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", "KF Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", "KF Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", "KF Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", "KF Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", "KF Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", "KF Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Kakariko Village - locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", "Kak Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", "Kak Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", "Kak Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", "Kak Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", "Kak Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", "Kak Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", "Kak Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", "Kak Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", "Kak Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", "Kak Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", "Kak Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", "Kak Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", "Kak Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", "Kak Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", "Kak Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", "Kak Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Market - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", "MK Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", "MK Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", "MK Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", "MK Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", "MK Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", "MK Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", "MK Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", "MK Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", "MK Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", "MK Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", "MK Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", "MK Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", "MK Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", "MK Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", "MK Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", "MK Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", "MK Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", "MK Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", "MK Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", "MK Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", "MK Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", "MK Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", "MK Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", "MK Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - - // Zora's Domain - locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", "ZD Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", "ZD Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", "ZD Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", "ZD Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", "ZD Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", "ZD Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", "ZD Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", "ZD Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - - // Goron City - locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", "GC Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", "GC Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", "GC Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", "GC Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", "GC Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", "GC Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + + // Zora's Domain + locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + + // Goron City + locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); /* +--------------+ | FISHSANITY | +--------------+ */ // Fishing Pond - locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Grotto fish - locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zora's Domain fish - locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Gossip Stones - locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); - locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); - locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); - locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); - locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); - locationTable[RC_GRAVEYARD_GOSSIP_STONE] = Location::HintStone(RC_GRAVEYARD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); - locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); - locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); - locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); - locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); - locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); - locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); - locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); - locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); - locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); - locationTable[RC_ZF_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_ZF_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); - locationTable[RC_ZF_JABU_GOSSIP_STONE] = Location::HintStone(RC_ZF_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); - locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); - locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); + locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", {}); + locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", {}); + locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", {}); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", {}); + locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", {}); + locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", {}); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", {}); + locationTable[RC_GRAVEYARD_GOSSIP_STONE] = Location::HintStone(RC_GRAVEYARD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", {}); + locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", {}); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", {}); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", {}); + locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", {}); + locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", {}); + locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", {}); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", {}); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", {}); + locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", {}); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", {}); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", {}); + locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", {}); + locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", {}); + locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", {}); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", {}); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", {}); + locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", {}); + locationTable[RC_ZF_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_ZF_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", {}); + locationTable[RC_ZF_JABU_GOSSIP_STONE] = Location::HintStone(RC_ZF_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", {}); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", {}); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", {}); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", {}); + locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", {}); + locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", {}); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", {}); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", {}); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", {}); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", {}); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", {}); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", {}); // Other Hints - locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); - locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle"); - locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle"); - locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint"); - locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint"); - locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); - locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text"); - locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text"); - locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint", "Fishing Pole Hint"); - - locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); + locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint"); + locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint"); + locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint"); + locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint"); + locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint"); + locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); + locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Child Altar Hint"); + locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Adult Altar Hint"); + locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint"); + + locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on // Init locationNameToEnum diff --git a/soh/soh/util.cpp b/soh/soh/util.cpp index ceadb8b0e..2e84d2d24 100644 --- a/soh/soh/util.cpp +++ b/soh/soh/util.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include "Enhancements/randomizer/randomizerTypes.h" std::vector sceneNames = { "Inside the Deku Tree", @@ -303,6 +305,41 @@ std::vector questItemNames = { "Gold Skulltula Token", }; +std::array rcareaPrefixes = { + "KF", + "LW", + "SFM", + "HF", + "LH", + "GV", + "GF", + "Wasteland", + "Colossus", + "Market", + "HC", + "Kak", + "Graveyard", + "DMT", + "GC", + "DMC", + "ZR", + "ZD", + "ZF", + "LLR", + "Deku Tree", + "Dodongos Cavern", + "Jabu Jabus Belly", + "Forest Temple", + "Fire Temple", + "Water Temple", + "Spirit Temple", + "Shadow Temple", + "Bottom of the Well", + "Ice Cavern", + "Gerudo Training Grounds", + "Ganon's Castle", +}; + const std::string& SohUtils::GetSceneName(int32_t scene) { return sceneNames[scene]; } @@ -315,6 +352,10 @@ const std::string& SohUtils::GetQuestItemName(int32_t item) { return questItemNames[item]; } +const std::string& SohUtils::GetRandomizerCheckAreaPrefix(int32_t rcarea) { + return rcareaPrefixes[rcarea]; +} + void SohUtils::CopyStringToCharArray(char* destination, std::string source, size_t size) { strncpy(destination, source.c_str(), size - 1); destination[size - 1] = '\0'; diff --git a/soh/soh/util.h b/soh/soh/util.h index 827355862..10619b89a 100644 --- a/soh/soh/util.h +++ b/soh/soh/util.h @@ -9,6 +9,8 @@ namespace SohUtils { const std::string& GetQuestItemName(int32_t item); + const std::string& GetRandomizerCheckAreaPrefix(int32_t rcarea); + // Copies a string and ensures the destination is null terminated if the source string is larger than size // Only up to size-1 characters are copied from the source string void CopyStringToCharArray(char* destination, std::string source, size_t size); From 980b1f1a6e5451459970be6974f6b9847abe9596 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 7 May 2024 18:48:00 +0100 Subject: [PATCH 230/300] Fix an infinite loop in hints and better comment hint distribution (#4080) --- .../Enhancements/randomizer/3drando/hints.cpp | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 1c1edd62d..5973fdcee 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -531,44 +531,40 @@ int32_t getRandomWeight(int32_t totalWeight){ } static void DistributeHints(std::vector& selected, size_t stoneCount, std::vector distTable, uint8_t junkWieght, bool addFixed = true){ - int32_t totalWeight = junkWieght; + int32_t totalWeight = junkWieght; //Start with our Junk Weight, the natural chance of a junk hint - for (HintDistributionSetting setting: distTable){ - totalWeight += setting.weight; + for (HintDistributionSetting setting: distTable){ //Gather the wieghts of each distribution and, if it's the first pass, apply fixed hints + totalWeight += setting.weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them if (addFixed){ selected[setting.type] += setting.fixed; stoneCount -= setting.fixed * setting.copies; } } - int32_t currentWeight = getRandomWeight(totalWeight); - while(stoneCount > 0 && totalWeight > 0){ + int32_t currentWeight = getRandomWeight(totalWeight); //Initialise with the first random weight from 1 to the total. + while(stoneCount > 0 && totalWeight > 0){//Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0 + //and that all weights have been 0'd out for another reason, and skips to placing all junk hints for (uint8_t distribution = 0; distribution < distTable.size(); distribution++){ - currentWeight -= distTable[distribution].weight; - if (currentWeight <= 0){ - if (distTable[distribution].copies == 0) { - // This should only happen if we ran out of locations to place hints of a certain distribution earlier. Skip - // to the next distribution. - break; - } - if (stoneCount >= distTable[distribution].copies){ - selected[distribution] += 1; + currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less, + if (currentWeight <= 0){ //tell the system to make 1 of that hint, unless not enough stones remain + if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0){ + selected[distribution] += 1; //if we have enough stones, and copies are not zero, assign 1 to this hint type, remove the stones, and break stoneCount -= distTable[distribution].copies; - break; - } else { - totalWeight -= distTable[distribution].weight; - distTable[distribution].weight = 0; + break; //This leaves the whole for loop + } else { //If we don't have the stones, or copies is 0 despite there being the wieght to trigger a hit, temporerally set wieght to zero + totalWeight -= distTable[distribution].weight; //Unlike PlaceHint, distTable is passed by value here, making this temporary + distTable[distribution].weight = 0; //this is so we can still roll this hint type if more stones free up later break; } } } - //if there's still weight, then it's junk - if (currentWeight > 0){ + //if there's still weight then it's junk, as the leftover weight is junkWeight + if (currentWeight > 0){ //zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case selected[selected.size()-1] += 1; stoneCount -= 1; } currentWeight = getRandomWeight(totalWeight); } - //if stones are left, assign junk + //if stones are left, assign junk to every remaining stone as a fallback. if (stoneCount > 0){ selected[selected.size()-1] += stoneCount; } @@ -586,10 +582,11 @@ uint8_t PlaceHints(std::vector& selectedHints, RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK; hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name); - if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place + if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place, remove all wieght and copies then return the number of stones to redistribute uint8_t hintsToRemove = (selectedHints[curSlot] - numHint) * distribution.copies; - selectedHints[curSlot] = 0; - distTable[curSlot].copies = 0; + selectedHints[curSlot] = 0; //as distTable is passed by refernce here, these changes stick for the rest of this seed generation + distTable[curSlot].copies = 0;//and prevent future distribution from choosing this slot + distTable[curSlot].weight = 0; return hintsToRemove; } if(Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()){ @@ -661,9 +658,8 @@ void CreateStoneHints() { while(totalStones != 0){ totalStones = PlaceHints(selectedHints, distTable); - while (totalStones != 0){ + if (totalStones != 0){ DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight, false); - totalStones = PlaceHints(selectedHints, distTable); } } From cfd93f160d7cf6d42b22066f9b0d9c2b3454d42c Mon Sep 17 00:00:00 2001 From: Malkierian Date: Tue, 7 May 2024 13:07:33 -0700 Subject: [PATCH 231/300] Fix check tracker performance changes. Move Mysterious Shuffle functionality to `hook_handlers.cpp` when applicable. --- soh/soh/Enhancements/randomizer/draw.h | 2 +- .../Enhancements/randomizer/hook_handlers.cpp | 36 +++++++++++---- soh/soh/Enhancements/randomizer/randomizer.h | 2 +- .../randomizer/randomizer_check_tracker.cpp | 16 ++++--- .../randomizer/randomizer_check_tracker.h | 2 +- soh/soh/OTRGlobals.cpp | 4 +- soh/src/code/z_en_item00.c | 37 +-------------- .../actors/ovl_Demo_Effect/z_demo_effect.c | 38 ++++++++++----- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 46 +------------------ .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 27 +++++------ .../ovl_Item_Etcetera/z_item_etcetera.c | 28 ----------- 11 files changed, 81 insertions(+), 157 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index ea56e6e32..ec390c002 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -24,7 +24,7 @@ void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry); #define GET_ITEM_MYSTERY \ - { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, Randomizer_DrawMysteryItem } + { ITEM_NONE_FE, 0, 0, 0, 0, 0, 0, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, NULL, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem } #ifdef __cplusplus }; #endif diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index db388ae1c..c3669af56 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -33,6 +33,8 @@ extern "C" { #include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" #include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h" #include "adult_trade_shuffle.h" +#include "draw.h" + extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -357,13 +359,21 @@ void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) { void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) { f32 mtxScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 10.0f); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&enItem00->actor, play, enItem00->itemEntry); - GetItemEntry_Draw(play, enItem00->itemEntry); + GetItemEntry randoItem = enItem00->itemEntry; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + randoItem = GET_ITEM_MYSTERY; + } + EnItem00_CustomItemsParticles(&enItem00->actor, play, randoItem); + GetItemEntry_Draw(play, randoItem); } void ItemBHeart_DrawRandomizedItem(ItemBHeart* itemBHeart, PlayState* play) { - EnItem00_CustomItemsParticles(&itemBHeart->actor, play, itemBHeart->sohItemEntry); - GetItemEntry_Draw(play, itemBHeart->sohItemEntry); + GetItemEntry randoItem = itemBHeart->sohItemEntry; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + randoItem = GET_ITEM_MYSTERY; + } + EnItem00_CustomItemsParticles(&itemBHeart->actor, play, randoItem); + GetItemEntry_Draw(play, randoItem); } void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { @@ -378,14 +388,18 @@ void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { } void ItemEtcetera_DrawRandomizedItem(ItemEtcetera* itemEtcetera, PlayState* play) { - EnItem00_CustomItemsParticles(&itemEtcetera->actor, play, itemEtcetera->sohItemEntry); + GetItemEntry randoItem = itemEtcetera->sohItemEntry; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + randoItem = GET_ITEM_MYSTERY; + } + EnItem00_CustomItemsParticles(&itemEtcetera->actor, play, randoItem); func_8002EBCC(&itemEtcetera->actor, play, 0); func_8002ED80(&itemEtcetera->actor, play, 0); - GetItemEntry_Draw(play, itemEtcetera->sohItemEntry); + GetItemEntry_Draw(play, randoItem); } void ItemEtcetera_DrawRandomizedItemThroughLens(ItemEtcetera* itemEtcetera, PlayState* play) { - if (play->actorCtx.lensActive) { + if (play->actorCtx.lensActive) { // todo [Rando] mysterious shuffle for chest minigame key shuffle ItemEtcetera_DrawRandomizedItem(itemEtcetera, play); } } @@ -1160,10 +1174,14 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) { } void EnSi_DrawRandomizedItem(EnSi* enSi, PlayState* play) { + GetItemEntry randoItem = enSi->sohGetItemEntry; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + randoItem = GET_ITEM_MYSTERY; + } func_8002ED80(&enSi->actor, play, 0); func_8002EBCC(&enSi->actor, play, 0); - EnItem00_CustomItemsParticles(&enSi->actor, play, enSi->sohGetItemEntry); - GetItemEntry_Draw(play, enSi->sohGetItemEntry); + EnItem00_CustomItemsParticles(&enSi->actor, play, randoItem); + GetItemEntry_Draw(play, randoItem); } u32 EnDns_RandomizerPurchaseableCheck(EnDns* enDns) { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index acbc3ad7f..3e6df6213 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -11,7 +11,7 @@ #include #include "soh/Enhancements/randomizer/randomizer_check_objects.h" #include "soh/Enhancements/randomizer/randomizer_check_tracker.h" -#include "soh/Enhancements/randomizer/randomizer_tricks.h" +#include "soh/Enhancements/randomizer/tricks.h" #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" #include "../custom-message/CustomMessageTypes.h" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index ace7781be..36263197a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1092,12 +1092,12 @@ bool ShouldHideArea(RandomizerCheckArea rcArea) { return true; } -bool ShouldShowCheck(RandomizerCheckObject check) { +bool ShouldShowCheck(RandomizerCheck check) { return ( IsVisibleInCheckTracker(check) && (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(Rando::StaticData::GetLocation(check)->GetArea()).c_str()) || - checkSearch.PassFilter(Rando::StaticData::GetLocation(check)->GetShortName().c_str()) + checkSearch.PassFilter(Rando::StaticData::GetLocation(check)->GetShortName().c_str())) ); } @@ -1244,7 +1244,7 @@ void LoadSettings() { fishsanityAgeSplit = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT); } -bool IsCheckShuffled(RandomizerCheckObject rcObj) { +bool IsCheckShuffled(RandomizerCheck rc) { Rando::Location* loc = Rando::StaticData::GetLocation(rc); if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { return @@ -1307,8 +1307,10 @@ bool IsCheckShuffled(RandomizerCheckObject rcObj) { return false; } -bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { - return IsCheckShuffled(rcObj) || (rcObj.rcType == RCTYPE_SKULL_TOKEN && alwaysShowGS) || (rcObj.rcType == RCTYPE_SHOP && (showShops && (!hideShopRightChecks))); +bool IsVisibleInCheckTracker(RandomizerCheck rc) { + auto loc = Rando::StaticData::GetLocation(rc); + return IsCheckShuffled(rc) || (loc->GetRCType() == RCTYPE_SKULL_TOKEN && alwaysShowGS) || + (loc->GetRCType() == RCTYPE_SHOP && (showShops && (!hideShopRightChecks))); } void UpdateInventoryChecks() { @@ -1501,7 +1503,7 @@ void DrawLocation(RandomizerCheck rc) { //Draw the extra info txt = ""; - bool mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && OTRGlobals::Instance->gRandomizer->merchantPrices.contains(rcObj.rc); + bool mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && itemLoc->IsAddedToPool(); if (checkData.hintItem != 0) { // TODO hints @@ -1534,7 +1536,7 @@ void DrawLocation(RandomizerCheck rc) { } else if (!mystery) { txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language); } - if (!IsVisibleInCheckTracker(rcObj) && status == RCSHOW_IDENTIFIED && !mystery) { + if (!IsVisibleInCheckTracker(rc) && status == RCSHOW_IDENTIFIED && !mystery) { txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rc].price); } } else { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 576a09cc7..c8915a8ec 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -47,7 +47,7 @@ void DefaultCheckData(RandomizerCheck rc); void Teardown(); void UpdateAllOrdering(); bool IsVisibleInCheckTracker(RandomizerCheck rc); -bool IsCheckShuffled(RandomizerCheck check); +bool IsCheckShuffled(RandomizerCheck rc); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bf248d0e0..42ba48e61 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2445,8 +2445,8 @@ extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck( return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck); } -extern "C" bool Randomizer_IsCheckShuffled(RandomizerCheck randomizerCheck) { - return CheckTracker::IsCheckShuffled(RandomizerCheckObjects::GetAllRCObjects().find(randomizerCheck)->second); +extern "C" bool Randomizer_IsCheckShuffled(RandomizerCheck rc) { + return CheckTracker::IsCheckShuffled(rc); } extern "C" GetItemEntry GetItemMystery() { diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index f286830e6..8e30f462a 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1361,23 +1361,7 @@ static const Vtx customDropVtx[] = { * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). */ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { - if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { - RandomizerCheck randoCheck = - Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); - GetItemEntry giEntry = this->randoGiEntry; - - if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) - ? GetItemMystery() : this->randoGiEntry; - giEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } - - f32 mtxScale = 16.0f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, giEntry); - GetItemEntry_Draw(play, giEntry); - } else if (this->actor.params == ITEM00_BOMBCHU) { + if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -1457,24 +1441,7 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) { * Draw Function used for the Piece of Heart type of En_Item00. */ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { - if (IS_RANDO) { - RandomizerCheck randoCheck = - Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); - GetItemEntry giEntry = this->randoGiEntry; - - if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) - ? GetItemMystery() : this->randoGiEntry; - giEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } - - f32 mtxScale = 16.0f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, giEntry); - GetItemEntry_Draw(play, giEntry); - } else { - s32 pad; + s32 pad; OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 2e06e8975..5984e7eee 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -2089,42 +2089,56 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { } if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { GetItemEntry getItemEntry = GET_ITEM_NONE; - if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_BARINADE)) - getItemEntry = GetItemMystery(); + RandomizerCheck rc = RC_MAX; + RandomizerGet rg = RG_NONE; switch (this->actor.params) { case DEMO_EFFECT_JEWEL_KOKIRI: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD); + rc = RC_QUEEN_GOHMA; + rg = RG_KOKIRI_EMERALD; break; case DEMO_EFFECT_JEWEL_GORON: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY); + rc = RC_KING_DODONGO; + rg = RG_GORON_RUBY; break; case DEMO_EFFECT_JEWEL_ZORA: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + rc = RC_BARINADE; + rg = RG_ZORA_SAPPHIRE; break; case DEMO_EFFECT_MEDAL_FOREST: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION); + rc = RC_PHANTOM_GANON; + rg = RG_FOREST_MEDALLION; break; case DEMO_EFFECT_MEDAL_FIRE: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION); + rc = RC_VOLVAGIA; + rg = RG_FIRE_MEDALLION; break; case DEMO_EFFECT_MEDAL_WATER: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION); + rc = RC_MORPHA; + rg = RG_WATER_MEDALLION; break; case DEMO_EFFECT_MEDAL_SPIRIT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION); + rc = RC_TWINROVA; + rg = RG_SPIRIT_MEDALLION; break; case DEMO_EFFECT_MEDAL_SHADOW: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION); + rc = RC_BONGO_BONGO; + rg = RG_SHADOW_MEDALLION; break; case DEMO_EFFECT_MEDAL_LIGHT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION); + rc = RC_GIFT_FROM_SAGES; + rg = RG_LIGHT_MEDALLION; break; case DEMO_EFFECT_LIGHTARROW: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS); + rc = RC_TOT_LIGHT_ARROWS_CUTSCENE; + rg = RG_LIGHT_ARROWS; break; } + getItemEntry = Randomizer_GetItemFromKnownCheck(rc, rg); if (getItemEntry.getItemId != GI_NONE) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(rc)) { + getItemEntry = GetItemMystery(); + } this->getItem.drawId = getItemEntry.gid; func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index bf0e4951d..170eed16e 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -155,50 +155,6 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (this->actionFunc != func_80AFB950) { func_8002ED80(&this->actor, play, 0); func_8002EBCC(&this->actor, play, 0); - if (!IS_RANDO) { - GetItem_Draw(play, GID_SKULL_TOKEN_2); - } else { - RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); - getItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_SKULL_TOKEN); - EnItem00_CustomItemsParticles(&this->actor, play, getItem); - if (getItem.itemId != ITEM_SKULL_TOKEN) { - f32 mtxScale = 1.5f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - } - GetItemEntry_Draw(play, getItem); - } - } -} - -void EnSi_Reset() { - textId = 0xB4; - giveItemId = ITEM_SKULL_TOKEN; -} - -void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); - getItemId = getItem.getItemId; - if (getItemId == RG_ICE_TRAP) { - textId = 0xF8; - } else { - textId = getItem.textId; - giveItemId = getItem.itemId; - } - player->getItemEntry = getItem; -} - -void Randomizer_GiveSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - if (getItem.modIndex == MOD_NONE) { - // RANDOTOD: Move this into Item_Give() or some other more central location - if (getItem.getItemId == GI_SWORD_BGS) { - gSaveContext.bgsFlag = true; - } - Item_Give(play, giveItemId); - } else if (getItem.modIndex == MOD_RANDOMIZER) { - Randomizer_Item_Give(play, getItem); + GetItem_Draw(play, GID_SKULL_TOKEN_2); } } diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index 02656e119..29efb832c 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -93,23 +93,18 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { actorIt = actorIt->next; } - if (IS_RANDO) { - RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); - GetItemEntry_Draw(play, (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_HEART_CONTAINER_2)); + if (flag) { + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); } else { - if (flag) { - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); - } else { - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); - } + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index d27893c3a..cc1f31aa0 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -206,16 +206,6 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { if (play->actorCtx.lensActive) { func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); - - if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - RandomizerCheck check = RC_MAX; - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); //TODO Rando: add mysterious shuffle when chest minigame keys get shuffled - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - if (randoGetItem.itemId != ITEM_NONE) { - GetItemEntry_Draw(play, randoGetItem); - return; - } - } GetItem_Draw(play, this->giDrawId); } @@ -225,24 +215,6 @@ void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; s32 type = this->actor.params & 0xFF; - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_SUN)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); - } else if (type == ITEM_ETC_LETTER) { - randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_UNDERWATER_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); - } - - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - - if (randoGetItem.itemId != ITEM_NONE) { - func_8002EBCC(&this->actor, play, 0); - func_8002ED80(&this->actor, play, 0); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); GetItem_Draw(play, this->giDrawId); From 0976198f2c4c47ba35ce4a2886085a7bc4c5c2bc Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 8 May 2024 00:13:47 -0400 Subject: [PATCH 232/300] get soh working with latest lus (#4132) --- libultraship | 2 +- soh/include/functions.h | 2 - soh/soh/Enhancements/debugger/colViewer.cpp | 6 +- soh/soh/stubs.c | 93 +-------------------- 4 files changed, 5 insertions(+), 98 deletions(-) diff --git a/libultraship b/libultraship index c2555d1cc..97b11c960 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit c2555d1cca2b7921c5b6790bbf0f6e66fe0433fb +Subproject commit 97b11c9601178ff02e141b7398f5d50ddf91fdc4 diff --git a/soh/include/functions.h b/soh/include/functions.h index 08179b341..b9e1f6981 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2354,7 +2354,6 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check); s32 __osGetId(OSPfs* pfs); s32 __osCheckId(OSPfs* pfs); s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank); -void guMtxL2F(MtxF* m1, Mtx* m2); s32 osPfsFindFile(OSPfs* pfs, u16 companyCode, u32 gameCode, u8* gameName, u8* extName, s32* fileNo); s32 osAfterPreNMI(void); s32 osContStartQuery(OSMesgQueue* mq); @@ -2408,7 +2407,6 @@ u32 __osSpGetStatus(void); void __osSpSetStatus(u32 status); void osWritebackDCacheAll(void); OSThread* __osGetCurrFaultedThread(void); -void guMtxF2L(MtxF* m1, Mtx* m2); // ? __d_to_ll(?); // ? __f_to_ll(?); // ? __d_to_ull(?); diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index 159e27128..da6e73630 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -445,7 +445,7 @@ void DrawBgActorCollision() { bg.curTransform.scale.z, bg.curTransform.rot.x, bg.curTransform.rot.y, bg.curTransform.rot.z, bg.curTransform.pos.x, bg.curTransform.pos.y, bg.curTransform.pos.z); - guMtxF2L(&mf, &m); + // guMtxF2L(mf, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); @@ -493,7 +493,7 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { SkinMatrix_SetScale(&ms, radius / 128.0f, radius / 128.0f, radius / 128.0f); MtxF dest; SkinMatrix_MtxFMtxFMult(&mf, &ms, &dest); - guMtxF2L(&dest, &m); + // guMtxF2L(&dest, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); @@ -512,7 +512,7 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { SkinMatrix_SetScale(&ms, radius / 128.0f, cyl->dim.height / 128.0f, radius / 128.0f); MtxF dest; SkinMatrix_MtxFMtxFMult(&mt, &ms, &dest); - guMtxF2L(&dest, &m); + // guMtxF2L(&dest, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); diff --git a/soh/soh/stubs.c b/soh/soh/stubs.c index a162a7ac5..63340734e 100644 --- a/soh/soh/stubs.c +++ b/soh/soh/stubs.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "z64.h" @@ -31,18 +32,6 @@ f32 qNaN0x10000 = 0x7F810000; // __gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy); //} -s32 osJamMesg(OSMesgQueue* mq, OSMesg msg, s32 flag) -{ -} - -void osSetEventMesg(OSEvent e, OSMesgQueue* mq, OSMesg msg) -{ -} - -void osViSetEvent(OSMesgQueue* mq, OSMesg msg, u32 retraceCount) -{ -} - OSId osGetThreadId(OSThread* thread) { } @@ -55,31 +44,11 @@ void osSetThreadPri(OSThread* thread, OSPri pri) { } -s32 osSetTimer(OSTimer* timer, OSTime countdown, OSTime interval, OSMesgQueue* mq, OSMesg msg) -{ - -} - void osCreatePiManager(OSPri pri, OSMesgQueue* cmdQ, OSMesg* cmdBuf, s32 cmdMsgCnt) { } -void osCreateViManager(OSPri pri) -{ - -} - -s32 osMotorInit(OSMesgQueue* ctrlrqueue, OSPfs* pfs, s32 channel) -{ - return 0; -} - -u32 osAiGetLength(void) -{ - -} - s32 osPfsFreeBlocks(OSPfs* pfs, s32* leftoverBytes) { @@ -130,16 +99,6 @@ s32 osPfsAllocateFile(OSPfs* pfs, u16 companyCode, u32 gameCode, u8* gameName, u } -s32 osAiSetNextBuffer(void* buf, size_t size) -{ - -} - -s32 __osMotorAccess(OSPfs* pfs, u32 vibrate) -{ - -} - OSIntMask osSetIntMask(OSIntMask a) { return 0; @@ -200,16 +159,6 @@ void osContGetQuery(OSContStatus* data) } -void osViSwapBuffer(void* vaddr) -{ - -} - -void* osViGetNextFramebuffer() -{ - -} - u32 __osGetFpcCsr() { return 0; @@ -240,11 +189,6 @@ OSThread* __osGetCurrFaultedThread(void) } -void osCartRomInit() -{ - -} - u32 osMemSize = 1024 * 1024 * 1024; void Audio_osInvalDCache(void* buf, s32 size) @@ -263,11 +207,6 @@ s32 osAiSetFrequency(u32 freq) return 1; } -s32 osEPiStartDma(OSPiHandle* handle, OSIoMesg* mb, s32 direction) -{ - -} - void osInvalDCache(void* vaddr, s32 nbytes) { @@ -313,31 +252,6 @@ OSPiHandle* osDriveRomInit() } -void osViSetMode(OSViMode* mode) -{ - -} - -void osViBlack(u8 active) -{ - -} - -void osViSetYScale(f32 scale) -{ - -} - -void osViSetXScale(f32 value) -{ - -} - -void osViSetSpecialFeatures(u32 func) -{ - -} - void __osInitialize_common(void) { @@ -390,11 +304,6 @@ s32 osEPiReadIo(OSPiHandle* handle, u32 devAddr, u32* data) return 0; } -u32* osViGetCurrentFramebuffer(void) -{ - -} - void osSpTaskYield(void) { } From 3c87c1ec98113d4da11c5d08d5a208ab982ba6f1 Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Wed, 8 May 2024 02:25:50 -0400 Subject: [PATCH 233/300] Lus window bump (#4131) --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 27 ++++++++++++++++++--------- soh/soh/SohMenuBar.cpp | 1 + soh/src/code/graph.c | 6 ++++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/libultraship b/libultraship index 97b11c960..61e304d21 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 97b11c9601178ff02e141b7398f5d50ddf91fdc4 +Subproject commit 61e304d21fe00b5b1de49998b16c510615ad7b44 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 518e9c1f3..12f94e5fd 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -7,6 +7,7 @@ #include #include +#include "graphic/Fast3D/Fast3dWindow.h" #include #include #include @@ -1253,11 +1254,6 @@ extern "C" uint64_t GetUnixTimestamp() { return (uint64_t)millis.count(); } -// C->C++ Bridge -extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) { - OTRGlobals::Instance->context->GetWindow()->MainLoop(run_one_game_iter); -} - extern bool ToggleAltAssetsAtEndOfFrame; extern "C" void Graph_StartFrame() { @@ -1381,6 +1377,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { static int time; int fps = target_fps; int original_fps = 60 / R_UPDATE_RATE; + auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); if (target_fps == 20 || original_fps > target_fps) { fps = original_fps; @@ -1404,10 +1401,12 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { time -= fps; - OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps); + if (wnd != nullptr) { + wnd->SetTargetFps(fps); + } int threshold = CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80); - OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); + wnd->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); RunCommands(commands, mtx_replacements); @@ -1440,11 +1439,21 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { float divisor_num = 0.0f; extern "C" void OTRGetPixelDepthPrepare(float x, float y) { - OTRGlobals::Instance->context->GetWindow()->GetPixelDepthPrepare(x, y); + auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); + if (wnd == nullptr) { + return; + } + + wnd->GetPixelDepthPrepare(x, y); } extern "C" uint16_t OTRGetPixelDepth(float x, float y) { - return OTRGlobals::Instance->context->GetWindow()->GetPixelDepth(x, y); + auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); + if (wnd == nullptr) { + return 0; + } + + return wnd->GetPixelDepth(x, y); } extern "C" uint32_t ResourceMgr_GetNumGameVersions() { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 35274e5ac..f60983c59 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -8,6 +8,7 @@ #include #include "UIWidgets.hpp" #include "include/z64audio.h" +#include "graphic/Fast3D/gfx_rendering_api.h" #include "OTRGlobals.h" #include "z64.h" #include "Enhancements/game-interactor/GameInteractor.h" diff --git a/soh/src/code/graph.c b/soh/src/code/graph.c index f5d620e72..db0e8bca3 100644 --- a/soh/src/code/graph.c +++ b/soh/src/code/graph.c @@ -10,6 +10,7 @@ #include "soh/Enhancements/debugger/valueViewer.h" #include "soh/Enhancements/gameconsole.h" #include "soh/OTRGlobals.h" +#include "libultraship/bridge.h" #define GFXPOOL_HEAD_MAGIC 0x1234 #define GFXPOOL_TAIL_MAGIC 0x5678 @@ -541,8 +542,9 @@ static void RunFrame() } void Graph_ThreadEntry(void* arg0) { - - Graph_ProcessFrame(RunFrame); + while (WindowIsRunning()) { + RunFrame(); + } } void* Graph_Alloc(GraphicsContext* gfxCtx, size_t size) { From 22c9d53985dbee674b06a6241f1c3a29b6a89c23 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Wed, 8 May 2024 11:23:43 -0400 Subject: [PATCH 234/300] bump lus (gfx debugger fix, stormlib optimizations) (#4135) --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index 61e304d21..878efcc26 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 61e304d21fe00b5b1de49998b16c510615ad7b44 +Subproject commit 878efcc26701f1779e06389a6c6ca8df7aef64da From 1231b8f9fa71ddf681b0f5599f2cf8d127c4546e Mon Sep 17 00:00:00 2001 From: Lywx Date: Wed, 8 May 2024 17:30:22 -0600 Subject: [PATCH 235/300] Fixed macos/ios errors (#4138) --- soh/CMakeLists.txt | 1 + soh/src/overlays/actors/ovl_player_actor/z_player.c | 2 +- soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index f8ee476b8..3f086bcac 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -547,6 +547,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") -Wno-parentheses -Wno-narrowing -Wno-missing-braces + -Wno-int-conversion $<$: -Werror-implicit-function-declaration -Wno-incompatible-pointer-types diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index f1dd52d6e..145da2f99 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6266,7 +6266,7 @@ s32 func_8083D12C(PlayState* play, Player* this, Input* arg2) { func_80832340(play, this); // Skip take breath animation on surface if Link didn't grab an item while underwater and the setting is enabled if (CVarGetInteger(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 0) && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { - auto lastAnimFrame = Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_deep_end); + int lastAnimFrame = Animation_GetLastFrame(&gPlayerAnim_link_swimer_swim_deep_end); LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_swimer_swim_deep_end, 1.0f, lastAnimFrame, lastAnimFrame, ANIMMODE_ONCE, -6.0f); } else { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 6cc02aa03..83b734156 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -141,7 +141,7 @@ static Vtx sCycleAButtonVtx[] = { }; // Track animation timers for each inventory slot -static sSlotCycleActiveAnimTimer[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static int sSlotCycleActiveAnimTimer[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Renders a left and/or right item for any item slot that can support cycling void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 canCycle, u8 leftItem, u8 rightItem) { From 3bcf178fcc7916a27a27fd6100871a9e53e43e66 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 8 May 2024 20:24:44 -0700 Subject: [PATCH 236/300] Fix LUS ref. --- libultraship | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship b/libultraship index 7d71a2906..a5d84b294 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 7d71a290657a2d3b09a83e8b33025e807f4fb38e +Subproject commit a5d84b29429dcd9b32fb1d8b169b6dd269e6c979 From cbeec006ecb4eeb34017282a4dfc5957a9aee642 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 9 May 2024 00:32:29 -0400 Subject: [PATCH 237/300] Fix syotes scene path to use shared (#4136) --- .../{nonmq => shared}/syotes_scene/syotes_room_0 | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename soh/assets/custom/scenes/{nonmq => shared}/syotes_scene/syotes_room_0 (100%) diff --git a/soh/assets/custom/scenes/nonmq/syotes_scene/syotes_room_0 b/soh/assets/custom/scenes/shared/syotes_scene/syotes_room_0 similarity index 100% rename from soh/assets/custom/scenes/nonmq/syotes_scene/syotes_room_0 rename to soh/assets/custom/scenes/shared/syotes_scene/syotes_room_0 From 47b690fb1e3cfbd5dad5cb948c46ea72794c18a7 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 9 May 2024 01:26:58 -0400 Subject: [PATCH 238/300] Bump LUS and restore guMtx in collision viewer (#4137) --- libultraship | 2 +- soh/soh/Enhancements/debugger/colViewer.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libultraship b/libultraship index 878efcc26..0da318c0f 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 878efcc26701f1779e06389a6c6ca8df7aef64da +Subproject commit 0da318c0f4e431313565cad546fc469b8e850388 diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index da6e73630..3b5b7aa47 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -445,7 +445,7 @@ void DrawBgActorCollision() { bg.curTransform.scale.z, bg.curTransform.rot.x, bg.curTransform.rot.y, bg.curTransform.rot.z, bg.curTransform.pos.x, bg.curTransform.pos.y, bg.curTransform.pos.z); - // guMtxF2L(mf, &m); + guMtxF2L(mf.mf, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); @@ -493,7 +493,7 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { SkinMatrix_SetScale(&ms, radius / 128.0f, radius / 128.0f, radius / 128.0f); MtxF dest; SkinMatrix_MtxFMtxFMult(&mf, &ms, &dest); - // guMtxF2L(&dest, &m); + guMtxF2L(dest.mf, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); @@ -512,7 +512,7 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { SkinMatrix_SetScale(&ms, radius / 128.0f, cyl->dim.height / 128.0f, radius / 128.0f); MtxF dest; SkinMatrix_MtxFMtxFMult(&mt, &ms, &dest); - // guMtxF2L(&dest, &m); + guMtxF2L(dest.mf, &m); mtxDl.push_back(m); dl.push_back(gsSPMatrix(&mtxDl.back(), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH)); From ca803099cfcdba5c92569c0f19fcaf41cbad92a4 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 9 May 2024 13:22:39 +0100 Subject: [PATCH 239/300] Fix DistributeHints (#4145) * fix stupid crash in DistributeHints * replace some uint8s in loops with size --- soh/soh/Enhancements/randomizer/3drando/hints.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 5973fdcee..1f195251b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -533,17 +533,17 @@ int32_t getRandomWeight(int32_t totalWeight){ static void DistributeHints(std::vector& selected, size_t stoneCount, std::vector distTable, uint8_t junkWieght, bool addFixed = true){ int32_t totalWeight = junkWieght; //Start with our Junk Weight, the natural chance of a junk hint - for (HintDistributionSetting setting: distTable){ //Gather the wieghts of each distribution and, if it's the first pass, apply fixed hints - totalWeight += setting.weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them + for (size_t c=0; c < distTable.size(); c++){ //Gather the wieghts of each distribution and, if it's the first pass, apply fixed hints + totalWeight += distTable[c].weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them if (addFixed){ - selected[setting.type] += setting.fixed; - stoneCount -= setting.fixed * setting.copies; + selected[c] += distTable[c].fixed; + stoneCount -= distTable[c].fixed * distTable[c].copies; } } int32_t currentWeight = getRandomWeight(totalWeight); //Initialise with the first random weight from 1 to the total. while(stoneCount > 0 && totalWeight > 0){//Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0 //and that all weights have been 0'd out for another reason, and skips to placing all junk hints - for (uint8_t distribution = 0; distribution < distTable.size(); distribution++){ + for (size_t distribution = 0; distribution < distTable.size(); distribution++){ currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less, if (currentWeight <= 0){ //tell the system to make 1 of that hint, unless not enough stones remain if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0){ @@ -650,7 +650,7 @@ void CreateStoneHints() { size_t totalStones = GetEmptyGossipStones().size(); std::vector selectedHints = {}; - for (uint8_t c=0; c < distTable.size(); c++){ + for (size_t c=0; c < distTable.size(); c++){ selectedHints.push_back(0); } selectedHints.push_back(0); @@ -672,7 +672,7 @@ void CreateStoneHints() { std::vector FindItemsAndMarkHinted(std::vector items, std::vector hintChecks){ std::vector locations = {}; auto ctx = Rando::Context::GetInstance(); - for (uint8_t c = 0; c < items.size(); c++){ + for (size_t c = 0; c < items.size(); c++){ std::vector found = FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) { return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];}); if (found.size() > 0){ From 1d5a54901bca5a4f18f793091354b91e00196ec1 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 9 May 2024 09:45:13 -0700 Subject: [PATCH 240/300] Add MSI to EnEx hook handler. Resolve other review suggestions. --- .../Enhancements/randomizer/hook_handlers.cpp | 8 +++-- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 35 +------------------ .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 4 +-- .../ovl_Item_Etcetera/z_item_etcetera.c | 2 -- 4 files changed, 9 insertions(+), 40 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index c3669af56..3f15ce4c8 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -333,9 +333,13 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { } void EnExItem_DrawRandomizedItem(EnExItem* enExItem, PlayState* play) { + GetItemEntry randoGetItem = enExItem->sohItemEntry; + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + randoGetItem = GET_ITEM_MYSTERY; + } func_8002ED80(&enExItem->actor, play, 0); - EnItem00_CustomItemsParticles(&enExItem->actor, play, enExItem->sohItemEntry); - GetItemEntry_Draw(play, enExItem->sohItemEntry); + EnItem00_CustomItemsParticles(&enExItem->actor, play, randoGetItem); + GetItemEntry_Draw(play, randoGetItem); } void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 26116664a..0b3d69f3c 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -487,46 +487,13 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { } if (this) {} func_8002ED80(&this->actor, play, 0); - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - switch (this->type) { - case EXITEM_BOMB_BAG_BOWLING: - case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE)) - ? GetItemMystery() - : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); - break; - case EXITEM_BOMBCHUS_BOWLING: - case EXITEM_BOMBCHUS_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); - break; - case EXITEM_BULLET_BAG: - randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LW_TARGET_IN_WOODS)) - ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - break; - } - - if (randoGetItem.getItemId != GI_NONE) { - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } GetItem_Draw(play, this->giDrawId); } void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); - - if (IS_RANDO) { - GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE)) - ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - } else { - GetItem_Draw(play, GID_HEART_PIECE); - } + GetItem_Draw(play, GID_HEART_PIECE); } void EnExItem_DrawMagic(EnExItem* this, PlayState* play, s16 magicIndex) { diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index 29efb832c..5015a3908 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -96,13 +96,13 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { if (flag) { Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); } else { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); } diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index cc1f31aa0..796b157a3 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -206,14 +206,12 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { if (play->actorCtx.lensActive) { func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); - GetItem_Draw(play, this->giDrawId); } } void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; - s32 type = this->actor.params & 0xFF; func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); From 3f67fed073f7848aadac96a99ace85d7d8f5db5b Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 9 May 2024 21:39:13 -0400 Subject: [PATCH 241/300] Fix some memory leaks with WrappedText and LoadArrayByNameAsVec3s (#4144) * avoid memory leaks with WrappedText * avoid memory leak with LoadArrayByNameAsVec3s --- .../Enhancements/debugger/debugSaveEditor.cpp | 2 +- soh/soh/OTRGlobals.cpp | 1 + soh/soh/UIWidgets.cpp | 16 ++++++++-------- soh/soh/UIWidgets.hpp | 4 ++-- soh/src/code/z_player_lib.c | 2 ++ 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 9af4eadb7..91eab6db5 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -782,7 +782,7 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl ImGui::PopStyleColor(); if (ImGui::IsItemHovered() && hasDescription) { ImGui::BeginTooltip(); - ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60)); + ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60).c_str()); ImGui::EndTooltip(); } ImGui::PopID(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 64d70da88..bb45fdba7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1735,6 +1735,7 @@ extern "C" char* ResourceMgr_LoadArrayByName(const char* path) return (char*)res->Scalars.data(); } +// Return of LoadArrayByNameAsVec3s must be freed by the caller extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) { auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 15bb088a3..06eaa33cd 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -21,7 +21,7 @@ namespace UIWidgets { // Automatically adds newlines to break up text longer than a specified number of characters // Manually included newlines will still be respected and reset the line length // If line is midword when it hits the limit, text should break at the last encountered space - char* WrappedText(const char* text, unsigned int charactersPerLine) { + std::string WrappedText(const char* text, unsigned int charactersPerLine) { std::string newText(text); const size_t tipLength = newText.length(); int lastSpace = -1; @@ -43,17 +43,17 @@ namespace UIWidgets { currentLineLength++; } - return strdup(newText.c_str()); + return newText; } - char* WrappedText(const std::string& text, unsigned int charactersPerLine) { + std::string WrappedText(const std::string& text, unsigned int charactersPerLine) { return WrappedText(text.c_str(), charactersPerLine); } void SetLastItemHoverText(const std::string& text) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -61,7 +61,7 @@ namespace UIWidgets { void SetLastItemHoverText(const char* text) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -72,7 +72,7 @@ namespace UIWidgets { ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -82,7 +82,7 @@ namespace UIWidgets { ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -92,7 +92,7 @@ namespace UIWidgets { void Tooltip(const char* text) { if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("%s", WrappedText(text)); + ImGui::SetTooltip("%s", WrappedText(text).c_str()); } } diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index b18487977..3c4622bc8 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -50,8 +50,8 @@ namespace UIWidgets { constexpr float sliderButtonWidth = 30.0f; #endif - char* WrappedText(const char* text, unsigned int charactersPerLine = 60); - char* WrappedText(const std::string& text, unsigned int charactersPerLine); + std::string WrappedText(const char* text, unsigned int charactersPerLine = 60); + std::string WrappedText(const std::string& text, unsigned int charactersPerLine); void SetLastItemHoverText(const std::string& text); void SetLastItemHoverText(const char* text); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 820f2c672..ee7fd3f53 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -2307,10 +2307,12 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* } srcTable = ResourceMgr_LoadArrayByNameAsVec3s(srcTable); + Vec3s* ogSrcTable = srcTable; destTable = skelAnime->jointTable; for (i = 0; i < skelAnime->limbCount; i++) { *destTable++ = *srcTable++; } + free(ogSrcTable); } From 5530ce2e61c2566eff1988bebdabfb3c70b1b2b7 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 9 May 2024 21:45:21 -0400 Subject: [PATCH 242/300] simplify ci (#4129) --- .github/workflows/generate-builds.yml | 100 +++++++------------------- .github/workflows/gtar | 2 +- 2 files changed, 26 insertions(+), 76 deletions(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 5c1930ede..ec0676de8 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: true jobs: generate-soh-otr: - runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: @@ -20,7 +20,6 @@ jobs: ${{ runner.os }}-otr-ccache-${{ github.ref }} ${{ runner.os }}-otr-ccache- - name: Install dependencies - if: ${{ !vars.LINUX_RUNNER }} run: | sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) @@ -35,7 +34,6 @@ jobs: build-cmake SDL2-2.28.5 - name: Install latest SDL - if: ${{ !vars.LINUX_RUNNER }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2-2.28.5" ]; then @@ -73,47 +71,44 @@ jobs: retention-days: 1 build-macos: needs: generate-soh-otr - runs-on: ${{ (vars.MAC_RUNNER && fromJSON(vars.MAC_RUNNER)) || 'macos-12' }} + runs-on: macos-14 steps: - uses: actions/checkout@v3 with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.11 + uses: hendrikmuhs/ccache-action@v1.2.13 with: - key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }} + create-symlink: true + key: ${{ runner.os }}-14-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache-${{ github.ref }} - ${{ runner.os }}-ccache- + ${{ runner.os }}-14-ccache-${{ github.ref }} + ${{ runner.os }}-14-ccache- - name: Install gtar wrapper - if: ${{ !vars.MAC_RUNNER }} run: | - sudo mv /usr/local/bin/gtar /usr/local/bin/gtar.orig - sudo cp .github/workflows//gtar /usr/local/bin/gtar - sudo chmod +x /usr/local/bin/gtar + sudo mv /opt/homebrew/bin/gtar /opt/homebrew/bin/gtar.orig + sudo cp .github/workflows//gtar /opt/homebrew/bin/gtar + sudo chmod +x /opt/homebrew/bin/gtar - name: Cache MacPorts id: cache-macports - if: ${{ !vars.MAC_RUNNER }} uses: actions/cache@v2 with: path: /opt/local/ - key: ${{ runner.os }}-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }} + key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }} restore-keys: | - ${{ runner.os }}-macports- + ${{ runner.os }}-14-macports- - name: Install MacPorts (if necessary) - if: ${{ !vars.MAC_RUNNER }} run: | if [ -d /opt/local/ ]; then echo "MacPorts already installed" else - wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-12-Monterey.pkg - sudo installer -pkg ./MacPorts-2.9.3-12-Monterey.pkg -target / + wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg + sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target / fi echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH - name: Install dependencies - if: ${{ !vars.MAC_RUNNER }} run: | - brew uninstall --ignore-dependencies libpng libzip + brew uninstall --ignore-dependencies libpng sudo port install $(cat .github/workflows/macports-deps.txt) brew install ninja - name: Download soh.otr @@ -122,7 +117,6 @@ jobs: name: soh.otr - name: Build SoH run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DBUILD_REMOTE_CONTROL=1 cmake --build build-cmake --config Release --parallel 10 mv soh.otr build-cmake/soh @@ -139,45 +133,33 @@ jobs: readme.txt build-linux: needs: generate-soh-otr - strategy: - fail-fast: true - matrix: - include: - - os: ubuntu-20.04 - gcc: 10 - archive-suffix: compatibility - - os: ubuntu-22.04 - gcc: 12 - archive-suffix: performance - runs-on: ${{ (matrix.os == 'ubuntu-20.04' && ((vars.LINUX_COMPATIBILITY_RUNNER && fromJSON(vars.LINUX_COMPATIBILITY_RUNNER)) || matrix.os)) || (matrix.os == 'ubuntu-22.04' && ((vars.LINUX_PERFORMANCE_RUNNER && fromJSON(vars.LINUX_PERFORMANCE_RUNNER)) || matrix.os)) }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: submodules: true - name: Install dependencies - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) - name: ccache uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ matrix.os }}-ccache-${{ github.ref }}-${{ github.sha }} + key: linux-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ matrix.os }}-ccache-${{ github.ref }} - ${{ matrix.os }}-ccache- + linux-ccache-${{ github.ref }} + linux-ccache- - name: Cache build folders uses: actions/cache@v4 with: - key: ${{ matrix.os }}-build-${{ github.ref }}-${{ github.sha }} + key: linux-build-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ matrix.os }}-build-${{ github.ref }} - ${{ matrix.os }}-build- + linux-build-${{ github.ref }} + linux-build- path: | SDL2-2.28.5 SDL2_net-2.2.0 - name: Install latest SDL - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2-2.28.5" ]; then @@ -189,38 +171,7 @@ jobs: make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ - - name: Install latest libzip - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} - run: | - sudo apt-get remove libzip-dev zipcmp zipmerge ziptool - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "libzip-1.10.1" ]; then - wget https://libzip.org/download/libzip-1.10.1.tar.gz - tar -xzvf libzip-1.10.1.tar.gz - fi - cd libzip-1.10.1 - mkdir build - cd build - cmake .. - make - sudo make install - - name: Install latest nlohmann - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} - run: | - sudo apt-get remove nlohmann-json3-dev - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "json-3.11.3" ]; then - wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz - tar -xzvf v3.11.3.tar.gz - fi - cd json-3.11.3 - mkdir build - cd build - cmake .. - make - sudo make install - name: Install latest tinyxml2 - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | sudo apt-get remove libtinyxml2-dev export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" @@ -235,7 +186,6 @@ jobs: make sudo make install - name: Install latest SDL_net - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2_net-2.2.0" ]; then @@ -261,12 +211,12 @@ jobs: mv README.md readme.txt mv build-cmake/*.appimage soh.appimage env: - CC: gcc-${{ matrix.gcc }} - CXX: g++-${{ matrix.gcc }} + CC: gcc-12 + CXX: g++-12 - name: Upload build uses: actions/upload-artifact@v4 with: - name: soh-linux-${{ matrix.archive-suffix }} + name: soh-linux path: | soh.appimage readme.txt diff --git a/.github/workflows/gtar b/.github/workflows/gtar index 5814696d1..cf64d0281 100644 --- a/.github/workflows/gtar +++ b/.github/workflows/gtar @@ -1,2 +1,2 @@ #!/bin/sh -exec sudo /usr/local/bin/gtar.orig "$@" +exec sudo /opt/homebrew/bin/gtar.orig "$@" From 23f9654940902a1ae86ef9eda342011dcca6e1c8 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 9 May 2024 21:49:32 -0400 Subject: [PATCH 243/300] update `BUILDING.md` (#4128) --- .github/workflows/test-builds-on-distros.yml | 32 ++++++++++++-------- docs/BUILDING.md | 16 +++++----- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index 36bbc67a9..e2029be78 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -1,8 +1,3 @@ -# todo: -# nlohmann -# tinyxml2 -# spdlog - name: test-builds-on-distros on: workflow_dispatch: # by request @@ -28,31 +23,42 @@ jobs: if: ${{ matrix.image == 'archlinux:base' }} run: | echo arch - echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost + echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost pacman -Syu --noconfirm - pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost + pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost - name: Install dependencies (dnf) if: ${{ matrix.image == 'fedora:39' }} run: | echo fedora - echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel + echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel dnf -y upgrade - dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel + dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel - name: Install dependencies (apt) if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }} run: | echo debian based - echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev + echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev apt-get update apt-get -y full-upgrade - apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev + apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev - name: Install dependencies (zypper) if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }} run: | echo openSUSE - echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools + echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel zypper --non-interactive dup - zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools + zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel + - name: Install latest nlohmann + if: ${{ matrix.image == 'fedora:39' }} + run: | + wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz + tar -xzvf v3.11.3.tar.gz + cd json-3.11.3 + mkdir build + cd build + cmake .. + make + sudo make install - uses: actions/checkout@v3 with: submodules: true diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 6c9222242..eb5a6a336 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -88,34 +88,34 @@ cd "build/x64" #### Debian/Ubuntu ```sh # using gcc -apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev +apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev # or using clang -apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev +apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev ``` #### Arch ```sh # using gcc -pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost +pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost # or using clang -pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost +pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost ``` #### Fedora ```sh # using gcc -dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel +dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel # or using clang -dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel +dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel ``` #### openSUSE ```sh # using gcc -zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools +zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel # or using clang -zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools +zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel ``` ### Build From 63bc2aff59ea9b0ec3019d026235afe35f40618c Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 9 May 2024 21:55:53 -0400 Subject: [PATCH 244/300] Frogs Ocarina Game Difficulty Options (#3373) * Frog actor edits, menu, presets * Block off vanilla code + comments * fix logic + formatting * new documentation format * Update for CVAR changes * Fix alignment * Conditions cleanup * Update soh/soh/SohMenuBar.cpp Oops, added Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> --------- Co-authored-by: inspectredc <78732756+inspectredc@users.noreply.github.com> --- soh/soh/Enhancements/presets.h | 4 ++ soh/soh/SohMenuBar.cpp | 26 +++++++++++++ soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c | 43 +++++++++++++++++---- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index a502dc3da..54c729371 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -200,6 +200,10 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), + CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), + CVAR_ENHANCEMENT("InstantFrogsGameWin"), + CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), + CVAR_ENHANCEMENT("FrogsModifyFailTime"), CVAR_ENHANCEMENT("CreditsFix"), CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), CVAR_ENHANCEMENT("StaticExplosionRadius"), diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f60983c59..9cd2c6844 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -891,6 +891,32 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); + if (ImGui::BeginMenu("Frogs Ocarina Game")) { + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame")); + UIWidgets::Tooltip("Turn on/off changes to the frogs ocarina game behavior"); + bool disabled = !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0); + static const char* disabledTooltip = + "This option is disabled because \"Customize Behavior\" is turned off"; + UIWidgets::PaddedEnhancementCheckbox("Instant Win", CVAR_ENHANCEMENT("InstantFrogsGameWin"), true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Skips the frogs ocarina game"); + UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Removes the timer to play back the song"); + bool disabledFrog = 0; + static const char* disabledFrogTooltip = + "This option is disabled because \"Customize Behavior\" is turned off or \"Unlimited Playback Time\" is on"; + if (!CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), 0)) { + disabledFrog = 1; + } else { + disabledFrog = 0; + } + UIWidgets::PaddedEnhancementSliderInt("Modify note timer: %dx", "##FrogsFailTimer", CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1, 5, "", 1, true, true, false, + disabledFrog, disabledFrogTooltip); + UIWidgets::Tooltip("Adjusts the time allowed for playback before failing"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", CVAR_ENHANCEMENT("DeleteFileOnDeath"), true, false); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); UIWidgets::Tooltip("Dying will delete your file\n\n " ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSABLE\nUSE AT YOUR OWN RISK!"); diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 36c9c2818..d616db040 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -819,12 +819,28 @@ void EnFr_SetupFrogSong(EnFr* this, PlayState* play) { if (this->frogSongTimer != 0) { this->frogSongTimer--; } else { - this->frogSongTimer = 40; - this->ocarinaNoteIndex = 0; - func_8010BD58(play, OCARINA_ACTION_FROGS); - this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); - EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); - this->actionFunc = EnFr_ContinueFrogSong; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) { + this->frogSongTimer = 40 * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1); + if (CVarGetInteger(CVAR_ENHANCEMENT("InstantFrogsGameWin"), 0)) { + this->actor.textId = 0x40AC; + EnFr_SetupReward(this, play, false); + } else { + this->ocarinaNoteIndex = 0; + func_8010BD58(play, OCARINA_ACTION_FROGS); + this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); + EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); + this->actionFunc = EnFr_ContinueFrogSong; + } + // #endregion + } else { + this->frogSongTimer = 40; + this->ocarinaNoteIndex = 0; + func_8010BD58(play, OCARINA_ACTION_FROGS); + this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); + EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); + this->actionFunc = EnFr_ContinueFrogSong; + } } } @@ -846,7 +862,13 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) { ocarinaNote = EnFr_GetNextNoteFrogSong(ocarinaNoteIndex); this->ocarinaNote = ocarinaNote; EnFr_CheckOcarinaInputFrogSong(ocarinaNote); - this->frogSongTimer = sTimerFrogSong[index]; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) { + this->frogSongTimer = sTimerFrogSong[index] * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1); + // #endregion + } else { + this->frogSongTimer = sTimerFrogSong[index]; + } } return false; } @@ -870,7 +892,12 @@ void EnFr_ContinueFrogSong(EnFr* this, PlayState* play) { if (this->frogSongTimer == 0) { EnFr_OcarinaMistake(this, play); } else { - this->frogSongTimer--; + // #region SOH [Enhancement] - Don't decrement timer + if (!CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0) || + !CVarGetInteger(CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), 0)) { + // #endregion + this->frogSongTimer--; + } if (play->msgCtx.msgMode == MSGMODE_FROGS_PLAYING) { counter = 0; for (i = 0; i < ARRAY_COUNT(sEnFrPointers.frogs); i++) { From 118cd044b528a9cca61e6c18c5a6cb387b642bad Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 10 May 2024 04:39:22 +0200 Subject: [PATCH 245/300] Rando: Starting hearts (#3974) * Initial implementation * Re-run build --------- Co-authored-by: Garrett Cox --- soh/soh/Enhancements/mods.cpp | 2 +- soh/soh/Enhancements/randomizer/savefile.cpp | 5 +++++ soh/soh/Enhancements/randomizer/settings.cpp | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index f12b12174..72f1bc599 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -434,7 +434,7 @@ void UpdatePermanentHeartLossState() { if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) { uint8_t heartContainers = gSaveContext.sohStats.heartContainers; // each worth 16 health uint8_t heartPieces = gSaveContext.sohStats.heartPieces; // each worth 4 health, but only in groups of 4 - uint8_t startingHealth = 16 * 3; + uint8_t startingHealth = 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3); uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4); diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index ffab46e49..e8998b4a4 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -140,6 +140,11 @@ void SetStartingItems() { gSaveContext.inventory.gsTokens = Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN); } + if ((Randomizer_GetSettingValue(RSK_STARTING_HEARTS) + 1) != 3) { + gSaveContext.healthCapacity = (Randomizer_GetSettingValue(RSK_STARTING_HEARTS) + 1) * 16; + gSaveContext.health = gSaveContext.healthCapacity; + } + if (Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 11a42aefb..48011f423 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -202,7 +202,7 @@ void Settings::CreateOptions() { mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW] = Option::Bool("Start with Nocturne of Shadow", CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), "", IMFLAG_NONE); mOptions[RSK_STARTING_PRELUDE_OF_LIGHT] = Option::Bool("Start with Prelude of Light", CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight")); mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WidgetType::Slider); - mOptions[RSK_STARTING_HEARTS] = Option::U8("Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, "", "", WidgetType::Slider, 2); + mOptions[RSK_STARTING_HEARTS] = Option::U8("Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, "gRandomizeStartingHearts", "", WidgetType::Slider, 2); // TODO: Remainder of Starting Items mOptions[RSK_LOGIC_RULES] = Option::U8("Logic", {"Glitchless", "Glitched", "No Logic", "Vanilla"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS); mOptions[RSK_ALL_LOCATIONS_REACHABLE] = Option::Bool("All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON); @@ -773,6 +773,7 @@ void Settings::CreateOptions() { &mOptions[RSK_STARTING_OCARINA], &mOptions[RSK_STARTING_CONSUMABLES], &mOptions[RSK_STARTING_SKULLTULA_TOKEN], + &mOptions[RSK_STARTING_HEARTS], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_STARTING_NORMAL_SONGS_IMGUI] = OptionGroup::SubGroup("Normal Songs", { &mOptions[RSK_STARTING_ZELDAS_LULLABY], @@ -933,6 +934,7 @@ void Settings::CreateOptions() { &mOptions[RSK_STARTING_CONSUMABLES], &mOptions[RSK_FULL_WALLETS], &mOptions[RSK_STARTING_SKULLTULA_TOKEN], + &mOptions[RSK_STARTING_HEARTS], }, false); mOptionGroups[RSG_STARTING_INVENTORY] = OptionGroup("Starting Inventory", { &mOptionGroups[RSG_STARTING_ITEMS], @@ -1196,6 +1198,7 @@ void Settings::CreateOptions() { { "Start with Consumables", RSK_STARTING_CONSUMABLES }, { "Full Wallets", RSK_FULL_WALLETS }, { "Gold Skulltula Tokens", RSK_STARTING_SKULLTULA_TOKEN }, + { "Hearts", RSK_STARTING_HEARTS }, { "Timesaver Settings:Cuccos to return", RSK_CUCCO_COUNT }, { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, From 65b18d61cfba4a93b547f5ff016f48bb8cb8fc6a Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Thu, 9 May 2024 23:02:50 -0400 Subject: [PATCH 246/300] Fix modifiers crash when obtaining underwater item (#4110) * NULL check * Update soh/src/overlays/actors/ovl_player_actor/z_player.c Co-authored-by: Garrett Cox * Update soh/src/overlays/actors/ovl_player_actor/z_player.c Co-authored-by: Garrett Cox --------- Co-authored-by: Garrett Cox --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 145da2f99..3e1452648 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -12116,7 +12116,8 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { } else if (gWalkSpeedToggle2) { swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping2"), 1.0f); } - } else { + // sControlInput is NULL to prevent inputs while surfacing after obtaining an underwater item so we want to ignore it for that case + } else if (sControlInput != NULL) { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping1"), 1.0f); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { From 6f7173a5c41eb700381ba7d1ce7558d5b556e892 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 9 May 2024 22:22:08 -0500 Subject: [PATCH 247/300] Split a few VB changes out into their own files (#4123) --- .../TimeSavers/SkipCutscene/SkipIntro.cpp | 21 ++ .../SkipCutscene/Story/SkipBlueWarp.cpp | 143 +++++++++++++ .../SkipCutscene/Story/SkipDekuTreeIntro.cpp | 22 ++ .../Story/SkipLostWoodsBridge.cpp | 39 ++++ .../Story/SkipToGivingZeldasLetter.cpp | 45 ++++ .../Story/SkipZeldaFleeingCastle.cpp | 67 ++++++ .../MoveMidoInKokiriForest.cpp | 30 +++ .../Enhancements/TimeSavers/TimeSavers.cpp | 14 ++ soh/soh/Enhancements/TimeSavers/TimeSavers.h | 17 ++ .../game-interactor/GameInteractor.h | 2 +- soh/soh/Enhancements/mods.cpp | 2 + .../Enhancements/timesaver_hook_handlers.cpp | 200 ------------------ .../actors/ovl_Bg_Treemouth/z_bg_treemouth.h | 2 + soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h | 5 +- 14 files changed, 407 insertions(+), 202 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipDekuTreeIntro.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipLostWoodsBridge.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipToGivingZeldasLetter.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipZeldaFleeingCastle.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/TimeSavers.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/TimeSavers.h diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp new file mode 100644 index 000000000..95e9c2d10 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp @@ -0,0 +1,21 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "z64save.h" + #include "functions.h" + extern PlayState* gPlayState; + extern SaveContext gSaveContext; +} + +void SkipIntro_Register() { + REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO)) { + if (gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp new file mode 100644 index 000000000..564ca2d8f --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp @@ -0,0 +1,143 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "macros.h" + #include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" + #include "z64save.h" + #include "functions.h" + #include "variables.h" +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() + +/** + * This will override the transitions into the blue warp cutscenes, set any appropriate flags, and + * set the entrance index to where you would normally end up after the blue warp cutscene. This + * should also account for the difference between your first and following visits to the blue warp. + */ +void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, void* opt) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + uint8_t isBlueWarp = 0; + // Deku Tree Blue warp + if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11; + isBlueWarp = 1; + // Dodongo's Cavern Blue warp + } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; + isBlueWarp = 1; + // Jabu Jabu's Blue warp + } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_0 && gSaveContext.cutsceneIndex == 0xFFF0) { + gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_0; + isBlueWarp = 1; + // Forest Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { + // Normally set in the blue warp cutscene + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); + + if (IS_RANDO) { + gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3; + } else { + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12; + } + + isBlueWarp = 1; + // Fire Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; + isBlueWarp = 1; + // Water Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; + + gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; + isBlueWarp = 1; + // Spirit Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { + gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_8; + isBlueWarp = 1; + // Shadow Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { + gSaveContext.entranceIndex = ENTR_GRAVEYARD_8; + isBlueWarp = 1; + } + + if (isBlueWarp) { + if (gSaveContext.entranceIndex != ENTR_LAKE_HYLIA_9) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + } + + *should = false; + gSaveContext.cutsceneIndex = 0; + + if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { + Entrance_OverrideBlueWarp(); + } + } + } +} + +/** + * While we could rely on the Item_Give that's normally called, it's not very clear to the player that they + * received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given + * to the player instead. + */ +void SkipBlueWarp_ShouldGiveItem(GIVanillaBehavior _, bool* should, void* opt) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + *should = false; + } +} + +// Todo: Move item queueing here + +/** + * This ensures the Kokiri blocking the forest exit checks if you are eligible to leave the forest + * every frame, instead of only at init. The reason we need to do this is when we skip the blue warp cutscene + * you end up getting the Kokiri Emerald after the actor has init'd, so the actor doesn't know you have it + */ +void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) { + func_80A995CC(enKo, play); + + if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) { + if (GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { + enKo->collider.dim.height -= 200; + Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos); + enKo->actionFunc = func_80A99384; + } + } +} + +void SkipBlueWarp_OnActorUpdate(void* actorPtr) { + EnKo* enKo = static_cast(actorPtr); + + if ( + (enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && + enKo->actionFunc == func_80A995CC && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) + ) { + enKo->actionFunc = EnKo_MoveWhenReady; + } +} + +/** + * This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene. + * Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it yet. + */ +void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, void* opt) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_11 && gSaveContext.cutsceneIndex == 0xFFF1) { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); + } + } +} + +void SkipBlueWarp_Register() { + GameInteractor::Instance->RegisterGameHookForID(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate); + GameInteractor::Instance->RegisterGameHookForID(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS); + GameInteractor::Instance->RegisterGameHookForID(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished); + GameInteractor::Instance->RegisterGameHookForID(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipDekuTreeIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipDekuTreeIntro.cpp new file mode 100644 index 000000000..bac84cb63 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipDekuTreeIntro.cpp @@ -0,0 +1,22 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" +} + +/** + * This will skip the Deku Tree intro, and simply open the mouth as you approach it. +*/ +void SkipDekuTreeIntro_Register() { + REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + BgTreemouth* treeMouth = static_cast(opt); + Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); + Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + BgTreemouth_SetupAction(treeMouth, func_808BC6F8); + *should = false; + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipLostWoodsBridge.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipLostWoodsBridge.cpp new file mode 100644 index 000000000..f447b7386 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipLostWoodsBridge.cpp @@ -0,0 +1,39 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "z64save.h" + #include "functions.h" + extern PlayState* gPlayState; + extern SaveContext gSaveContext; +} + +void SkipLostWoodsBridge_Register() { + /** + * This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy Ocarina. + */ + REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { + Item_Give(gPlayState, ITEM_OCARINA_FAIRY); + } + *should = false; + } + } + }); + + /** + * While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the player + * that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given instead. + */ + REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + *should = false; + } + }); + + // Todo: Move item queueing here +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipToGivingZeldasLetter.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipToGivingZeldasLetter.cpp new file mode 100644 index 000000000..357125db8 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipToGivingZeldasLetter.cpp @@ -0,0 +1,45 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" +} + +/** + * This overrides Zelda's update function to effectively skip the dialog and cutscenes played when + * you meet with her in Hyrule Castle Courtyard. As you approach her she will turn around, and talking + * with her will place you at the very last dialog option where she gives you the letter. + */ + +u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) { + return 0x207D; +} + +void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { + if (enZl4->csState == 0 && enZl4->actor.xzDistToPlayer < 700.0f && EnZl4_SetNextAnim(enZl4, 3)) { + Audio_PlayFanfare(NA_BGM_APPEAR); + enZl4->csState = 8; // ZL4_CS_PLAN + } else { + Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); + func_80B5BB78(enZl4, play); + + if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { + enZl4->talkState = 6; + enZl4->actionFunc = EnZl4_Cutscene; + } + } +} + +void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + EnZl4* enZl4 = static_cast(actorPtr); + if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; + + enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; + } +} + +void SkipToGivingZeldasLetter_Register() { + GameInteractor::Instance->RegisterGameHookForID(ACTOR_EN_ZL4, SkipToGivingZeldasLetter_OnActorInit); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipZeldaFleeingCastle.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipZeldaFleeingCastle.cpp new file mode 100644 index 000000000..48cc80aa7 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipZeldaFleeingCastle.cpp @@ -0,0 +1,67 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "z64save.h" + #include "functions.h" + extern SaveContext gSaveContext; +} + +void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, void* opt) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { + if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + // Normally set in the cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA; + + gSaveContext.cutsceneIndex = 0; + *should = false; + } + } +} + +/** + * When this cutscene is skipped, walking up to the bridge to castle town triggers a quick fade in/out + * which can be confusing to beginners, because they need to then fetch the Ocarina of Time from the water. + * To make it more obvious what happened, we'll play the sound of the Ocarina dropping into the water. + */ +static int framesSinceSpawn = 0; +static HOOK_ID itemOcarinaUpdateHook = 0; +static HOOK_ID sceneInitHook = 0; + +void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) { + Actor* actor = static_cast(actorPtr); + + framesSinceSpawn++; + if (framesSinceSpawn > 20) { + Audio_PlayActorSound2(actor, NA_SE_EV_BOMB_DROP_WATER); + + GameInteractor::Instance->UnregisterGameHookForPtr(itemOcarinaUpdateHook); + GameInteractor::Instance->UnregisterGameHook(sceneInitHook); + itemOcarinaUpdateHook = 0; + sceneInitHook = 0; + } +} + +void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) { + Actor* actor = static_cast(actorPtr); + + if ( + actor->params == 3 && + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) + ) { + framesSinceSpawn = 0; + itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr((uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate); + sceneInitHook = GameInteractor::Instance->RegisterGameHook([] (int16_t sceneNum) { + GameInteractor::Instance->UnregisterGameHookForPtr(itemOcarinaUpdateHook); + GameInteractor::Instance->UnregisterGameHook(sceneInitHook); + itemOcarinaUpdateHook = 0; + sceneInitHook = 0; + }); + } +} + +void SkipZeldaFleeingCastle_Register() { + GameInteractor::Instance->RegisterGameHookForID(ACTOR_ITEM_OCARINA, SkipZeldaFleeingCastle_OnActorInit); + GameInteractor::Instance->RegisterGameHookForID(VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp new file mode 100644 index 000000000..78a680175 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp @@ -0,0 +1,30 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { + #include "z64save.h" + #include "macros.h" + #include "variables.h" + #include "functions.h" + extern PlayState* gPlayState; + extern SaveContext gSaveContext; +} + +/** + * This simply skips the Mido interaction in Kokiri Forest, once you equip the Kokiri + * Sword and Deku Shield he will move out of the way without you needing to talk to him. + */ +void MoveMidoInKokiriForest_Register() { + REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, { + if ( + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && + !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && + (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && + (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) + ) { + Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + *should = true; + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp new file mode 100644 index 000000000..f6d2e3629 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp @@ -0,0 +1,14 @@ +#include "TimeSavers.h" + +void TimeSavers_Register() { + // SkipCutscene + // Story + SkipBlueWarp_Register(); + SkipDekuTreeIntro_Register(); + SkipLostWoodsBridge_Register(); + SkipToGivingZeldasLetter_Register(); + SkipZeldaFleeingCastle_Register(); + SkipIntro_Register(); + // SkipMiscInteractions + MoveMidoInKokiriForest_Register(); +} diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.h b/soh/soh/Enhancements/TimeSavers/TimeSavers.h new file mode 100644 index 000000000..b3b221351 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.h @@ -0,0 +1,17 @@ +#ifndef TIME_SAVERS_H +#define TIME_SAVERS_H + +void TimeSavers_Register(); + +// SkipCutscene + // Story + void SkipBlueWarp_Register(); + void SkipDekuTreeIntro_Register(); + void SkipLostWoodsBridge_Register(); + void SkipToGivingZeldasLetter_Register(); + void SkipZeldaFleeingCastle_Register(); + void SkipIntro_Register(); +// SkipMiscInteractions + void MoveMidoInKokiriForest_Register(); + +#endif // TIME_SAVERS_H diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index cca978b2d..956384e5d 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -440,7 +440,7 @@ typedef uint32_t HOOK_ID; } #define REGISTER_VB_SHOULD(flag, body) \ - GameInteractor::Instance->RegisterGameHookForID(flag, [](GIVanillaBehavior _, bool* should, void* opt) body) + GameInteractor::Instance->RegisterGameHookForID(flag, [](GIVanillaBehavior _, bool* should, void* opt) body) class GameInteractor { public: diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 72f1bc599..2efe6477e 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -11,6 +11,7 @@ #include #include "soh/Enhancements/nametag.h" #include "soh/Enhancements/timesaver_hook_handlers.h" +#include "soh/Enhancements/TimeSavers/TimeSavers.h" #include "soh/Enhancements/cheat_hook_handlers.h" #include "soh/Enhancements/randomizer/hook_handlers.h" #include "objects/object_gi_compass/object_gi_compass.h" @@ -1715,6 +1716,7 @@ void InitMods() { RandomizerRegisterHooks(); TimeSaverRegisterHooks(); CheatsRegisterHooks(); + TimeSavers_Register(); RegisterTTS(); RegisterInfiniteMoney(); RegisterInfiniteHealth(); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 569459c67..28518ae14 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -34,20 +34,6 @@ extern int32_t D_8011D3AC; #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() -void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) { - func_80A995CC(enKo, play); - - if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) { - // Typically this doesn't get get live updated in vanilla, but we need to - // live update it if we're skipping a certain cutscene or in randomizer - if (GameInteractor_Should(VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { - enKo->collider.dim.height -= 200; - Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos); - enKo->actionFunc = func_80A99384; - } - } -} - void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); @@ -74,25 +60,6 @@ void EnFu_EndTeachSong(EnFu* enFu, PlayState* play) { } } -u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) { - return 0x207D; -} - -void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { - if (enZl4->csState == 0 && enZl4->actor.xzDistToPlayer < 600.0f && EnZl4_SetNextAnim(enZl4, 3)) { - Audio_PlayFanfare(NA_BGM_APPEAR); - enZl4->csState = 8; // ZL4_CS_PLAN - } else { - Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); - func_80B5BB78(enZl4, play); - - if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { - enZl4->talkState = 6; - enZl4->actionFunc = EnZl4_Cutscene; - } - } -} - void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { // todo: figure out a better way to handle toggling so we don't // need to double check cvars like this @@ -141,11 +108,6 @@ void TimeSaverOnGameFrameUpdateHandler() { void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { switch (id) { case VB_PLAY_TRANSITION_CS: { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { - gSaveContext.cutsceneIndex = 0; - *should = false; - } - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), IS_RANDO) || IS_RANDO) { // Song of Time if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) { @@ -185,82 +147,6 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - uint8_t isBlueWarp = 0; - // Deku Tree Blue warp - if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { - gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11; - isBlueWarp = 1; - // Dodongo's Cavern Blue warp - } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_0 && gSaveContext.cutsceneIndex == 0xFFF1) { - gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; - isBlueWarp = 1; - // Jabu Jabu's Blue warp - } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_0 && gSaveContext.cutsceneIndex == 0xFFF0) { - gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_0; - isBlueWarp = 1; - // Forest Temple Blue warp - } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { - // Normally set in the blue warp cutscene - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); - - if (IS_RANDO) { - gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3; - } else { - gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12; - } - - isBlueWarp = 1; - // Fire Temple Blue warp - } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { - gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; - isBlueWarp = 1; - // Water Temple Blue warp - } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { - // Normally set in the blue warp cutscene - gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; - - gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; - isBlueWarp = 1; - // Spirit Temple Blue warp - } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { - gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_8; - isBlueWarp = 1; - // Shadow Temple Blue warp - } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { - gSaveContext.entranceIndex = ENTR_GRAVEYARD_8; - isBlueWarp = 1; - } - - if (isBlueWarp) { - // Normally set in the blue warp cutscene - gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; - - *should = false; - gSaveContext.cutsceneIndex = 0; - - if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { - Entrance_OverrideBlueWarp(); - } - } - - // Flee hyrule castle cutscene - if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) { - // Normally set in the blue warp cutscene - gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA; - - gSaveContext.cutsceneIndex = 0; - *should = false; - } - - // Lost Woods Bridge - if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); - if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { - Item_Give(gPlayState, ITEM_OCARINA_FAIRY); - } - *should = false; - } - // LACS u8 meetsLACSRequirements = LINK_IS_ADULT && @@ -429,38 +315,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* *should = true; } break; - case VB_MOVE_MIDO_IN_KOKIRI_FOREST: - if ( - CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) && - !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && - (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && - (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) - ) { - Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); - *should = true; - } - break; - case VB_PLAY_DEKU_TREE_INTRO_CS: { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - BgTreemouth* treeMouth = static_cast(opt); - Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); - Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - BgTreemouth_SetupAction(treeMouth, func_808BC6F8); - *should = false; - } - break; - } - case VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { - // We're overriding this so that the Deku JR doesn't despawn after skipping the forest temple blue warp cutscene. - // It typically relies on the forest medallion being obtained, but that isn't given yet until after scene init - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); - } - break; - } - case VB_GIVE_ITEM_FROM_BLUE_WARP: case VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: - case VB_GIVE_ITEM_FAIRY_OCARINA: case VB_GIVE_ITEM_LIGHT_ARROW: if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { *should = false; @@ -773,10 +628,6 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } } -static uint32_t enKoUpdateHook = 0; -static uint32_t enKoKillHook = 0; -static uint32_t itemOcarinaUpdateHook = 0; -static uint32_t itemOcarinaframesSinceSpawn = 0; static uint32_t enMa1UpdateHook = 0; static uint32_t enMa1KillHook = 0; static uint32_t enFuUpdateHook = 0; @@ -788,50 +639,6 @@ static uint32_t enPoSistersKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); - if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) { - enKoUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { - Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || IS_RANDO)) { - EnKo* enKo = static_cast(innerActorRef); - // They haven't moved yet, wrap their update function so we check every frame - if (enKo->actionFunc == func_80A995CC) { - enKo->actionFunc = EnKo_MoveWhenReady; - GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enKoKillHook); - enKoUpdateHook = 0; - enKoKillHook = 0; - // They have already moved - } else if (enKo->actionFunc == func_80A99384) { - GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enKoKillHook); - enKoUpdateHook = 0; - enKoKillHook = 0; - } - } - }); - enKoKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { - GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enKoKillHook); - enKoUpdateHook = 0; - enKoKillHook = 0; - }); - } - - if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - itemOcarinaframesSinceSpawn = 0; - itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { - Actor* innerActor = static_cast(innerActorRef); - if (innerActor->id != ACTOR_ITEM_OCARINA || innerActor->params != 3) return; - itemOcarinaframesSinceSpawn++; - if (itemOcarinaframesSinceSpawn > 20) { - Audio_PlayActorSound2(innerActor, NA_SE_EV_BOMB_DROP_WATER); - - GameInteractor::Instance->UnregisterGameHook(itemOcarinaUpdateHook); - itemOcarinaUpdateHook = 0; - } - }); - } - if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) { enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { Actor* innerActor = static_cast(innerActorRef); @@ -904,13 +711,6 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } - if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - EnZl4* enZl4 = static_cast(actorRef); - if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; - - enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; - } - if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnDntDemo* enDntDemo = static_cast(actorRef); enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h index daa33bfee..ea8189ad2 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h @@ -15,7 +15,9 @@ typedef struct BgTreemouth { /* 0x016C */ BgTreemouthActionFunc actionFunc; } BgTreemouth; // size = 0x0170 +// #region SoH [Enhancements] Externed for time savers void BgTreemouth_SetupAction(BgTreemouth* actor, BgTreemouthActionFunc actionFunc); void func_808BC6F8(BgTreemouth* actor, PlayState* play); +// #endregion #endif diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h index 5deeef465..80ecd0664 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h @@ -1,8 +1,10 @@ #ifndef Z_EN_KO_H #define Z_EN_KO_H +#ifndef __cplusplus #include #include "global.h" +#endif struct EnKo; @@ -57,8 +59,9 @@ typedef enum { ENKO_FQS_ADULT_SAVED } KokiriForestQuestState; +// #region SoH [Enhancements] Externed for time savers void func_80A995CC(EnKo* actor, PlayState* play); void func_80A99384(EnKo* actor, PlayState* play); -void func_80A99560(EnKo* actor, PlayState* play); +// #endregion #endif From 844413b391eadef832a5dadf46adcdb3a887b6bd Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 9 May 2024 19:57:31 -0800 Subject: [PATCH 248/300] Add Modifier buttons to input viewer and support individual button outline modes (#3966) * Add Modifier buttons to input viewer and support individual button outline modes * Clearer naming * Remove hardcoded indent values * clean up diff --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- soh/assets/custom/textures/buttons/Mod1.png | Bin 0 -> 1166 bytes .../custom/textures/buttons/Mod1Outline.png | Bin 0 -> 1180 bytes soh/assets/custom/textures/buttons/Mod2.png | Bin 0 -> 1110 bytes .../custom/textures/buttons/Mod2Outline.png | Bin 0 -> 1192 bytes soh/soh/Enhancements/controls/InputViewer.cpp | 275 ++++++++++++++---- 5 files changed, 218 insertions(+), 57 deletions(-) create mode 100644 soh/assets/custom/textures/buttons/Mod1.png create mode 100644 soh/assets/custom/textures/buttons/Mod1Outline.png create mode 100644 soh/assets/custom/textures/buttons/Mod2.png create mode 100644 soh/assets/custom/textures/buttons/Mod2Outline.png diff --git a/soh/assets/custom/textures/buttons/Mod1.png b/soh/assets/custom/textures/buttons/Mod1.png new file mode 100644 index 0000000000000000000000000000000000000000..69496db6a7a9cc4a7fc8506653d4c1dbb55c7aa4 GIT binary patch literal 1166 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 QPy|xo>FVdQ&MBb@0BC5Em;e9( literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/Mod2Outline.png b/soh/assets/custom/textures/buttons/Mod2Outline.png new file mode 100644 index 0000000000000000000000000000000000000000..06464c553e96bd4327fe8b65d764ed7bb629cd73 GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@lrn7T^r?ay{K~a8MW=<*t zgT}<#iMAex9b}Hi2QO6;W$*5=NLk@0c0^ysTeLf2;TF-TQiGjexM!KDXzKMfWgk4) ze{@xI_vUqc>zWjPFg|+oV95(5)qnb$TRJ{I*dhP^o$b4Oj82OWg>24d3NStGaWpx} zY`Yd)oMM7NU5lZzVX*%aapMm%@!vmu{Hk|o^Pcm6Eq_hfbCO}chfM0OM8SN4^LbHL z&ubqEXnS&fwEVckQCy|&$*wn_q@OQ3%ygbda^@AA!j1@?vJH0*u1Q&OMy@;6SHIbwY{j0{t<>#4Z!73Kcv`Tyr-e*Mn8^+wU5?AAL%z-VDh@^*J&SjsS&VTJ?i zHaDOMXMsm#F#`j)FbFd;%$g$s6l5>)^mS!_!6e4QZ!#l9;}lRxvcxr_#5q4VH#M(> z!MP|ku_QG`p**uBL&4qCHz2%`Pn>~)sln65F{I+w+dGbVw*my%9#n4Sf8@c~8GL1q z%304z^HiRwObAwB6|?I&`})|_By-IRX@Y0Izul0dpZ3xC@%J|zKzoK3_z~mDX?Nai zTWI98a=}1%m$}7xL0-P6R$3l;n0oJQ_$rn|AElf>emt?Ve{0z$ZT}b!eN4(t zjuv&@Xjh)7`uxtB-9LM|nl@HV65E)uYhCoSnqQj_-=DkmRpYsjT2?25?IP2rusy7p zTK06EpXJ@BQ&v}e-gvv?#+KaQHus)mPbUXj{xZdh%qw?pS^o-@iacHYT-G@yGywnv C$;%r6 literal 0 HcmV?d00001 diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 93727b5fa..106a08b53 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -20,6 +20,8 @@ static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f); static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed", "Shown Only While Pressed", "Always Hidden" }; +static const char* buttonOutlineOptionsVerbose[4] = { "Outline Always Shown", "Outline Shown Only While Not Pressed", + "Outline Shown Only While Pressed", "Outline Always Hidden" }; static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" }; @@ -85,6 +87,8 @@ void InputViewer::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", @@ -117,6 +121,10 @@ void InputViewer::DrawElement() { "textures/buttons/DPadUpOutline.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1 Outline", + "textures/buttons/Mod1Outline.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2 Outline", + "textures/buttons/Mod2Outline.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); sButtonTexturesLoaded = true; @@ -132,17 +140,19 @@ void InputViewer::DrawElement() { #endif const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); + const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); - ImGui::SetNextWindowSize(ImVec2( - scaledBGSize.x + 20, - scaledBGSize.y + - (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + 20)); + ImGui::SetNextWindowSize( + ImVec2(scaledBGSize.x + 20, scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + + 20)); ImGui::SetNextWindowContentSize( ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); ImGui::SetNextWindowPos( ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), ImGuiCond_FirstUseEver); @@ -176,52 +186,78 @@ void InputViewer::DrawElement() { if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // C buttons if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // L/R/Z if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // Start @@ -229,7 +265,9 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // Dpad @@ -237,18 +275,46 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + + // Modifier 1 + if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_MODIFIER1, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + // Modifier 2 + if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_MODIFIER2, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; @@ -359,9 +425,9 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() { } void InputViewerSettingsWindow::DrawElement() { - ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(500, 525), ImGuiCond_FirstUseEver); - if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) { + if (ImGui::Begin("Input Viewer Settings", &mIsVisible, ImGuiWindowFlags_HorizontalScrollbar)) { // gInputViewer.Scale UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", CVAR_INPUT_VIEWER("Scale"), 0.1f, 5.0f, "", @@ -381,48 +447,143 @@ void InputViewerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(true, true); if (ImGui::CollapsingHeader("Buttons")) { - // gInputViewer.ABtn - UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.BBtn - UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CUp - UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CRight - UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CDown - UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CLeft - UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.LBtn - UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.RBtn - UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.ZBtn - UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.StartBtn - UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.Dpad - UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, false); // gInputViewer.ButtonOutlineMode UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false); - UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, - BUTTON_OUTLINE_NOT_PRESSED); + UIWidgets::EnhancementCombobox( + CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, BUTTON_OUTLINE_NOT_PRESSED, + !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), "", + CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); UIWidgets::Tooltip( "Sets the desired visibility behavior for the button outline/background layers. Useful for " "custom input viewers."); + // gInputViewer.UseGlobalButtonOutlineMode + UIWidgets::EnhancementCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(); + + bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); + + // gInputViewer.ABtn + UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.BBtn + UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CUp + UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CRight + UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CDown + UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CLeft + UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.LBtn + UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.RBtn + UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.ZBtn + UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.StartBtn + UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Dpad + UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Mod1 + UIWidgets::EnhancementCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Mod2 + UIWidgets::EnhancementCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + UIWidgets::PaddedSeparator(true, true); } @@ -517,4 +678,4 @@ void InputViewerSettingsWindow::DrawElement() { ImGui::End(); } -} \ No newline at end of file +} From 08ad16e75046c2a1d8424b56571980775dc0296a Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 10 May 2024 07:17:50 +0200 Subject: [PATCH 249/300] Add path XML parser (#4115) * Add path XML parser * Update SetPathwaysFactory.cpp --- soh/soh/resource/importer/PathFactory.cpp | 55 +++++++++++++++++++ soh/soh/resource/importer/PathFactory.h | 6 ++ .../scenecommand/SetPathwaysFactory.cpp | 1 + soh/soh/resource/logging/PathLogger.cpp | 33 +++++++++++ soh/soh/resource/logging/PathLogger.h | 6 ++ 5 files changed, 101 insertions(+) create mode 100644 soh/soh/resource/logging/PathLogger.cpp create mode 100644 soh/soh/resource/logging/PathLogger.h diff --git a/soh/soh/resource/importer/PathFactory.cpp b/soh/soh/resource/importer/PathFactory.cpp index 00807b75a..f0f92be02 100644 --- a/soh/soh/resource/importer/PathFactory.cpp +++ b/soh/soh/resource/importer/PathFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/PathFactory.h" #include "soh/resource/type/Path.h" +#include "soh/resource/logging/PathLogger.h" #include "spdlog/spdlog.h" namespace SOH { @@ -35,6 +36,60 @@ std::shared_ptr ResourceFactoryBinaryPathV0::ReadResource(std:: path->pathData.push_back(pathDataEntry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogPathAsXML(path); + } + return path; } + +std::shared_ptr ResourceFactoryXMLPathV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto path = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + auto pathElement = reader->RootElement(); + + //path->numPaths = pathElement->IntAttribute("NumPaths"); + //path->paths.reserve(path->numPaths); + + auto pathDataElement = pathElement->FirstChildElement(); + + while (pathDataElement != nullptr) { + std::vector points; + //uint32_t pointCount = pathDataElement->IntAttribute("NumPoints"); + //points.reserve(pointCount); + + auto pointElement = pathDataElement->FirstChildElement(); + + while (pointElement != nullptr) { + Vec3s point; + point.x = pointElement->IntAttribute("X"); + point.y = pointElement->IntAttribute("Y"); + point.z = pointElement->IntAttribute("Z"); + + points.push_back(point); + + pointElement = pointElement->NextSiblingElement(); + } + + PathData pathDataEntry; + //pathDataEntry.count = pointCount; + pathDataEntry.count = points.size(); + + path->paths.push_back(points); + pathDataEntry.points = path->paths.back().data(); + + path->pathData.push_back(pathDataEntry); + + pathDataElement = pathDataElement->NextSiblingElement(); + } + + path->numPaths = path->paths.size(); + + return path; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/PathFactory.h b/soh/soh/resource/importer/PathFactory.h index ddbee772d..9dd73b110 100644 --- a/soh/soh/resource/importer/PathFactory.h +++ b/soh/soh/resource/importer/PathFactory.h @@ -2,10 +2,16 @@ #include "Resource.h" #include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" namespace SOH { class ResourceFactoryBinaryPathV0 : public Ship::ResourceFactoryBinary { public: std::shared_ptr ReadResource(std::shared_ptr file) override; }; + +class ResourceFactoryXMLPathV0 : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp index 65af2e0de..ed3681235 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp @@ -17,6 +17,7 @@ SetPathwaysFactory::ReadResource(std::shared_ptr initDat std::string pathFileName = reader->ReadString(); auto path = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); setPathways->paths.push_back(path->GetPointer()); + setPathways->pathFileNames.push_back(pathFileName); } if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { diff --git a/soh/soh/resource/logging/PathLogger.cpp b/soh/soh/resource/logging/PathLogger.cpp new file mode 100644 index 000000000..5c216c9ff --- /dev/null +++ b/soh/soh/resource/logging/PathLogger.cpp @@ -0,0 +1,33 @@ +#include "soh/resource/type/Path.h" +#include "spdlog/spdlog.h" + +namespace SOH { + void LogPathAsXML(std::shared_ptr resource) { + std::shared_ptr path = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("Path"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < path->paths.size(); i += 1) { + tinyxml2::XMLElement* pathData = doc.NewElement("PathData"); + + for (size_t j = 0; j < path->paths[i].size(); j += 1) { + tinyxml2::XMLElement* pathPoint = doc.NewElement("PathPoint"); + + pathPoint->SetAttribute("X", path->paths[i][j].x); + pathPoint->SetAttribute("Y", path->paths[i][j].y); + pathPoint->SetAttribute("Z", path->paths[i][j].z); + + pathData->InsertEndChild(pathPoint); + } + + root->InsertEndChild(pathData); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); + } +} \ No newline at end of file diff --git a/soh/soh/resource/logging/PathLogger.h b/soh/soh/resource/logging/PathLogger.h new file mode 100644 index 000000000..a5e42aeaf --- /dev/null +++ b/soh/soh/resource/logging/PathLogger.h @@ -0,0 +1,6 @@ +#include "Resource.h" +#include "soh/OTRGlobals.h" + +namespace SOH { + void LogPathAsXML(std::shared_ptr resource); +} \ No newline at end of file From baf7691fbde9b27a328a7e9b5a9ffb4c244d22ca Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 13 May 2024 12:29:34 -0500 Subject: [PATCH 250/300] Fix weirdness with item gets from chests (#4146) --- .../game-interactor/GameInteractor.h | 2 ++ .../Enhancements/randomizer/hook_handlers.cpp | 26 ++++++++++++++++--- .../Enhancements/timesaver_hook_handlers.cpp | 11 ++++++++ .../actors/ovl_player_actor/z_player.c | 15 +++++------ 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 956384e5d..57f1d1e5c 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -260,6 +260,8 @@ typedef enum { // Opt: *EnOkarinaTag VB_PLAY_DOOR_OF_TIME_CS, VB_PLAY_RAINBOW_BRIDGE_CS, + // Opt: *EnBox + VB_PLAY_SLOW_CHEST_CS, /*** Give Items ***/ diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 3f15ce4c8..e164eae16 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -37,6 +37,9 @@ extern "C" { extern SaveContext gSaveContext; extern PlayState* gPlayState; +extern void func_8084DFAC(PlayState* play, Player* player); +extern void func_80835DAC(PlayState* play, Player* player, PlayerActionFunc actionFunc, s32 flags); +extern s32 func_80836898(PlayState* play, Player* player, PlayerFuncA74 func); } #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() @@ -555,8 +558,26 @@ void RandomizerSetChestGameRandomizerInf(RandomizerCheck rc) { } } +void Player_Action_8084E6D4_override(Player* player, PlayState* play) { + if (LinkAnimation_Update(play, &player->skelAnime)) { + func_8084DFAC(play, player); + } +} + +void func_8083A434_override(PlayState* play, Player* player) { + func_80835DAC(play, player, Player_Action_8084E6D4_override, 0); + player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_IN_CUTSCENE; +} + void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) { switch (id) { + case VB_PLAY_SLOW_CHEST_CS: { + // We force fast chests if SkipGetItemAnimation is enabled because the camera in the CS looks pretty wonky otherwise + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimation"), SGIA_DISABLED)) { + *should = false; + } + break; + } case VB_GIVE_ITEM_FROM_CHEST: { EnBox* chest = static_cast(optionalArg); RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(chest->dyna.actor.id, gPlayState->sceneNum, chest->dyna.actor.params); @@ -565,9 +586,8 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void RandomizerSetChestGameRandomizerInf(rc); Player* player = GET_PLAYER(gPlayState); - player->av2.actionVar2 = 1; - player->getItemId = GI_NONE; - player->getItemEntry = GetItemEntry(GET_ITEM_NONE); + func_80836898(gPlayState, player, func_8083A434_override); + *should = false; break; } diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 28518ae14..81c7d7727 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -3,6 +3,7 @@ #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/enhancementTypes.h" extern "C" { #include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h" @@ -14,6 +15,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" #include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h" #include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" +#include "src/overlays/actors/ovl_En_Box/z_en_box.h" #include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h" #include "src/overlays/actors/ovl_En_Sa/z_en_sa.h" #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" @@ -625,6 +627,15 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* } break; } + case VB_PLAY_SLOW_CHEST_CS: { + if (CVarGetInteger(CVAR_ENHANCEMENT("FastChests"), 0)) { + *should = false; + } else if (CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED) && *should) { + EnBox* enBox = static_cast(opt); + *should = enBox->dyna.actor.scale.x != 0.005f; + } + break; + } } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 8cadd404b..3dfb2dbeb 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6853,10 +6853,6 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { giEntry = this->getItemEntry; } EnBox* chest = (EnBox*)interactedActor; - if (CVarGetInteger(CVAR_ENHANCEMENT("FastChests"), 0) != 0) { - giEntry.gi = -1 * abs(giEntry.gi); - } - if (giEntry.itemId != ITEM_NONE) { if (((Item_CheckObtainability(giEntry.itemId) == ITEM_NONE) && (giEntry.field & 0x40)) || ((Item_CheckObtainability(giEntry.itemId) != ITEM_NONE) && (giEntry.field & 0x20))) { @@ -6865,11 +6861,12 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { } } - func_80836898(play, this, func_8083A434); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_CHEST, true, chest)) { + func_80836898(play, this, func_8083A434); + } this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; func_8083AE40(this, giEntry.objectId); - } + this->actor.world.pos.x = chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); this->actor.world.pos.z = @@ -6877,8 +6874,10 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { this->yaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y; func_80832224(this); - if ((giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) && - (Item_CheckObtainability(giEntry.itemId) == ITEM_NONE)) { + bool vanillaPlaySlowChestCS = (giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) && + (Item_CheckObtainability(giEntry.itemId) == ITEM_NONE); + + if (GameInteractor_Should(VB_PLAY_SLOW_CHEST_CS, vanillaPlaySlowChestCS, chest)) { Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98); Player_AnimReplaceApplyFlags(play, this, 0x28F); chest->unk_1F4 = 1; From ad0e17383e72c652541e6a90367ab720c6a18723 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Thu, 16 May 2024 14:55:04 -0400 Subject: [PATCH 251/300] update nightly links in readme (#4147) --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index ad80f7f2f..233ef86d9 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,7 @@ If you want to playtest a continuous integration build, you can find them at the * [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip) * [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip) -* [Linux (performance)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-performance.zip) _(requires `glibc 2.35` or newer, but will be more performant than the compatibility build.)_ -* [Linux (compatibility)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatibility.zip) _(compatible with most Linux distributions, but may not be as performant as the performance build.)_ -* [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip) -* [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip) +* [Linux](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux.zip) From 53efc22a23efd7bc76733efa00a35d67b798ae29 Mon Sep 17 00:00:00 2001 From: Lywx Date: Mon, 27 May 2024 16:33:02 -0600 Subject: [PATCH 252/300] Framebuffer clear and bump LUS (#4187) --- CMakeLists.txt | 6 ++++++ OTRExporter | 2 +- ZAPDTR | 2 +- libultraship | 2 +- soh/CMakeLists.txt | 4 ++++ soh/include/functions.h | 2 -- soh/soh/GbiWrap.cpp | 9 --------- soh/src/code/z_rcp.c | 8 ++++---- 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 891d6ad26..490489f55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,12 @@ include(CMake/GlobalSettingsInclude.cmake OPTIONAL) ################################################################################ set_property(GLOBAL PROPERTY USE_FOLDERS ON) +################################################################################ +# Set GBI version +################################################################################ + +add_compile_definitions(F3DEX_GBI_2) + ################################################################################ # Sub-projects ################################################################################ diff --git a/OTRExporter b/OTRExporter index 3cea9ee7c..d70db9806 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 3cea9ee7c017d842aa4d9ceeb8d3ffbf29c6effb +Subproject commit d70db9806c02c229ca3ed928ad0bdae128fe4ac7 diff --git a/ZAPDTR b/ZAPDTR index f38a9c92e..04d42249d 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit f38a9c92eb99368c0607acf356d5651ebdc96f51 +Subproject commit 04d42249d2c15c3b442a0282a90bc8b7bda25b03 diff --git a/libultraship b/libultraship index 0da318c0f..9def18e62 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 0da318c0f4e431313565cad546fc469b8e850388 +Subproject commit 9def18e62467b4225d26e206e0039a31ed406573 diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 3f086bcac..6984291d3 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -407,6 +407,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") ">" "$<$:ENABLE_REMOTE_CONTROL>" "INCLUDE_GAME_PRINTF;" + "F3DEX_GBI_2" "UNICODE;" "_UNICODE" STORMLIB_NO_AUTO_LINK @@ -425,6 +426,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") "NDEBUG;" ">" "INCLUDE_GAME_PRINTF;" + "F3DEX_GBI_2" "WIN32;" "UNICODE;" "_UNICODE" @@ -440,6 +442,7 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" "SPDLOG_ACTIVE_LEVEL=3;" "SPDLOG_NO_THREAD_ID;" "SPDLOG_NO_TLS;" @@ -453,6 +456,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" "$<$:ENABLE_REMOTE_CONTROL>" "SPDLOG_ACTIVE_LEVEL=0;" "_CONSOLE;" diff --git a/soh/include/functions.h b/soh/include/functions.h index b9e1f6981..fc7fc15b7 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -22,12 +22,10 @@ extern "C" void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); -void gDPSetTextureImage(Gfx* pkt, u32 f, u32 s, u32 w, uintptr_t i); void gSPDisplayList(Gfx* pkt, Gfx* dl); void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset); void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0); void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr); -void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb); void cleararena(void); diff --git a/soh/soh/GbiWrap.cpp b/soh/soh/GbiWrap.cpp index 2399051f5..2dad29e60 100644 --- a/soh/soh/GbiWrap.cpp +++ b/soh/soh/GbiWrap.cpp @@ -66,15 +66,6 @@ extern "C" void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target) { __gSPSegment(value, segNum, target); } -extern "C" void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i) { - __gDPSetTextureImage(pkt, format, size, width, i); -} - -extern "C" void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb) -{ - __gDPSetTextureImageFB(pkt, format, size, width, fb); -} - extern "C" void gSPDisplayList(Gfx* pkt, Gfx* dl) { char* imgData = (char*)dl; diff --git a/soh/src/code/z_rcp.c b/soh/src/code/z_rcp.c index adfa946e7..978c04d3c 100644 --- a/soh/src/code/z_rcp.c +++ b/soh/src/code/z_rcp.c @@ -1539,7 +1539,7 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(POLY_OPA_DISP++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); - gDPFillRectangle(POLY_OPA_DISP++, 0, letterboxSize, gScreenWidth - 1, gScreenHeight - letterboxSize - 1); + gDPFillWideRectangle(POLY_OPA_DISP++, OTRGetRectDimensionFromLeftEdge(0), letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - letterboxSize - 1); gDPPipeSync(POLY_OPA_DISP++); // Fill the whole screen with the base color @@ -1548,7 +1548,7 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(POLY_OPA_DISP++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); - gDPFillRectangle(POLY_OPA_DISP++, 0, letterboxSize, gScreenWidth - 1, gScreenHeight - letterboxSize - 1); + gDPFillWideRectangle(POLY_OPA_DISP++, OTRGetRectDimensionFromLeftEdge(0), letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - letterboxSize - 1); gDPPipeSync(POLY_OPA_DISP++); // Draw the letterbox if applicable (uses the same color as the screen base) @@ -1557,8 +1557,8 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(OVERLAY_DISP++, G_CYC_FILL); gDPSetRenderMode(OVERLAY_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(OVERLAY_DISP++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); - gDPFillRectangle(OVERLAY_DISP++, 0, 0, gScreenWidth - 1, letterboxSize - 1); - gDPFillRectangle(OVERLAY_DISP++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1); + gDPFillWideRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromLeftEdge(0), 0, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), letterboxSize - 1); + gDPFillWideRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromLeftEdge(0), gScreenHeight - letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - 1); gDPPipeSync(OVERLAY_DISP++); } } From b8c7c715785a113142d3fc00d2a28f9b52eeb33b Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:13:03 -0400 Subject: [PATCH 253/300] allow setting device visibility in controller mapping window (#4165) --- .../controls/SohInputEditorWindow.cpp | 256 ++++++------------ .../controls/SohInputEditorWindow.h | 4 +- 2 files changed, 82 insertions(+), 178 deletions(-) diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 667d96c18..a5c1364b8 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -38,6 +38,13 @@ void SohInputEditorWindow::InitElement() { addButtonName(BTN_DLEFT, "D-pad left"); addButtonName(BTN_DRIGHT, "D-pad right"); addButtonName(0, "None"); + + mDeviceIndexVisiblity.clear(); + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = true; + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Blue] = true; + for (auto index = 1; index < Ship::ShipDeviceIndex::Max; index++) { + mDeviceIndexVisiblity[static_cast(index)] = false; + } } #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 @@ -251,6 +258,9 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ if (mapping == nullptr) { return; } + if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) { + return; + } ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); std::string icon = ""; @@ -521,6 +531,9 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, if (mapping == nullptr) { return; } + if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) { + return; + } ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); std::string icon = ""; @@ -1705,11 +1718,75 @@ void SohInputEditorWindow::DrawMiscControlPanel() { Ship::GuiWindow::EndGroupPanel(0); } +void SohInputEditorWindow::DrawDeviceVisibilityButtons() { + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() + ->GetControlDeck() + ->GetDeviceIndexMappingManager() + ->GetAllDeviceIndexMappingsFromConfig()) { + auto sdlIndexMapping = std::static_pointer_cast(mapping); + if (sdlIndexMapping == nullptr) { + continue; + } + + indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 }; + } + + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() + ->GetControlDeck() + ->GetDeviceIndexMappingManager() + ->GetAllDeviceIndexMappings()) { + auto sdlIndexMapping = std::static_pointer_cast(mapping); + if (sdlIndexMapping == nullptr) { + continue; + } + + indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() }; + } + + auto keyboardButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); + auto keyboardButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex::Keyboard, keyboardButtonColor, keyboardButtonHoveredColor); + ImGui::PushStyleColor(ImGuiCol_Button, keyboardButtonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, keyboardButtonHoveredColor); + bool keyboardVisible = mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard]; + if(ImGui::Button( + StringHelper::Sprintf("%s %s Keyboard", keyboardVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, ICON_FA_KEYBOARD_O) + .c_str())) { + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = !keyboardVisible; + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + + for (auto [lusIndex, info] : indexMappings) { + auto [name, sdlIndex] = info; + bool connected = sdlIndex != -1; + + auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); + auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); + + ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); + bool visible = mDeviceIndexVisiblity[lusIndex]; + if(ImGui::Button( + StringHelper::Sprintf("%s %s %s (%s)", visible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(), + connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected") + .c_str())) { + mDeviceIndexVisiblity[lusIndex] = !visible; + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } +} + void SohInputEditorWindow::DrawLinkTab() { uint8_t portIndex = 0; if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1848,6 +1925,7 @@ void SohInputEditorWindow::DrawIvanTab() { if (ImGui::BeginTabItem(StringHelper::Sprintf("Ivan (P2)###port%d", portIndex).c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1903,6 +1981,7 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo : customName.c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1972,133 +2051,6 @@ void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) { } } -#ifdef __WIIU__ -void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { - ImGui::SameLine(); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); - auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex); - if (ImGui::Button(StringHelper::Sprintf("Set defaults...##%d", portIndex).c_str())) { - ImGui::OpenPopup(popupId.c_str()); - } - ImGui::PopStyleVar(); - - if (ImGui::BeginPopup(popupId.c_str())) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), - wiiuIndexMapping->IsWiiUGamepad() ? INT32_MAX - : wiiuIndexMapping->GetDeviceChannel() }; - } - - bool shouldClose = false; - for (auto [lusIndex, info] : indexMappings) { - auto [name, wiiuChannel] = info; - bool isGamepad = wiiuChannel == INT32_MAX; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); - - auto fancyName = StringHelper::Sprintf( - "%s%s", name.c_str(), isGamepad ? "" : StringHelper::Sprintf(" (%d)", wiiuChannel).c_str()); - if (ImGui::Button(StringHelper::Sprintf("%s %s", ICON_FA_GAMEPAD, fancyName.c_str()).c_str())) { - ImGui::OpenPopup(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str()); - } - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - if (ImGui::BeginPopupModal(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str(), NULL, - ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::Text("This will clear all existing mappings for\n%s on port %d.\n\nContinue?", fancyName.c_str(), - portIndex + 1); - if (ImGui::Button("Cancel")) { - shouldClose = true; - ImGui::CloseCurrentPopup(); - } - if (ImGui::Button("Set defaults")) { - Ship::Context::GetInstance() - ->GetControlDeck() - ->GetControllerByPort(portIndex) - ->ClearAllMappingsForDevice(lusIndex); - Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( - lusIndex); - shouldClose = true; - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - } - - if (ImGui::Button("Cancel") || shouldClose) { - ImGui::CloseCurrentPopup(); - } - - ImGui::EndPopup(); - } -} - -void SohInputEditorWindow::DrawDevicesTab() { - if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappingsFromConfig()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), -1 }; - } - - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), - wiiuIndexMapping->IsWiiUGamepad() ? INT32_MAX - : wiiuIndexMapping->GetDeviceChannel() }; - } - - for (auto [lusIndex, info] : indexMappings) { - auto [name, wiiuChannel] = info; - bool connected = wiiuChannel != -1; - bool isGamepad = wiiuChannel == INT32_MAX; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::Button(StringHelper::Sprintf("%s %s%s", connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, - name.c_str(), - !connected ? " (Disconnected)" - : isGamepad ? "" - : StringHelper::Sprintf(" (%d)", wiiuChannel).c_str()) - .c_str()); - ImGui::PopStyleColor(); - ImGui::PopItemFlag(); - } - - ImGui::EndTabItem(); - } -} -#else void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::SameLine(); auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex); @@ -2192,55 +2144,6 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { } } -void SohInputEditorWindow::DrawDevicesTab() { - if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappingsFromConfig()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); - if (sdlIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 }; - } - - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); - if (sdlIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() }; - } - - for (auto [lusIndex, info] : indexMappings) { - auto [name, sdlIndex] = info; - bool connected = sdlIndex != -1; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::Button( - StringHelper::Sprintf("%s %s (%s)", connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(), - connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected") - .c_str()); - ImGui::PopStyleColor(); - ImGui::PopItemFlag(); - } - - ImGui::EndTabItem(); - } -} -#endif - void SohInputEditorWindow::DrawElement() { ImGui::Begin("Controller Configuration###sohControllerConfigWindowV1", &mIsVisible); ImGui::BeginTabBar("##ControllerConfigPortTabs"); @@ -2250,7 +2153,6 @@ void SohInputEditorWindow::DrawElement() { DrawDebugPortTab(2); DrawDebugPortTab(3); } - DrawDevicesTab(); ImGui::EndTabBar(); ImGui::End(); } diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h index b418a041e..aa2c3f4f4 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h @@ -92,7 +92,6 @@ class SohInputEditorWindow : public Ship::GuiWindow { void DrawLinkTab(); void DrawIvanTab(); void DrawDebugPortTab(uint8_t portIndex, std::string customName = ""); - void DrawDevicesTab(); std::set mButtonsBitmasks; std::set mDpadBitmasks; std::set mModifierButtonsBitmasks; @@ -104,4 +103,7 @@ class SohInputEditorWindow : public Ship::GuiWindow { bool mInputEditorPopupOpen; void DrawSetDefaultsButton(uint8_t portIndex); void DrawClearAllButton(uint8_t portIndex); + + std::map mDeviceIndexVisiblity; + void DrawDeviceVisibilityButtons(); }; From 736dccb00b161a007a387b04267bdc30ef91e0af Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sun, 2 Jun 2024 15:34:53 -0400 Subject: [PATCH 254/300] update to latest LUS main (#4202) Includes supporting changes from: * https://github.com/HarbourMasters/Shipwright/pull/4197 (alt assets variable changes) * https://github.com/HarbourMasters/Shipwright/pull/4199 (WindowBackend enum changes) * https://github.com/HarbourMasters/Shipwright/pull/4200 (Extract gMtxClear) --------- Co-authored-by: Malkierian Co-authored-by: inspectredc --- CMake/lus-cvars.cmake | 1 - libultraship | 2 +- soh/assets/xml/GC_MQ_D/code/sys_matrix.xml | 5 +++ .../xml/GC_MQ_D/scenes/dungeons/bdan.xml | 1 + .../xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml | 1 + .../xml/GC_MQ_PAL_F/code/sys_matrix.xml | 5 +++ .../xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml | 1 + .../GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml | 1 + soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml | 5 +++ .../xml/GC_NMQ_D/scenes/dungeons/bdan.xml | 1 + .../GC_NMQ_D/scenes/dungeons/bdan_boss.xml | 1 + .../xml/GC_NMQ_PAL_F/code/sys_matrix.xml | 5 +++ .../xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml | 1 + .../scenes/dungeons/bdan_boss.xml | 1 + soh/assets/xml/N64_PAL_10/code/sys_matrix.xml | 5 +++ .../xml/N64_PAL_10/scenes/dungeons/bdan.xml | 1 + .../N64_PAL_10/scenes/dungeons/bdan_boss.xml | 1 + soh/assets/xml/N64_PAL_11/code/sys_matrix.xml | 5 +++ .../xml/N64_PAL_11/scenes/dungeons/bdan.xml | 1 + .../N64_PAL_11/scenes/dungeons/bdan_boss.xml | 1 + soh/soh/OTRGlobals.cpp | 31 ++++++++++--------- soh/soh/OTRGlobals.h | 1 + soh/soh/SohGui.cpp | 1 - soh/soh/SohMenuBar.cpp | 27 ++++++---------- soh/soh/resource/type/Skeleton.cpp | 7 ++--- soh/src/code/game.c | 2 +- soh/src/code/gfxprint.c | 2 +- 27 files changed, 75 insertions(+), 41 deletions(-) create mode 100644 soh/assets/xml/GC_MQ_D/code/sys_matrix.xml create mode 100644 soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml create mode 100644 soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml create mode 100644 soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml create mode 100644 soh/assets/xml/N64_PAL_10/code/sys_matrix.xml create mode 100644 soh/assets/xml/N64_PAL_11/code/sys_matrix.xml diff --git a/CMake/lus-cvars.cmake b/CMake/lus-cvars.cmake index e7376cfe2..dee8f8c08 100644 --- a/CMake/lus-cvars.cmake +++ b/CMake/lus-cvars.cmake @@ -16,7 +16,6 @@ set(CVAR_STATS_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Stats" CACHE STRING "") set(CVAR_ENABLE_MULTI_VIEWPORTS "${CVAR_PREFIX_SETTING}.EnableMultiViewports" CACHE STRING "") set(CVAR_LOW_RES_MODE "${CVAR_PREFIX_SETTING}.LowResMode" CACHE STRING "") set(CVAR_SIMULATED_INPUT_LAG "${CVAR_PREFIX_SETTING}.SimulatedInputLag" CACHE STRING "") -set(CVAR_ALT_ASSETS "${CVAR_PREFIX_ENHANCEMENT}.AltAssets" CACHE STRING "") set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont" CACHE STRING "") set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar" CACHE STRING "") set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers" CACHE STRING "") diff --git a/libultraship b/libultraship index 9def18e62..fb10cd2fe 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 9def18e62467b4225d26e206e0039a31ed406573 +Subproject commit fb10cd2feb488cf58899a7d5283195fc50b07b23 diff --git a/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml b/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml new file mode 100644 index 000000000..b39033d59 --- /dev/null +++ b/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml index 18d39d57b..9eb1ee61a 100644 --- a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml b/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml new file mode 100644 index 000000000..a3fed368b --- /dev/null +++ b/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml index 18d39d57b..9eb1ee61a 100644 --- a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml b/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml new file mode 100644 index 000000000..ed2a859c6 --- /dev/null +++ b/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml b/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml new file mode 100644 index 000000000..d2143f4e4 --- /dev/null +++ b/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml b/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml new file mode 100644 index 000000000..706c249d4 --- /dev/null +++ b/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml b/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml new file mode 100644 index 000000000..97b57a57c --- /dev/null +++ b/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 12f94e5fd..11ea494d5 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -149,6 +149,8 @@ Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 }; float previousImGuiScale; +bool prevAltAssets = false; + // Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED. typedef struct { Color_RGB8 inner; @@ -320,6 +322,8 @@ OTRGlobals::OTRGlobals() { // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) context->InitResourceManager(OTRFiles, {}, 3); + prevAltAssets = CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0); + context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets); context->InitControlDeck({BTN_MODIFIER1, BTN_MODIFIER2}); context->GetControlDeck()->SetSinglePlayerMappingMode(true); @@ -468,7 +472,7 @@ bool OTRGlobals::HasOriginal() { } uint32_t OTRGlobals::GetInterpolationFPS() { - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { return CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20); } @@ -484,9 +488,6 @@ struct ExtensionEntry { std::string ext; }; -extern uintptr_t clearMtx; -extern "C" Mtx gMtxClear; -extern "C" MtxF gMtxFClear; extern "C" void OTRMessage_Init(); extern "C" void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples); extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len); @@ -1145,7 +1146,6 @@ extern "C" void InitOTR() { GameInteractorSail::Instance = new GameInteractorSail(); #endif - clearMtx = (uintptr_t)&gMtxClear; OTRMessage_Init(); OTRAudio_Init(); OTRExtScanner(); @@ -1254,8 +1254,6 @@ extern "C" uint64_t GetUnixTimestamp() { return (uint64_t)millis.count(); } -extern bool ToggleAltAssetsAtEndOfFrame; - extern "C" void Graph_StartFrame() { #ifndef __WIIU__ using Ship::KbScancode; @@ -1337,7 +1335,7 @@ extern "C" void Graph_StartFrame() { } #endif case KbScancode::LUS_KB_TAB: { - ToggleAltAssetsAtEndOfFrame = true; + CVarSetInteger(CVAR_ENHANCEMENT("AltAssets"), !CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0)); break; } } @@ -1420,11 +1418,10 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { } } - if (ToggleAltAssetsAtEndOfFrame) { - ToggleAltAssetsAtEndOfFrame = false; - - // Actually update the CVar now before runing the alt asset update listeners - CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); + bool curAltAssets = CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0); + if (prevAltAssets != curAltAssets) { + prevAltAssets = curAltAssets; + Ship::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); gfx_texture_cache_clear(); SOH::SkeletonPatcher::UpdateSkeletons(); GameInteractor::Instance->ExecuteHooks(); @@ -1610,10 +1607,14 @@ extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) { return ExtensionCache.contains(path); } +extern "C" bool ResourceMgr_IsAltAssetsEnabled() { + return Ship::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled(); +} + // Unloads a resource if an alternate version exists when alt assets are enabled // The resource is only removed from the internal cache to prevent it from used in the next resource lookup extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { - if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileAltExists((char*) resName)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists((char*)resName)) { ResourceMgr_UnloadResource((char*) resName); } } @@ -1964,7 +1965,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel pathStr = pathStr.substr(sOtr.length()); } - bool isAlt = CVarGetInteger(CVAR_ALT_ASSETS, 0); + bool isAlt = ResourceMgr_IsAltAssetsEnabled(); if (isAlt) { pathStr = Ship::IResource::gAltAssetPrefix + pathStr; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index e0b5c7a38..d0001534a 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -137,6 +137,7 @@ void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); uint64_t GetPerfCounter(); +bool ResourceMgr_IsAltAssetsEnabled(); struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime); void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime); void ResourceMgr_ClearSkeletons(); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 7fde4f351..25763525d 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -43,7 +43,6 @@ #include "Enhancements/resolution-editor/ResolutionEditor.h" #include "Enhancements/debugger/MessageViewer.h" -bool ToggleAltAssetsAtEndOfFrame = false; bool isBetaQuestEnabled = false; extern "C" { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 9cd2c6844..00f7994f5 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -37,7 +37,6 @@ #include "Enhancements/randomizer/randomizer_settings_window.h" #include "Enhancements/resolution-editor/ResolutionEditor.h" -extern bool ToggleAltAssetsAtEndOfFrame; extern bool isBetaQuestEnabled; extern "C" PlayState* gPlayState; @@ -319,7 +318,7 @@ void DrawSettingsMenu() { { // FPS Slider const int minFps = 20; static int maxFps; - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { maxFps = 360; } else { maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); @@ -387,12 +386,12 @@ void DrawSettingsMenu() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); #else bool matchingRefreshRate = - CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11; + CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::FAST3D_DXGI_DX11; UIWidgets::PaddedEnhancementSliderInt( (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps", "##FPSInterpolation", CVAR_SETTING("InterpolationFPS"), minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); #endif - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::Tooltip( "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n" "This is purely visual and does not impact game logic, execution of glitches etc.\n" @@ -407,7 +406,7 @@ void DrawSettingsMenu() { } } // END FPS Slider - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::Spacer(0); if (ImGui::Button("Match Frame Rate to Refresh Rate")) { int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); @@ -421,7 +420,7 @@ void DrawSettingsMenu() { } UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate."); - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", "##ExtraLatencyThreshold", CVAR_SETTING("ExtraLatencyThreshold"), 0, 360, "", 80, true, true, false); UIWidgets::Tooltip( @@ -444,17 +443,16 @@ void DrawSettingsMenu() { UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); static std::unordered_map windowBackendNames = { - { Ship::WindowBackend::DX11, "DirectX" }, - { Ship::WindowBackend::SDL_OPENGL, "OpenGL"}, - { Ship::WindowBackend::SDL_METAL, "Metal" }, - { Ship::WindowBackend::GX2, "GX2"} + { Ship::WindowBackend::FAST3D_DXGI_DX11, "DirectX" }, + { Ship::WindowBackend::FAST3D_SDL_OPENGL, "OpenGL"}, + { Ship::WindowBackend::FAST3D_SDL_METAL, "Metal" } }; ImGui::Text("Renderer API (Needs reload)"); Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend(); Ship::WindowBackend configWindowBackend; int configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); - if (configWindowBackendId != -1 && configWindowBackendId < static_cast(Ship::WindowBackend::BACKEND_COUNT)) { + if (Ship::Context::GetInstance()->GetWindow()->IsAvailableWindowBackend(configWindowBackendId)) { configWindowBackend = static_cast(configWindowBackendId); } else { configWindowBackend = runningWindowBackend; @@ -1086,12 +1084,7 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Graphics")) { if (ImGui::BeginMenu("Mods")) { - if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", CVAR_ALT_ASSETS, false, false)) { - // The checkbox will flip the alt asset CVar, but we instead want it to change at the end of the game frame - // We toggle it back while setting the flag to update the CVar later - CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); - ToggleAltAssetsAtEndOfFrame = true; - } + UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", CVAR_ENHANCEMENT("AltAssets"), false, false); UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not."); UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", CVAR_ENHANCEMENT("DisableBombBillboarding"), true, false); UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects."); diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 8ac676c55..057f24b65 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -65,12 +65,11 @@ void SkeletonPatcher::ClearSkeletons() } void SkeletonPatcher::UpdateSkeletons() { - bool isHD = CVarGetInteger(CVAR_ALT_ASSETS, 0); + auto resourceMgr = Ship::Context::GetInstance()->GetResourceManager(); + bool isHD = resourceMgr->IsAltAssetsEnabled(); for (auto skel : skeletons) { Skeleton* newSkel = - (Skeleton*)Ship::Context::GetInstance()->GetResourceManager() - ->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) - .get(); + (Skeleton*)resourceMgr->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true).get(); if (newSkel != nullptr) { skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment; diff --git a/soh/src/code/game.c b/soh/src/code/game.c index f0988c7c3..aa0670a21 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -467,7 +467,7 @@ void GameState_Destroy(GameState* gameState) { // Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system. ResourceMgr_ClearSkeletons(); - if (CVarGetInteger(CVAR_ALT_ASSETS, 0)) { + if (ResourceMgr_IsAltAssetsEnabled()) { ResourceUnloadDirectory("alt/*"); gfx_texture_cache_clear(); } diff --git a/soh/src/code/gfxprint.c b/soh/src/code/gfxprint.c index 1717e46b3..6d8686074 100644 --- a/soh/src/code/gfxprint.c +++ b/soh/src/code/gfxprint.c @@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt; // https://github.com/HarbourMasters/Shipwright/issues/2762 typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t; font_texture_t GfxPrint_TextureToUse() { - if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { // If we have alt assets enabled, and we have alt prefixed font texture, use that return otrAlt; } else if (ResourceMgr_FileExists(rGfxPrintFontData)) { From 4441304dfd5706f335d2ee9418b6e4373262c752 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 14 Jun 2024 13:40:39 -0400 Subject: [PATCH 255/300] support LUS not providing an array resource type/factory (#4204) * support LUS not providing an array resource type/factory * bump to latest upstream --- OTRExporter | 2 +- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 13 ++-- soh/soh/resource/importer/ArrayFactory.cpp | 64 ++++++++++++++++ soh/soh/resource/importer/ArrayFactory.h | 11 +++ soh/soh/resource/type/Array.cpp | 45 ++++++++++++ soh/soh/resource/type/Array.h | 85 ++++++++++++++++++++++ soh/soh/resource/type/SohResourceType.h | 1 + 8 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 soh/soh/resource/importer/ArrayFactory.cpp create mode 100644 soh/soh/resource/importer/ArrayFactory.h create mode 100644 soh/soh/resource/type/Array.cpp create mode 100644 soh/soh/resource/type/Array.h diff --git a/OTRExporter b/OTRExporter index d70db9806..2cfdb3960 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit d70db9806c02c229ca3ed928ad0bdae128fe4ac7 +Subproject commit 2cfdb3960900ba059f570b2ded2fed3494a96a9b diff --git a/libultraship b/libultraship index fb10cd2fe..c7974d6a2 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit fb10cd2feb488cf58899a7d5283195fc50b07b23 +Subproject commit c7974d6a25853d65b44905df728a0e0249636947 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 11ea494d5..2d7e1fcd5 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -22,7 +22,6 @@ #else #include #endif -#include #include #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include "Enhancements/controls/SohInputEditorWindow.h" @@ -108,12 +107,12 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/type/Skeleton.h" #include "soh/resource/type/SkeletonLimb.h" #include "soh/resource/type/Text.h" -#include "resource/factory/ArrayFactory.h" #include "resource/factory/BlobFactory.h" #include "resource/factory/DisplayListFactory.h" #include "resource/factory/MatrixFactory.h" #include "resource/factory/TextureFactory.h" #include "resource/factory/VertexFactory.h" +#include "soh/resource/importer/ArrayFactory.h" #include "soh/resource/importer/AnimationFactory.h" #include "soh/resource/importer/AudioSampleFactory.h" #include "soh/resource/importer/AudioSequenceFactory.h" @@ -351,8 +350,8 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Matrix", static_cast(LUS::ResourceType::Matrix), 0); - loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Array", static_cast(LUS::ResourceType::Array), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Blob", static_cast(LUS::ResourceType::Blob), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Array", static_cast(SOH::ResourceType::SOH_Array), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Animation", static_cast(SOH::ResourceType::SOH_Animation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast(SOH::ResourceType::SOH_PlayerAnimation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? @@ -1697,8 +1696,8 @@ extern "C" char* ResourceMgr_LoadTexOrDListByName(const char* filePath) { if (res->GetInitData()->Type == static_cast(LUS::ResourceType::DisplayList)) return (char*)&((std::static_pointer_cast(res))->Instructions[0]); - else if (res->GetInitData()->Type == static_cast(LUS::ResourceType::Array)) - return (char*)(std::static_pointer_cast(res))->Vertices.data(); + else if (res->GetInitData()->Type == static_cast(SOH::ResourceType::SOH_Array)) + return (char*)(std::static_pointer_cast(res))->Vertices.data(); else { return (char*)GetResourceDataByNameHandlingMQ(filePath); } @@ -1828,13 +1827,13 @@ extern "C" void ResourceMgr_UnpatchGfxByName(const char* path, const char* patch extern "C" char* ResourceMgr_LoadArrayByName(const char* path) { - auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); + auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); return (char*)res->Scalars.data(); } extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) { - auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); + auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); // if (res->CachedGameAsset != nullptr) // return (char*)res->CachedGameAsset; diff --git a/soh/soh/resource/importer/ArrayFactory.cpp b/soh/soh/resource/importer/ArrayFactory.cpp new file mode 100644 index 000000000..39be7c093 --- /dev/null +++ b/soh/soh/resource/importer/ArrayFactory.cpp @@ -0,0 +1,64 @@ +#include "soh/resource/importer/ArrayFactory.h" +#include "soh/resource/type/Array.h" +#include "spdlog/spdlog.h" +#include "graphic/Fast3D/lus_gbi.h" + +namespace SOH { +std::shared_ptr ResourceFactoryBinaryArrayV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto array = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + array->ArrayType = (ArrayResourceType)reader->ReadUInt32(); + array->ArrayCount = reader->ReadUInt32(); + + for (uint32_t i = 0; i < array->ArrayCount; i++) { + if (array->ArrayType == ArrayResourceType::Vertex) { + // OTRTODO: Implement Vertex arrays as just a vertex resource. + F3DVtx data; + data.v.ob[0] = reader->ReadInt16(); + data.v.ob[1] = reader->ReadInt16(); + data.v.ob[2] = reader->ReadInt16(); + data.v.flag = reader->ReadUInt16(); + data.v.tc[0] = reader->ReadInt16(); + data.v.tc[1] = reader->ReadInt16(); + data.v.cn[0] = reader->ReadUByte(); + data.v.cn[1] = reader->ReadUByte(); + data.v.cn[2] = reader->ReadUByte(); + data.v.cn[3] = reader->ReadUByte(); + array->Vertices.push_back(data); + } else { + array->ArrayScalarType = (ScalarType)reader->ReadUInt32(); + + int iter = 1; + + if (array->ArrayType == ArrayResourceType::Vector) { + iter = reader->ReadUInt32(); + } + + for (int k = 0; k < iter; k++) { + ScalarData data; + + switch (array->ArrayScalarType) { + case ScalarType::ZSCALAR_S16: + data.s16 = reader->ReadInt16(); + break; + case ScalarType::ZSCALAR_U16: + data.u16 = reader->ReadUInt16(); + break; + default: + // OTRTODO: IMPLEMENT OTHER TYPES! + break; + } + + array->Scalars.push_back(data); + } + } + } + + return array; +} +} // namespace LUS diff --git a/soh/soh/resource/importer/ArrayFactory.h b/soh/soh/resource/importer/ArrayFactory.h new file mode 100644 index 000000000..b9f5ca75b --- /dev/null +++ b/soh/soh/resource/importer/ArrayFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "resource/Resource.h" +#include "resource/ResourceFactoryBinary.h" + +namespace SOH { +class ResourceFactoryBinaryArrayV0 : public Ship::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} // namespace LUS diff --git a/soh/soh/resource/type/Array.cpp b/soh/soh/resource/type/Array.cpp new file mode 100644 index 000000000..70d5d42ba --- /dev/null +++ b/soh/soh/resource/type/Array.cpp @@ -0,0 +1,45 @@ +#include "Array.h" +#include "graphic/Fast3D/lus_gbi.h" +namespace SOH { +Array::Array() : Resource(std::shared_ptr()) { +} + +void* Array::GetPointer() { + void* dataPointer = nullptr; + switch (ArrayType) { + case ArrayResourceType::Vertex: + dataPointer = Vertices.data(); + break; + case ArrayResourceType::Scalar: + default: + dataPointer = Scalars.data(); + break; + } + + return dataPointer; +} + +size_t Array::GetPointerSize() { + size_t typeSize = 0; + switch (ArrayType) { + case ArrayResourceType::Vertex: + typeSize = sizeof(F3DVtx); + break; + case ArrayResourceType::Scalar: + default: + switch (ArrayScalarType) { + case ScalarType::ZSCALAR_S16: + typeSize = sizeof(int16_t); + break; + case ScalarType::ZSCALAR_U16: + typeSize = sizeof(uint16_t); + break; + default: + // OTRTODO: IMPLEMENT OTHER TYPES! + break; + } + break; + } + return ArrayCount * typeSize; +} +} // namespace LUS diff --git a/soh/soh/resource/type/Array.h b/soh/soh/resource/type/Array.h new file mode 100644 index 000000000..ba41ec049 --- /dev/null +++ b/soh/soh/resource/type/Array.h @@ -0,0 +1,85 @@ +#pragma once + +#include "resource/Resource.h" + +union F3DVtx; +namespace SOH { +typedef union ScalarData { + uint8_t u8; + int8_t s8; + uint16_t u16; + int16_t s16; + uint32_t u32; + int32_t s32; + uint64_t u64; + int64_t s64; + float f32; + double f64; +} ScalarData; + +enum class ScalarType { + ZSCALAR_NONE, + ZSCALAR_S8, + ZSCALAR_U8, + ZSCALAR_X8, + ZSCALAR_S16, + ZSCALAR_U16, + ZSCALAR_X16, + ZSCALAR_S32, + ZSCALAR_U32, + ZSCALAR_X32, + ZSCALAR_S64, + ZSCALAR_U64, + ZSCALAR_X64, + ZSCALAR_F32, + ZSCALAR_F64 +}; + +// OTRTODO: Replace this with something that can be shared between the exporter and importer... +enum class ArrayResourceType { + Error, + Animation, + Array, + AltHeader, + Background, + Blob, + CollisionHeader, + Cutscene, + DisplayList, + Limb, + LimbTable, + Mtx, + Path, + PlayerAnimationData, + Room, + RoomCommand, + Scalar, + Scene, + Skeleton, + String, + Symbol, + Texture, + TextureAnimation, + TextureAnimationParams, + Vector, + Vertex, + Audio +}; + +class Array : public Ship::Resource { + public: + using Resource::Resource; + + Array(); + + void* GetPointer() override; + size_t GetPointerSize() override; + + ArrayResourceType ArrayType; + ScalarType ArrayScalarType; + size_t ArrayCount; + // OTRTODO: Should be a vector of resource pointers... + std::vector Scalars; + std::vector Vertices; +}; +} // namespace LUS diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index fdf39031e..6455c28c7 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -2,6 +2,7 @@ namespace SOH { enum class ResourceType { + SOH_Array = 0x4F415252, // OARR SOH_Animation = 0x4F414E4D, // OANM SOH_PlayerAnimation = 0x4F50414D, // OPAM SOH_Room = 0x4F524F4D, // OROM From cd7c5ab316cb3f48bedea399e1adda2cd28f75e0 Mon Sep 17 00:00:00 2001 From: Archez Date: Sat, 15 Jun 2024 23:13:13 -0400 Subject: [PATCH 256/300] Clear the framebuffer for the pause menu link texture (#4213) * clear pause menu link framebuffer * cache bust * Add enums for pause menu link width/height and rename the framebuffer * revert cache bust --- libultraship | 2 +- soh/include/z64.h | 3 ++ soh/src/code/game.c | 11 +++--- soh/src/code/z_player_lib.c | 38 ++++++++++++++----- .../ovl_kaleido_scope/z_kaleido_equipment.c | 10 ++--- .../ovl_kaleido_scope/z_kaleido_scope_PAL.c | 4 +- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/libultraship b/libultraship index c7974d6a2..9907ebfd6 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit c7974d6a25853d65b44905df728a0e0249636947 +Subproject commit 9907ebfd66ff5bf903ecb7327cca69014993772b diff --git a/soh/include/z64.h b/soh/include/z64.h index bad2e1ca7..7a4cb193d 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -841,6 +841,9 @@ typedef enum { #define PAUSE_CURSOR_PAGE_LEFT 10 #define PAUSE_CURSOR_PAGE_RIGHT 11 +#define PAUSE_EQUIP_PLAYER_WIDTH 64 +#define PAUSE_EQUIP_PLAYER_HEIGHT 112 + typedef enum { /* 0x00 */ PAUSE_ITEM, /* 0x01 */ PAUSE_MAP, diff --git a/soh/src/code/game.c b/soh/src/code/game.c index aa0670a21..e1974ed98 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -239,16 +239,15 @@ void GameState_ReqPadData(GameState* gameState) { PadMgr_RequestPadData(&gPadMgr, &gameState->input[0], 1); } -// OTRTODO -int fbTest = -1; +// Framebuffer for the Link preview on the pause menu equipment sub-screen +int gPauseLinkFrameBuffer = -1; void GameState_Update(GameState* gameState) { GraphicsContext* gfxCtx = gameState->gfxCtx; - if (fbTest == -1) - { - fbTest = gfx_create_framebuffer(64, 112, SCREEN_WIDTH, SCREEN_HEIGHT, true); - //fbTest = gfx_create_framebuffer(256, 512); + if (gPauseLinkFrameBuffer == -1) { + gPauseLinkFrameBuffer = gfx_create_framebuffer(PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, + PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, true); } GameState_SetFrameBuffer(gfxCtx); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index b9ef17f6e..4b790122f 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -2075,10 +2075,12 @@ void Pause_DrawTriforceSpot(PlayState* play, s32 showLightColumn) { rotation += 0x03E8; } -void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* skelAnime, Vec3f* pos, Vec3s* rot, - f32 scale, s32 sword, s32 tunic, s32 shield, s32 boots, s32 width, s32 height, Vec3f* eye, Vec3f* at, - f32 fovy, void* img1, void* img2) { - static Vp viewport = { 128, 224, 511, 0, 128, 224, 511, 0 }; +void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject, SkelAnime* skelAnime, Vec3f* pos, + Vec3s* rot, f32 scale, s32 sword, s32 tunic, s32 shield, s32 boots, s32 width, s32 height, + Vec3f* eye, Vec3f* at, f32 fovy, void* colorFrameBuffer, void* depthFrameBuffer) { + // Note: the viewport x and y values are overwritten below, before usage + static Vp viewport = { (PAUSE_EQUIP_PLAYER_WIDTH / 2) << 2, (PAUSE_EQUIP_PLAYER_HEIGHT / 2) << 2, G_MAXZ / 2, 0, + (PAUSE_EQUIP_PLAYER_WIDTH / 2) << 2, (PAUSE_EQUIP_PLAYER_HEIGHT / 2) << 2, G_MAXZ / 2, 0 }; static Lights1 lights1 = gdSPDefLights1(80, 80, 80, 255, 255, 255, 84, 84, 172); static Vec3f lightDir = { 89.8f, 0.0f, 89.8f }; u8 playerSwordAndShield[2]; @@ -2106,6 +2108,24 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* gDPSetScissor(POLY_OPA_DISP++, G_SC_NON_INTERLACE, 0, 0, width, height); gSPClipRatio(POLY_OPA_DISP++, FRUSTRATIO_1); + gDPSetColorImage(POLY_OPA_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, depthFrameBuffer); + gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); + gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(POLY_OPA_DISP++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); + gDPFillRectangle(POLY_OPA_DISP++, 0, 0, width - 1, height - 1); + + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetColorImage(POLY_OPA_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, colorFrameBuffer); + gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); + gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(POLY_OPA_DISP++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); + gDPFillRectangle(POLY_OPA_DISP++, 0, 0, width - 1, height - 1); + + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetDepthImage(POLY_OPA_DISP++, depthFrameBuffer); + viewport.vp.vscale[0] = viewport.vp.vtrans[0] = width * 2; viewport.vp.vscale[1] = viewport.vp.vtrans[1] = height * 2; gSPViewport(POLY_OPA_DISP++, &viewport); @@ -2126,8 +2146,8 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* pos->y - (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0) ? 16 : 0), pos->z, rot); Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale, scale, MTXMODE_APPLY); - gSPSegment(POLY_OPA_DISP++, 0x04, seg04); - gSPSegment(POLY_OPA_DISP++, 0x06, seg06); + gSPSegment(POLY_OPA_DISP++, 0x04, gameplayKeep); + gSPSegment(POLY_OPA_DISP++, 0x06, linkObject); gSPSetLights1(POLY_OPA_DISP++, lights1); @@ -2401,8 +2421,8 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* } } - Player_DrawPauseImpl(play, segment + 0x3800, segment + 0x8800, skelAnime, pos, rot, scale, sword, tunic, shield, - boots, 64, 112, &eye, &at, 60.0f, play->state.gfxCtx->curFrameBuffer, - play->state.gfxCtx->curFrameBuffer + 0x1C00); + boots, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, &eye, &at, 60.0f, + play->state.gfxCtx->curFrameBuffer, + play->state.gfxCtx->curFrameBuffer + (PAUSE_EQUIP_PLAYER_WIDTH * PAUSE_EQUIP_PLAYER_HEIGHT)); } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 99ba5df72..116ad0c3c 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -27,6 +27,8 @@ static Vtx sStrengthAButtonVtx[] = { static s16 sEquipTimer = 0; +extern int gPauseLinkFrameBuffer; + void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u32 height) { PauseContext* pauseCtx = &play->pauseCtx; u8* curTexture; @@ -70,13 +72,12 @@ void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u for (i = 0; i < textureCount; i++) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->equipVtx[vtxIndex], 4, 0); - extern int fbTest; gDPSetTextureImage(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, curTexture); gDPLoadSync(POLY_KAL_DISP++); gDPLoadTile(POLY_KAL_DISP++, G_TX_LOADTILE, 0, 0, (width - 1) << 2, (textureHeight - 1) << 2); - gDPSetTextureImageFB(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, fbTest); + gDPSetTextureImageFB(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, gPauseLinkFrameBuffer); gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); curTexture += textureSize; @@ -185,8 +186,7 @@ void KaleidoScope_DrawPlayerWork(PlayState* play) { link_kaleido_rot.x = 0; - extern int fbTest; - gsSPSetFB(play->state.gfxCtx->polyOpa.p++, fbTest); + gsSPSetFB(play->state.gfxCtx->polyOpa.p++, gPauseLinkFrameBuffer); Player_DrawPause(play, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &link_kaleido_rot, scale, SWORD_EQUIP_TO_PLAYER(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD)), TUNIC_EQUIP_TO_PLAYER(CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC)), @@ -852,7 +852,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { //gSPSegment(POLY_KAL_DISP++, 0x0C, pauseCtx->iconItemAltSegment); Gfx_SetupDL_42Kal(play->state.gfxCtx); - KaleidoScope_DrawEquipmentImage(play, pauseCtx->playerSegment, 64, 112); + KaleidoScope_DrawEquipmentImage(play, pauseCtx->playerSegment, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT); if (gUpgradeMasks[0]) {} diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 424c823d6..a8b7536f0 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -929,7 +929,6 @@ static void* sPromptChoiceTexs[][2] = { static u8 sButtonStatusSave[ARRAY_COUNT(gSaveContext.buttonStatus)]; static PreRender sPlayerPreRender; static void* sPreRenderCvg; -extern int fbTest; void KaleidoScope_ProcessPlayerPreRender(void) { PreRender_Calc(&sPlayerPreRender); @@ -3725,7 +3724,8 @@ void KaleidoScope_Update(PlayState* play) sPreRenderCvg = (void*)(((uintptr_t)pauseCtx->nameSegment + 0x400 + 0xA00 + 0xF) & ~0xF); PreRender_Init(&sPlayerPreRender); - PreRender_SetValuesSave(&sPlayerPreRender, 64, 112, pauseCtx->playerSegment, NULL, sPreRenderCvg); + PreRender_SetValuesSave(&sPlayerPreRender, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, + pauseCtx->playerSegment, NULL, sPreRenderCvg); KaleidoScope_DrawPlayerWork(play); //KaleidoScope_SetupPlayerPreRender(play); From f99993af85c744eed8b298283178e8d9a87a043a Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:28:42 +0200 Subject: [PATCH 257/300] Reduce stack usage during static initialization (#4184) * Reduce stack usage during static initialization * Implement `ABS` macro for `TWO_ACTOR_PARAMS` --- soh/soh/ActorDB.cpp | 7 +++-- .../Enhancements/item-tables/ItemTableTypes.h | 2 +- .../Enhancements/randomizer/randomizer.cpp | 28 +++++++++---------- .../randomizer/randomizer_check_objects.cpp | 3 +- .../randomizer/randomizer_check_objects.h | 9 ++++-- .../randomizer/randomizer_check_tracker.cpp | 2 +- .../randomizer/randomizer_tricks.cpp | 3 +- .../randomizer/randomizer_tricks.h | 4 +-- 8 files changed, 32 insertions(+), 26 deletions(-) diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp index ea8450ac4..de2538888 100644 --- a/soh/soh/ActorDB.cpp +++ b/soh/soh/ActorDB.cpp @@ -16,7 +16,7 @@ ActorDB* ActorDB::Instance; #undef DEFINE_ACTOR_UNSET struct AddPair { - std::string name; + const char* name; ActorInit& init; }; @@ -24,7 +24,7 @@ struct AddPair { #define DEFINE_ACTOR(name, _1, allocType) { #name, name##_InitVars }, #define DEFINE_ACTOR_UNSET(_0) -static const std::vector initialActorTable = { +static constexpr AddPair initialActorTable[] = { #include "tables/actor_table.h" }; @@ -33,7 +33,7 @@ static const std::vector initialActorTable = { #undef DEFINE_ACTOR // https://wiki.cloudmodding.com/oot/Actor_List_(Variables) -static std::unordered_map actorDescriptions = { +static constexpr std::pair actorDescriptionData[] = { { ACTOR_PLAYER, "Link" }, { ACTOR_EN_TEST, "Stalfos" }, { ACTOR_EN_GIRLA, "Shop Items" }, @@ -464,6 +464,7 @@ static std::unordered_map actorDescriptions = { { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } }; +static std::unordered_map actorDescriptions = std::unordered_map(std::begin(actorDescriptionData), std::end(actorDescriptionData)); ActorDB::ActorDB() { db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each diff --git a/soh/soh/Enhancements/item-tables/ItemTableTypes.h b/soh/soh/Enhancements/item-tables/ItemTableTypes.h index 6282275b1..28e70dc95 100644 --- a/soh/soh/Enhancements/item-tables/ItemTableTypes.h +++ b/soh/soh/Enhancements/item-tables/ItemTableTypes.h @@ -59,4 +59,4 @@ typedef struct GetItemEntry { /* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps. /* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps. CustomDrawFunc drawFunc; -}; // size = 0x11 +} GetItemEntry; // size = 0x11 diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 107e23e83..5ea7293eb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4660,7 +4660,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasItems = false; for (auto& [randomizerCheck, rcObject] : rcObjects) { if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) && - locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) { + locationSearch.PassFilter(rcObject->rcSpoilerName)) { hasItems = true; break; @@ -4672,7 +4672,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { for (auto& [randomizerCheck, rcObject] : rcObjects) { if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) && - locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) { + locationSearch.PassFilter(rcObject->rcSpoilerName)) { if (ImGui::ArrowButton(std::to_string(rcObject->rc).c_str(), ImGuiDir_Right)) { excludedLocations.insert(rcObject->rc); @@ -4686,7 +4686,7 @@ void RandomizerSettingsWindow::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); - ImGui::Text("%s", rcObject->rcShortName.c_str()); + ImGui::Text("%s", rcObject->rcShortName); } } ImGui::TreePop(); @@ -4731,7 +4731,7 @@ void RandomizerSettingsWindow::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); - ImGui::Text("%s", rcObject->rcShortName.c_str()); + ImGui::Text("%s", rcObject->rcShortName); } } ImGui::TreePop(); @@ -4997,7 +4997,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::Button("Enable Visible")) { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { for (auto [randomizerTrick, rtObject] : rtObjects) { - if (!rtObject.rtGlitch && !enabledTricks.count(rtObject.rt) && trickSearch.PassFilter(rtObject.rtShortName.c_str()) && areaTreeDisabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { + if (!rtObject.rtGlitch && !enabledTricks.count(rtObject.rt) && trickSearch.PassFilter(rtObject.rtShortName) && areaTreeDisabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { enabledTricks.insert(randomizerTrick); } } @@ -5017,7 +5017,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasTricks = false; for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && !enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5032,7 +5032,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::TreeNode(RandomizerTricks::GetRTAreaName(rtArea).c_str())) { for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && !enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5048,8 +5048,8 @@ void RandomizerSettingsWindow::DrawElement() { } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); - ImGui::Text("%s", rtObject.rtShortName.c_str()); - UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str()); + ImGui::Text("%s", rtObject.rtShortName); + UIWidgets::InsertHelpHoverText(rtObject.rtDesc); } } areaTreeDisabled[rtArea] = true; @@ -5107,7 +5107,7 @@ void RandomizerSettingsWindow::DrawElement() { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { for (auto [randomizerTrick, rtObject] : rtObjects) { auto etfound = enabledTricks.find(randomizerTrick); - if (!rtObject.rtGlitch && etfound != enabledTricks.end() && trickSearch.PassFilter(rtObject.rtShortName.c_str()) && areaTreeEnabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { + if (!rtObject.rtGlitch && etfound != enabledTricks.end() && trickSearch.PassFilter(rtObject.rtShortName) && areaTreeEnabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { enabledTricks.erase(etfound); } } @@ -5127,7 +5127,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasTricks = false; for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5143,7 +5143,7 @@ void RandomizerSettingsWindow::DrawElement() { for (auto [randomizerTrick, rtObject] : rtObjects) { auto etfound = enabledTricks.find(rtObject.rt); if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && etfound != enabledTricks.end() && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5164,8 +5164,8 @@ void RandomizerSettingsWindow::DrawElement() { } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); - ImGui::Text("%s", rtObject.rtShortName.c_str()); - UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str()); + ImGui::Text("%s", rtObject.rtShortName); + UIWidgets::InsertHelpHoverText(rtObject.rtDesc); } } areaTreeEnabled[rtArea] = true; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index b97a6f335..e3dcf4673 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -6,7 +6,7 @@ #include "soh/OTRGlobals.h" // RandomizerCheck, RCVORMQ, RCTYPE, RCAREA, ActorId, SceneId, ActorParams, OG ItemID, "Short name", "Spoiler name", vanillaCompletion -std::map rcObjects = { +static constexpr std::pair rcObjectsData[] = { RC_OBJECT(RC_KF_KOKIRI_SWORD_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, GI_SWORD_KOKIRI, "Kokiri Sword Chest", "KF Kokiri Sword Chest", true), RC_OBJECT(RC_KF_MIDOS_TOP_LEFT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, GI_RUPEE_BLUE, "Mido Top Left Chest", "KF Mido Top Left Chest", false), RC_OBJECT(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, GI_RUPEE_BLUE, "Mido Top Right Chest", "KF Mido Top Right Chest", false), @@ -775,6 +775,7 @@ std::map rcObjects = { RC_OBJECT(RC_UNKNOWN_CHECK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Invalid Check", "Invalid Check", false), }; +std::map rcObjects = std::map(std::begin(rcObjectsData), std::end(rcObjectsData)); std::map rcAreaNames = { { RCAREA_KOKIRI_FOREST, "Kokiri Forest"}, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h index dc9bd2010..e2b784135 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h @@ -7,7 +7,10 @@ enum ActorID : int; enum SceneID : int; -#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) +// ABS macro to use since `std::abs` is not constexpr yet +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +#define TWO_ACTOR_PARAMS(a, b) (ABS(a) << 16) | ABS(b) #define RC_OBJECT(rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, rc_shortname, rc_spoilername, vanillaCompletion) \ { rc, {rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, false, rc_shortname, rc_spoilername, vanillaCompletion} } @@ -22,8 +25,8 @@ typedef struct { int32_t actorParams; GetItemID ogItemId; bool visibleInImgui; - std::string rcShortName; - std::string rcSpoilerName; + const char* rcShortName; + const char* rcSpoilerName; bool vanillaCompletion; } RandomizerCheckObject; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index aca75ef93..02952a052 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1089,7 +1089,7 @@ bool ShouldShowCheck(RandomizerCheckObject check) { IsVisibleInCheckTracker(check) && (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(check.rcArea).c_str()) || - checkSearch.PassFilter(check.rcShortName.c_str())) + checkSearch.PassFilter(check.rcShortName)) ); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp b/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp index 8a397f840..4b704ccc0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp @@ -21,7 +21,7 @@ std::vector extremeBase{RTTAG_EXTREME}; // Experimental - not implemented; these tricks may let you put the game into a softlockable state // Please see https://www.youtube.com/playlist?list=PLqsXSioZwQyoa23_27l5NZq5IZdKRi5Sm for reference on performing several of these tricks // RandomizerTrick, RTVORMQ, RTAREA, rt_tags rt_glitch (is it a glitch) "Short name", "Description" -std::unordered_map rtObjects = { +static constexpr std::pair rtObjectsData[] = { RT_OBJECT(RT_ACUTE_ANGLE_CLIP, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Acute angle clip", "Enables locations requiring jumpslash clips through walls which meet at an acute angle."), RT_OBJECT(RT_ADVANCED_CLIPS, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Advanced clips", "Enables locations requiring clips through walls and objects requiring precise jumps or other tricks."), RT_OBJECT(RT_BLANK_A, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Blank A", "Enables locations requiring blank A button; NOTE: this requires the 'Quick Putaway' restoration."), @@ -208,6 +208,7 @@ std::unordered_map rtObjects = { RT_OBJECT(RT_GANON_MQ_SHADOW_TRIAL, RTVORMQ_MQ, RTAREA_GANONS_CASTLE, &noviceBase, false, "Shadow Trial MQ Torch with Bow", "You can light the torch in this room without a fire source by shooting an arrow through the lit torch at the beginning of the room. Because the room is so dark and the unlit torch is so far away, it can be difficult to aim the shot correctly."), RT_OBJECT(RT_GANON_MQ_LIGHT_TRIAL, RTVORMQ_MQ, RTAREA_GANONS_CASTLE, &intermediateBase, /*todo*/ false, "Light Trial MQ without Hookshot", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. In this case to do it without taking damage is especially precise.") }; +std::unordered_map rtObjects = std::unordered_map(std::begin(rtObjectsData), std::end(rtObjectsData)); std::unordered_map rtAreaNames = { { RTAREA_GENERAL, "General Tricks"}, diff --git a/soh/soh/Enhancements/randomizer/randomizer_tricks.h b/soh/soh/Enhancements/randomizer/randomizer_tricks.h index 6fb4a4341..5d1df34d4 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_tricks.h +++ b/soh/soh/Enhancements/randomizer/randomizer_tricks.h @@ -71,8 +71,8 @@ typedef struct { std::vector *rtTags; bool rtGlitch; bool visibleInImgui; - std::string rtShortName; - std::string rtDesc; + const char* rtShortName; + const char* rtDesc; } RandomizerTrickObject; namespace RandomizerTricks { From 79a29a62efc60865c9fe55eae8f665d4ca073249 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sun, 16 Jun 2024 04:43:09 +0100 Subject: [PATCH 258/300] Use correct default value (#4194) --- soh/src/code/z_message_PAL.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 87cff43da..3c77c300c 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1115,7 +1115,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { } } if (msgCtx->textDelayTimer == 0) { - msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 2); + msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 1); msgCtx->textDelayTimer = msgCtx->textDelay; } else { msgCtx->textDelayTimer--; From 839fcffe17f00671baa6fb411cba74f42a7b5f5d Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:47:35 +0200 Subject: [PATCH 259/300] Add Alternate Headers XML logger (#4207) --- .../importer/scenecommand/SetAlternateHeadersFactory.cpp | 3 ++- soh/soh/resource/logging/SceneCommandLoggers.cpp | 6 ++++++ soh/soh/resource/type/scenecommand/SetAlternateHeaders.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp index c04f717c3..f5ac8914e 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp @@ -17,6 +17,7 @@ std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::s auto headerName = reader->ReadString(); if (!headerName.empty()) { setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + setAlternateHeaders->headerFileNames.push_back(headerName); } else { setAlternateHeaders->headers.push_back(nullptr); } @@ -41,7 +42,7 @@ std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std std::string childName = child->Name(); if (childName == "AlternateHeader") { for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { - auto headerName = std::string(child->Attribute("HeaderName")); + auto headerName = std::string(child->Attribute("Path")); if (!headerName.empty()) { setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); } else { diff --git a/soh/soh/resource/logging/SceneCommandLoggers.cpp b/soh/soh/resource/logging/SceneCommandLoggers.cpp index 7c55bcaf0..805de9be0 100644 --- a/soh/soh/resource/logging/SceneCommandLoggers.cpp +++ b/soh/soh/resource/logging/SceneCommandLoggers.cpp @@ -73,6 +73,12 @@ void LogAlternateHeadersAsXML(std::shared_ptr resource) { tinyxml2::XMLElement* root = doc.NewElement("SetAlternateHeaders"); doc.InsertFirstChild(root); + for (size_t i = 0; i < setAlternateHeaders->headerFileNames.size(); i++) { + tinyxml2::XMLElement* entry = doc.NewElement("Header"); + entry->SetAttribute("Path", setAlternateHeaders->headerFileNames[i].c_str()); + root->InsertEndChild(entry); + } + tinyxml2::XMLPrinter printer; doc.Accept(&printer); diff --git a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h index fdddee3f8..596e0a22e 100644 --- a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h +++ b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h @@ -21,6 +21,7 @@ class SetAlternateHeaders : public SceneCommand { size_t GetPointerSize(); uint32_t numHeaders; + std::vector headerFileNames; std::vector> headers; }; }; // namespace LUS From 510b655e5e7a8bc53ced1123e1509cd9e3d21a09 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:35:47 +0100 Subject: [PATCH 260/300] Fix Link's Pocket Appearing in Hints. (#4191) * Fix issues with areas not being applied to the region itself, and Link's Pocket Propogating through randomised warps * Address reviews * address reviews again * fix mac issues * git pls --- .../Enhancements/randomizer/3drando/fill.cpp | 22 ++++++++++--------- .../Enhancements/randomizer/3drando/hints.cpp | 2 +- .../randomizer/3drando/location_access.hpp | 5 ++++- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 6b23c6f2d..d25d04aa0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -485,18 +485,19 @@ static void GeneratePlaythrough() { GetAccessibleLocations(ctx->allLocations, SearchMode::GeneratePlaythrough); } -RandomizerArea LookForExternalArea(Area* curRegion, std::vector alreadyChecked){//RANDOTODO curREGION - for (auto& entrance : curRegion->entrances) { +RandomizerArea LookForExternalArea(const Area* const currentRegion, std::vector &alreadyChecked){ + for (const auto& entrance : currentRegion->entrances) { RandomizerArea otherArea = entrance->GetParentRegion()->GetArea(); - if(otherArea != RA_NONE){ - return otherArea; - //if the area hasn't already been checked, check it - } else if (std::find(alreadyChecked.begin(), alreadyChecked.end(), entrance->GetParentRegionKey()) == alreadyChecked.end()) { + const bool isAreaUnchecked = std::find(alreadyChecked.begin(), alreadyChecked.end(), entrance->GetParentRegionKey()) == alreadyChecked.end(); + if (otherArea == RA_NONE && isAreaUnchecked) { + //if the region is in RA_NONE and hasn't already been checked, check it alreadyChecked.push_back(entrance->GetParentRegionKey()); - RandomizerArea passdown = LookForExternalArea(entrance->GetParentRegion(), alreadyChecked); + const RandomizerArea passdown = LookForExternalArea(entrance->GetParentRegion(), alreadyChecked); if(passdown != RA_NONE){ return passdown; } + } else if (otherArea != RA_LINKS_POCKET){ //if it's links pocket, do not propogate this, Link's Pocket is not a real Area + return otherArea; } } return RA_NONE; @@ -505,16 +506,17 @@ RandomizerArea LookForExternalArea(Area* curRegion, std::vector alreadyChecked = {(RandomizerRegion)c}; + std::vector alreadyChecked = {static_cast(regionType)}; area = LookForExternalArea(®ion, alreadyChecked); } for (auto& loc : region.locations){ ctx->GetItemLocation(loc.GetLocation())->SetArea(area); } + areaTable[regionType].SetArea(area); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 1f195251b..d571c1ab5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -496,7 +496,7 @@ void CreateWarpSongTexts() { if (ctx->GetOption(RSK_WARP_SONG_HINTS)){ auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); for (auto entrance : warpSongEntrances) { - auto destination = entrance->GetConnectedRegion()->GetArea();//KNOWN ISSUE: says links pocket sometimes, putting off as this will need rewriting when entrance hits are added anyway + const auto destination = entrance->GetConnectedRegion()->GetArea(); switch (entrance->GetIndex()) { case 0x0600: // minuet RANDOTODO make into entrance hints when they are added ctx->AddHint(RH_MINUET_WARP_LOC, Hint(RH_MINUET_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 82b3817bf..7a4024c69 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -186,6 +186,10 @@ public: return area; } + void SetArea(RandomizerArea newArea) { + area = newArea; + } + //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 @@ -222,7 +226,6 @@ public: "Child Night: " + std::to_string(childNight) + "\t" "Adult Day: " + std::to_string(adultDay) + "\t" "Adult Night: " + std::to_string(adultNight); - //CitraPrint(message); } }; From db5e9cbc118b2fd1c4e39735314c891e970b3768 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:49:56 +0100 Subject: [PATCH 261/300] Fix Multiple Foolish hints from an area being generated. (#4190) * Fix Multiple Foolish hints for the same location * remove debug comment --- .../Enhancements/randomizer/3drando/hints.cpp | 17 +++++++++-------- .../Enhancements/randomizer/item_location.cpp | 2 +- soh/soh/Enhancements/randomizer/item_location.h | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index d571c1ab5..a01f2a4ce 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -129,9 +129,9 @@ bool FilterWotHLocations(RandomizerCheck loc){ return ctx->GetItemLocation(loc)->IsWothCandidate(); } -bool FilterBarrenLocations(RandomizerCheck loc){ +bool FilterFoolishLocations(RandomizerCheck loc){ auto ctx = Rando::Context::GetInstance(); - return ctx->GetItemLocation(loc)->IsBarrenCandidate(); + return ctx->GetItemLocation(loc)->IsFoolishCandidate(); } bool FilterSongLocations(RandomizerCheck loc){ @@ -176,7 +176,7 @@ const std::array hintSettingTable{{ .junkWeight = 6, .distTable = { {"WotH", HINT_TYPE_WOTH, 7, 0, 1, FilterWotHLocations, 2}, - {"Barren", HINT_TYPE_FOOLISH, 4, 0, 1, FilterBarrenLocations, 1}, + {"Foolish", HINT_TYPE_FOOLISH, 4, 0, 1, FilterFoolishLocations, 1}, //("Entrance", HINT_TYPE_ENTRANCE, 6, 0, 1), //not yet implemented {"Song", HINT_TYPE_ITEM, 2, 0, 1, FilterSongLocations}, {"Overworld", HINT_TYPE_ITEM, 4, 0, 1, FilterOverworldLocations}, @@ -192,7 +192,7 @@ const std::array hintSettingTable{{ .junkWeight = 0, .distTable = { {"WotH", HINT_TYPE_WOTH, 12, 0, 2, FilterWotHLocations, 2}, - {"Barren", HINT_TYPE_FOOLISH, 12, 0, 1, FilterBarrenLocations, 1}, + {"Foolish", HINT_TYPE_FOOLISH, 12, 0, 1, FilterFoolishLocations, 1}, //{"Entrance", HINT_TYPE_ENTRANCE, 4, 0, 1}, //not yet implemented {"Song", HINT_TYPE_ITEM, 4, 0, 1, FilterSongLocations}, {"Overworld", HINT_TYPE_ITEM, 6, 0, 1, FilterOverworldLocations}, @@ -208,7 +208,7 @@ const std::array hintSettingTable{{ .junkWeight = 0, .distTable = { {"WotH", HINT_TYPE_WOTH, 15, 0, 2, FilterWotHLocations}, - {"Barren", HINT_TYPE_FOOLISH, 15, 0, 1, FilterBarrenLocations}, + {"Foolish", HINT_TYPE_FOOLISH, 15, 0, 1, FilterFoolishLocations}, //{"Entrance", HINT_TYPE_ENTRANCE, 10, 0, 1}, //not yet implemented {"Song", HINT_TYPE_ITEM, 2, 0, 1, FilterSongLocations}, {"Overworld", HINT_TYPE_ITEM, 7, 0, 1, FilterOverworldLocations}, @@ -448,9 +448,6 @@ static RandomizerCheck CreateRandomHint(std::vector& possibleHi placed = CreateHint(hintedLocation, copies, type, distributionName); } - if (type == HINT_TYPE_FOOLISH){ - SetAllInRegionAsHinted(ctx->GetItemLocation(hintedLocation)->GetArea(), possibleHintLocations); - } return hintedLocation; } @@ -582,6 +579,10 @@ uint8_t PlaceHints(std::vector& selectedHints, RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK; hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name); + if (distribution.type == HINT_TYPE_FOOLISH){ + SetAllInRegionAsHinted(ctx->GetItemLocation(hintedLocation)->GetArea(), hintTypePool); + hintTypePool = FilterHintability(hintTypePool); + } if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place, remove all wieght and copies then return the number of stones to redistribute uint8_t hintsToRemove = (selectedHints[curSlot] - numHint) * distribution.copies; selectedHints[curSlot] = 0; //as distTable is passed by refernce here, these changes stick for the rest of this seed generation diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 032619a62..3185fce8a 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -192,7 +192,7 @@ void ItemLocation::SetWothCandidate() { wothCandidate = true; } -bool ItemLocation::IsBarrenCandidate() const { +bool ItemLocation::IsFoolishCandidate() const { return barrenCandidate; } diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h index 082fd4493..b40cac537 100644 --- a/soh/soh/Enhancements/randomizer/item_location.h +++ b/soh/soh/Enhancements/randomizer/item_location.h @@ -49,7 +49,7 @@ class ItemLocation { void SetVisible(bool visibleInImGui_); bool IsWothCandidate() const; void SetWothCandidate(); - bool IsBarrenCandidate() const; + bool IsFoolishCandidate() const; void SetBarrenCandidate(); void ResetVariables(); From 5c155a625a2b1bbc89b709130f9550b614f5c87e Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:50:58 +0100 Subject: [PATCH 262/300] Quick fix Chest Minigame Setting (#4189) --- soh/soh/Enhancements/randomizer/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 48011f423..939da09ad 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1848,6 +1848,7 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio // RANDOTODO implement chest shuffle with keysanity // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); + mOptions[RSK_SHUFFLE_CHEST_MINIGAME].SetSelectedIndex(RO_CHEST_GAME_OFF); //TODO: RandomizeAllSettings(true) when implementing the ability to randomize the options themselves. std::array dungeons = ctx->GetDungeons()->GetDungeonList(); std::array dungeonModesKnown{}; From 1ca8d0ab7331d82d3e1e042d9882a5a4630caa4e Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:52:59 +0100 Subject: [PATCH 263/300] Implement Mask Hints (#4152) * Implement Mask Hints * fix typo --- .../Enhancements/custom-message/CustomMessageTypes.h | 1 + soh/soh/Enhancements/randomizer/3drando/hint_list.cpp | 4 ++++ soh/soh/Enhancements/randomizer/3drando/hints.cpp | 2 +- .../3drando/location_access/locacc_castle_town.cpp | 6 ++++-- soh/soh/Enhancements/randomizer/location_list.cpp | 4 +++- .../Enhancements/randomizer/option_descriptions.cpp | 1 + soh/soh/Enhancements/randomizer/randomizerTypes.h | 4 ++++ soh/soh/Enhancements/randomizer/settings.cpp | 11 ++++++++--- soh/soh/Enhancements/randomizer/static_data.cpp | 8 +++++--- soh/soh/OTRGlobals.cpp | 3 +++ 10 files changed, 34 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 1f5a093c7..6d25d9f8a 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -74,6 +74,7 @@ typedef enum { TEXT_SARIAS_SONG_IMPRISON_GANONDORF = 0x016C, TEXT_SARIAS_SONG_CHANNELING_POWER = 0x016D, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x01B3, // 0x1yy for Navi msg range + TEXT_MASK_SHOP_SIGN = 0x0207, TEXT_FROGS_UNDERWATER = 0x022E, TEXT_GF_HBA_SIGN = 0x031A, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x0346, // 0x3yy for cuttable sign range diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 22ef9f962..c437bcecd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2861,6 +2861,10 @@ void StaticData::HintTable_Init() { /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore #[[d]] Araignées de la Malédiction# et j'aurai quelque chose à te donner! #([[1]])#", {QM_YELLOW, QM_GREEN})); + hintTextTable[RHT_MASK_SHOP_HINT] = HintText(CustomMessage("Some young scrubs in the #Deku Theatre# love seeing Masks!^" + "They'll give you #[[1]]# if you show them the #Skull Mask#, and #[[2]]# if you show them the #Mask of Truth#!", + {QM_GREEN, QM_GREEN, QM_RED, QM_GREEN, QM_RED})); + /*-------------------------- | GANON LINE TEXT | ---------------------------*/ diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index a01f2a4ce..09930fa25 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -277,7 +277,7 @@ std::vector>> conditionalAlways }), // Remember, the option's value being 3 means 4 are required std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); + return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); }), std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index fbff295ad..160fff18d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -191,9 +191,11 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->SkullMask, {[]{return logic->SkullMask || (logic->ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}), + EventAccess(&logic->SkullMask, {[]{return logic->SkullMask || (logic->ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link'd pocket EventAccess(&logic->MaskOfTruth, {[]{return logic->MaskOfTruth || (logic->SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->HasAllStones)));}}), - }, {}, { + }, { + LocationAccess(RC_MASK_SHOP_HINT, {[]{return true;}}), + }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), }); diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 454520d48..a380e0d02 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -558,7 +558,8 @@ std::vector Rando::StaticData::staticHintLocations = { RC_SARIA_SONG_HINT, RC_ALTAR_HINT_CHILD, RC_ALTAR_HINT_ADULT, - RC_FISHING_POLE_HINT + RC_FISHING_POLE_HINT, + RC_MASK_SHOP_HINT, }; std::vector Rando::StaticData::pondFishLocations = { @@ -1564,6 +1565,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Child Altar Hint"); locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Adult Altar Hint"); locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint"); + locationTable[RC_MASK_SHOP_HINT] = Location::OtherHint(RC_MASK_SHOP_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_HAPPY_MASK_SHOP, "Mask Shop Hint"); locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index b0160a6c6..3344a8cc1 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -532,6 +532,7 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_KAK_40_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 40 tokens will tell you the reward"; mOptionDescriptions[RSK_KAK_50_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 50 tokens will tell you the reward"; mOptionDescriptions[RSK_KAK_100_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 100 tokens will tell you the reward"; + mOptionDescriptions[RSK_MASK_SHOP_HINT] = "Reading the mask shop sign will tell you rewards from showing masks at the Deku Theatre."; mOptionDescriptions[RSK_FULL_WALLETS] = "Start with a full wallet. All wallet upgrades come filled with rupees."; mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC] = diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 35d0b48ec..c48bfeeb5 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1489,6 +1489,7 @@ typedef enum { RC_ALTAR_HINT_CHILD, RC_ALTAR_HINT_ADULT, RC_FISHING_POLE_HINT, + RC_MASK_SHOP_HINT, RC_DMC_UPPER_GROTTO_FISH, RC_DMT_STORMS_GROTTO_FISH, RC_HF_SOUTHEAST_GROTTO_FISH, @@ -2086,6 +2087,7 @@ typedef enum { RH_KAK_40_SKULLS_HINT, RH_KAK_50_SKULLS_HINT, RH_KAK_100_SKULLS_HINT, + RH_MASK_SHOP_HINT, RH_MAX, } RandomizerHint; @@ -3447,6 +3449,7 @@ typedef enum { RHT_BIGGORON_HINT, RHT_FROGS_HINT, RHT_SKULLS_HINT, + RHT_MASK_SHOP_HINT, // Ganon Line RHT_GANON_JOKE01, RHT_GANON_JOKE02, @@ -3607,6 +3610,7 @@ typedef enum { RSK_KAK_40_SKULLS_HINT, RSK_KAK_50_SKULLS_HINT, RSK_KAK_100_SKULLS_HINT, + RSK_MASK_SHOP_HINT, RSK_BIGGORON_HINT, RSK_BIG_POES_HINT, RSK_CHICKENS_HINT, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 939da09ad..9d836371b 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -176,7 +176,8 @@ void Settings::CreateOptions() { mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", CVAR_RANDOMIZER_SETTING("30GSHint"), mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE); mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", CVAR_RANDOMIZER_SETTING("40GSHint"), mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE); mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", CVAR_RANDOMIZER_SETTING("50GSHint"), mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE); - mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT]); + mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT], IMFLAG_NONE); + mOptions[RSK_MASK_SHOP_HINT] = Option::Bool("Mask Shop Hint", CVAR_RANDOMIZER_SETTING("MaskShopHint"), mOptionDescriptions[RSK_MASK_SHOP_HINT]); // TODO: Compasses show rewards/woth, maps show dungeon mode mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); @@ -745,7 +746,8 @@ void Settings::CreateOptions() { &mOptions[RSK_KAK_30_SKULLS_HINT], &mOptions[RSK_KAK_40_SKULLS_HINT], &mOptions[RSK_KAK_50_SKULLS_HINT], - &mOptions[RSK_KAK_100_SKULLS_HINT] + &mOptions[RSK_KAK_100_SKULLS_HINT], + &mOptions[RSK_MASK_SHOP_HINT] }, false, WidgetContainerType::SECTION, "This setting adds some hints at locations other than Gossip Stones."); mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI_COLUMN] = OptionGroup::SubGroup("Item Pool & Hints", std::initializer_list{ &mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI], @@ -974,6 +976,7 @@ void Settings::CreateOptions() { &mOptions[RSK_KAK_40_SKULLS_HINT], &mOptions[RSK_KAK_50_SKULLS_HINT], &mOptions[RSK_KAK_100_SKULLS_HINT], + &mOptions[RSK_MASK_SHOP_HINT], &mOptions[RSK_SCRUB_TEXT_HINT], &mOptions[RSK_FISHING_POLE_HINT], // TODO: Compasses show Reward/WOTH, Maps show Dungeon Mode, Starting Time @@ -1185,7 +1188,8 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:30 GS Hint", RSK_KAK_30_SKULLS_HINT }, { "Miscellaneous Settings:40 GS Hint", RSK_KAK_40_SKULLS_HINT }, { "Miscellaneous Settings:50 GS Hint", RSK_KAK_50_SKULLS_HINT }, - { "Miscellaneous Settings:50 GS Hint", RSK_KAK_100_SKULLS_HINT }, + { "Miscellaneous Settings:100 GS Hint", RSK_KAK_100_SKULLS_HINT }, + { "Miscellaneous Settings:Mask Shop Hint", RSK_MASK_SHOP_HINT }, { "Miscellaneous Settings:Biggoron's Hint", RSK_BIGGORON_HINT }, { "Miscellaneous Settings:Big Poes Hint", RSK_BIG_POES_HINT }, { "Miscellaneous Settings:Warp Song Hints", RSK_WARP_SONG_HINTS }, @@ -2295,6 +2299,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_KAK_40_SKULLS_HINT: case RSK_KAK_50_SKULLS_HINT: case RSK_KAK_100_SKULLS_HINT: + case RSK_MASK_SHOP_HINT: case RSK_BIGGORON_HINT: case RSK_BIG_POES_HINT: case RSK_CHICKENS_HINT: diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 524ab4700..bf7a93f17 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -93,7 +93,8 @@ std::unordered_map StaticData::hintNames = { {RH_KAK_30_SKULLS_HINT, CustomMessage("30 Skulls Hint")}, {RH_KAK_40_SKULLS_HINT, CustomMessage("40 Skulls Hint")}, {RH_KAK_50_SKULLS_HINT, CustomMessage("50 Skulls Hint")}, - {RH_KAK_100_SKULLS_HINT, CustomMessage("100 Skulls Hint")} + {RH_KAK_100_SKULLS_HINT, CustomMessage("100 Skulls Hint")}, + {RH_MASK_SHOP_HINT, CustomMessage("Mask Shop Hint")}, }; std::unordered_map StaticData::gossipStoneCheckToHint { @@ -203,7 +204,7 @@ std::unordered_map StaticData::staticHintInfoMap {RH_CARPET_SALESMAN, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_CARPET_SALESMAN_DIALOG_HINTED}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_WASTELAND_BOMBCHU_SALESMAN})}, {RH_BEAN_SALESMAN, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_BEAN_SALESMAN_HINT}, RSK_SHUFFLE_MAGIC_BEANS, true, {RC_ZR_MAGIC_BEAN_SALESMAN})}, {RH_HBA_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_HBA_HINT_SIGN, RHT_HBA_HINT_NOT_ON_HORSE, RHT_HBA_HINT_INITIAL, RHT_HBA_HINT_HAVE_1000}, RSK_HBA_HINT, true, {RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS})}, - {RH_MALON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MALON_HINT_TURNING_EVIL, RHT_MALON_HINT_HOW_IS_EPONA, RHT_MALON_HINT_OBSTICLE_COURSE, RHT_MALON_HINT_INGO_TEMPTED},RSK_MALON_HINT, true, {RC_KF_LINKS_HOUSE_COW})}, + {RH_MALON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MALON_HINT_TURNING_EVIL, RHT_MALON_HINT_HOW_IS_EPONA, RHT_MALON_HINT_OBSTICLE_COURSE, RHT_MALON_HINT_INGO_TEMPTED}, RSK_MALON_HINT, true, {RC_KF_LINKS_HOUSE_COW})}, {RH_BIG_POES_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIG_POES_HINT}, RSK_BIG_POES_HINT, true, {RC_MARKET_10_BIG_POES})}, {RH_CHICKENS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_CHICKENS_HINT}, RSK_CHICKENS_HINT, true, {RC_KAK_ANJU_AS_CHILD})}, {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK})}, @@ -213,7 +214,8 @@ std::unordered_map StaticData::staticHintInfoMap {RH_KAK_30_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_30_SKULLS_HINT, true, {RC_KAK_30_GOLD_SKULLTULA_REWARD}, {}, {}, false, 30)}, {RH_KAK_40_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_40_SKULLS_HINT, true, {RC_KAK_40_GOLD_SKULLTULA_REWARD}, {}, {}, false, 40)}, {RH_KAK_50_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_50_SKULLS_HINT, true, {RC_KAK_50_GOLD_SKULLTULA_REWARD}, {}, {}, false, 50)}, - {RH_KAK_100_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_100_SKULLS_HINT, true, {RC_KAK_100_GOLD_SKULLTULA_REWARD}, {}, {}, false, 100)} + {RH_KAK_100_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_100_SKULLS_HINT, true, {RC_KAK_100_GOLD_SKULLTULA_REWARD}, {}, {}, false, 100)}, + {RH_MASK_SHOP_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MASK_SHOP_HINT}, RSK_MASK_SHOP_HINT, true, {RC_DEKU_THEATER_SKULL_MASK, RC_DEKU_THEATER_MASK_OF_TRUTH}, {}, {RC_MASK_SHOP_HINT})} }; std::unordered_map StaticData::PopulateTranslationMap(std::unordered_map input){ diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a5f325350..18da01c2c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2754,6 +2754,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { else if (textId == TEXT_HBA_ALREADY_HAVE_1000 && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); } + else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { + messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts"), 0) != 0) { From f88883044e0708f46f5f83f1509295fd441b4cf9 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sat, 6 Jul 2024 01:16:56 +0100 Subject: [PATCH 264/300] Add OoT Static Hint, Fix Sheik Crashes, Add multiple text boxes to AutoFormat (#4149) * add OoT hint, sheik is crashing without hint due to an unrelated bug * Fix Sheik crashes, add new textbox to autoFormat, trim OoTHint text * save pls * fix receive typos * git pls * nice conflict fix --- .../custom-message/CustomMessageManager.cpp | 58 ++++++++++++++----- soh/soh/Enhancements/presets.h | 1 + .../randomizer/3drando/hint_list.cpp | 3 + .../Enhancements/randomizer/3drando/hints.cpp | 5 +- .../location_access/locacc_castle_town.cpp | 1 + .../Enhancements/randomizer/location_list.cpp | 4 +- .../randomizer/option_descriptions.cpp | 3 +- .../Enhancements/randomizer/randomizer.cpp | 31 +++++----- .../Enhancements/randomizer/randomizerTypes.h | 4 ++ soh/soh/Enhancements/randomizer/settings.cpp | 5 ++ .../Enhancements/randomizer/static_data.cpp | 2 + 11 files changed, 85 insertions(+), 32 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 8c71fb023..dd0591181 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -314,7 +314,6 @@ void CustomMessage::CleanString(std::string& str) const { static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) { const size_t maxLinePixelWidth = hasIcon ? 200 : 216; - size_t totalPixelWidth = 0; size_t currentPos = lastNewline; @@ -363,24 +362,53 @@ void CustomMessage::AutoFormatString(std::string& str) const {// did I do this r size_t lastNewline = 0; const bool hasIcon = str.find('$', 0) != std::string::npos; size_t lineLength = NextLineLength(&str, lastNewline, hasIcon); + size_t lineCount = 1; while (lastNewline + lineLength < str.length()) { const size_t carrot = str.find('^', lastNewline); const size_t ampersand = str.find('&', lastNewline); const size_t lastSpace = str.rfind(' ', lastNewline + lineLength); - const size_t lastPeriod = str.rfind('.', lastNewline + lineLength); - // replace '&' first if it's within the newline range - if (ampersand < lastNewline + lineLength) { - lastNewline = ampersand + 1; - // 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) { - str.replace(lastPeriod, 1, ".&"); - lastNewline = lastPeriod + 2; - } else { - str.replace(lastSpace, 1, "&"); - lastNewline = lastSpace + 1; + if (lineCount < 4){ + // replace '&' first if it's within the newline range + if (ampersand < lastNewline + lineLength) { + lastNewline = ampersand + 1; + // or move the lastNewline cursor to the next line if a '^' is encountered + } else if (carrot < lastNewline + lineLength) { + lastNewline = carrot + 1; + lineCount = 0; + // some lines need to be split but don't have spaces, look for periods instead + } else if (lastSpace == std::string::npos) { + const size_t lastPeriod = str.rfind('.', lastNewline + lineLength); + str.replace(lastPeriod, 1, ".&"); + lastNewline = lastPeriod + 2; + } else { + str.replace(lastSpace, 1, "&"); + lastNewline = lastSpace + 1; + } + lineCount += 1; + } else { + const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength); + std::string colorText = ""; + //check if we are on a non default colour, as ^ resets it, and readd if needed + if (lastColor != std::string::npos && str[lastColor+1] != 0){ + colorText = "\x05"s + str[lastColor+1]; + } + // replace '&' first if it's within the newline range + if (ampersand < lastNewline + lineLength) { + str.replace(ampersand, 1, "^" + colorText); + lastNewline = ampersand + 1; + // 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) { + const size_t lastPeriod = str.rfind('.', lastNewline + lineLength); + str.replace(lastPeriod, 1, ".^" + colorText); + lastNewline = lastPeriod + 2; + } else { + str.replace(lastSpace, 1, "^" + colorText); + lastNewline = lastSpace + 1; + } + lineCount = 1; } lineLength = NextLineLength(&str, lastNewline, hasIcon); } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index fabefebe8..05307af6d 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -504,6 +504,7 @@ const std::vector randomizerCvars = { CVAR_RANDOMIZER_SETTING("SariaHint"), CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), CVAR_RANDOMIZER_SETTING("FrogsHint"), + CVAR_RANDOMIZER_SETTING("OoTHint"), CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), CVAR_RANDOMIZER_ENHANCEMENT("QuestItemFanfares"), }; diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index c437bcecd..3d0ae5940 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2856,6 +2856,9 @@ void StaticData::HintTable_Init() { /*french*/ "Des grenouilles se trouvant sous l'eau vous fixent attentivement, tenant fermement #[[1]]#.", {QM_GREEN})); + hintTextTable[RHT_OOT_HINT] = HintText(CustomMessage("Bring the #Spiritual Stones# to the past so you can receive #[[1]]# from Zelda and learn #[[2]]#!", + {QM_BLUE, QM_GREEN, QM_GREEN})); + hintTextTable[RHT_SKULLS_HINT] = HintText(CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying #[[d]] Spiders of the Curse# and I will give you my #[[1]]#!", /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du #[[d]] Skulltulas# zerstörst und ich werde dir dafür #[[1]]# geben!", /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore #[[d]] Araignées de la Malédiction# et j'aurai quelque chose à te donner! #([[1]])#", diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 09930fa25..95f5a1144 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -279,7 +279,10 @@ std::vector>> conditionalAlways auto ctx = Rando::Context::GetInstance(); return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); }), - std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), + std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { + auto ctx = Rando::Context::GetInstance(); + return StonesRequiredBySettings() < 2 && !ctx->GetOption(RSK_OOT_HINT); + }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index 160fff18d..4dc4af7e0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -53,6 +53,7 @@ void AreaTable_Init_CastleTown() { LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return logic->IsAdult && logic->CanTriggerLACS;}}), LocationAccess(RC_ALTAR_HINT_CHILD, {[]{return logic->IsChild;}}), LocationAccess(RC_ALTAR_HINT_ADULT, {[]{return logic->IsAdult;}}), + LocationAccess(RC_TOT_SHEIK_HINT, {[]{return logic->IsAdult;}}), }, { //Exits Entrance(RR_TOT_ENTRANCE, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index a380e0d02..987565352 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -559,6 +559,7 @@ std::vector Rando::StaticData::staticHintLocations = { RC_ALTAR_HINT_CHILD, RC_ALTAR_HINT_ADULT, RC_FISHING_POLE_HINT, + RC_TOT_SHEIK_HINT, RC_MASK_SHOP_HINT, }; @@ -1565,7 +1566,8 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Child Altar Hint"); locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Adult Altar Hint"); locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint"); - locationTable[RC_MASK_SHOP_HINT] = Location::OtherHint(RC_MASK_SHOP_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_HAPPY_MASK_SHOP, "Mask Shop Hint"); + locationTable[RC_TOT_SHEIK_HINT] = Location::OtherHint(RC_TOT_SHEIK_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_XC, SCENE_TEMPLE_OF_TIME, "Ocarina of Time Hint"); + locationTable[RC_MASK_SHOP_HINT] = Location::OtherHint(RC_MASK_SHOP_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_HAPPY_MASK_SHOP, "Mask Shop Hint"); locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 3344a8cc1..522007403 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -516,10 +516,11 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SARIA_HINT] = "Talking to Saria either in person or through Saria's Song will tell you the " "location of a progressive magic meter."; mOptionDescriptions[RSK_FISHING_POLE_HINT] = "Talking to the fishing pond owner without the fishing pole will tell you its location."; + mOptionDescriptions[RSK_OOT_HINT] = "Sheik in the Temple of Time will tell you the item and song on the Ocarina of Time."; mOptionDescriptions[RSK_FROGS_HINT] = "Standing near the pedestal for the frogs in Zora's River will tell you the " "reward for the frogs' ocarina game."; mOptionDescriptions[RSK_BIGGORON_HINT] = "Talking to Biggoron will tell you the item he will give you in exchange for the Claim Check."; - mOptionDescriptions[RSK_BIG_POES_HINT] = "Talking to the Poe Collector in the Market Guardhouse while adult will tell you what you recieve for handing in Big Poes."; + mOptionDescriptions[RSK_BIG_POES_HINT] = "Talking to the Poe Collector in the Market Guardhouse while adult will tell you what you receive for handing in Big Poes."; mOptionDescriptions[RSK_CHICKENS_HINT] = "Talking to Anju as a child will tell you the item she will give you for delivering her Cuccos to the pen"; mOptionDescriptions[RSK_MALON_HINT] = "Talking to Malon as adult will tell you the item on \"Link's cow\", the cow you win from beating her time on the Lon Lon Obsticle Course."; mOptionDescriptions[RSK_HBA_HINT] = "Talking to the Horseback Archery gerudo in Gerudo Fortress, or the nearby sign, will tell you what you win for scoring 1000 and 1500 points on Horseback Archery."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 231d5e411..e75e03ee6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2396,11 +2396,13 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { CustomMessage messageEntry; switch (scene) { case SCENE_TEMPLE_OF_TIME: - if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { + if (ctx->GetOption(RSK_OOT_HINT) && !ctx->GetItemLocation(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ + messageEntry = ctx->GetHint(RH_OOT_HINT)->GetHintMessage(MF_RAW); + } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { messageEntry = CustomMessage( - "@,&meet me at %gGanon's Castle%w&once you obtain the %rkey to his lair%w.", - "@, wir treffen uns bei %gGanons Schloß%w,&sobald Du den %rSchlüssel zu&seinem Verließ%w hast.", - "Retrouve-moi au %gChâteau de Ganon%w une&fois que tu auras obtenu la&Mrclé de son repaire%w."); + "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", + "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verließ%w hast.", + "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la Mrclé de son repaire%w."); } else { messageEntry = CustomMessage( "The time has come. Prepare yourself.", @@ -2410,18 +2412,18 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { break; case SCENE_INSIDE_GANONS_CASTLE: if (ctx->GetOption(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { - messageEntry = ctx->GetHint(RH_SHEIK_HINT)->GetHintMessage(MF_AUTO_FORMAT); + messageEntry = ctx->GetHint(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { - messageEntry = CustomMessage("You are still ill-equipped to&face %rGanondorf%w." - "^Seek out the %cMaster Sword%w,&%rsomething to hold your arrows%w,&and %gmagic%w to summon the %ylight%w.", - "Du bist noch nicht gewappnet um Dich&%rGanondorf%w stellen zu können.^" - "Begib Dich auf die Suche nach dem&%cMaster-Schwert%w, %retwas um deine Pfeilen&einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w&herauf beschwören zu können.", - "@, tu n'es toujours pas prêt à affronter&%rGanondorf%w.^" - "Cherche l'%cÉpée de Légende%w,&%rquelque chose pour ranger tes flèches%w&et de la %gmagie%w pour invoquer la&%ylumière%w."); - } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER)){ + messageEntry = CustomMessage("You are still ill-equipped to face %rGanondorf%w." + "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", + "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" + "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um deine Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", + "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" + "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); + } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){ messageEntry = CustomMessage( - "You may have what you need to defeat&%rthe Evil King%w, but the %cbarrier%w still&stands.^Complete the remaining %gtrials%w&to destroy it." + "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it." ); } else { messageEntry = CustomMessage( @@ -2431,7 +2433,8 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { } break; } - return messageEntry; + messageEntry.AutoFormat(); + return messageEntry; } CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index c48bfeeb5..43fddacea 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1489,6 +1489,7 @@ typedef enum { RC_ALTAR_HINT_CHILD, RC_ALTAR_HINT_ADULT, RC_FISHING_POLE_HINT, + RC_TOT_SHEIK_HINT, RC_MASK_SHOP_HINT, RC_DMC_UPPER_GROTTO_FISH, RC_DMT_STORMS_GROTTO_FISH, @@ -2081,6 +2082,7 @@ typedef enum { RH_BIG_POES_HINT, RH_BIGGORON_HINT, RH_FROGS_HINT, + RH_OOT_HINT, RH_KAK_10_SKULLS_HINT, RH_KAK_20_SKULLS_HINT, RH_KAK_30_SKULLS_HINT, @@ -3448,6 +3450,7 @@ typedef enum { RHT_BIG_POES_HINT, RHT_BIGGORON_HINT, RHT_FROGS_HINT, + RHT_OOT_HINT, RHT_SKULLS_HINT, RHT_MASK_SHOP_HINT, // Ganon Line @@ -3604,6 +3607,7 @@ typedef enum { RSK_GREG_HINT, RSK_SARIA_HINT, RSK_FROGS_HINT, + RSK_OOT_HINT, RSK_KAK_10_SKULLS_HINT, RSK_KAK_20_SKULLS_HINT, RSK_KAK_30_SKULLS_HINT, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 9d836371b..a67bbddab 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -164,6 +164,7 @@ void Settings::CreateOptions() { mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE); mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); + mOptions[RSK_OOT_HINT] = Option::Bool("Ocarina of Time Hint", CVAR_RANDOMIZER_SETTING("OoTHint"), mOptionDescriptions[RSK_OOT_HINT], IMFLAG_NONE); mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", CVAR_RANDOMIZER_SETTING("BiggoronHint"), mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE); mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", CVAR_RANDOMIZER_SETTING("BigPoesHint"), mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE); mOptions[RSK_CHICKENS_HINT] = Option::Bool("Chickens Hint", CVAR_RANDOMIZER_SETTING("ChickensHint"), mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE); @@ -733,6 +734,7 @@ void Settings::CreateOptions() { &mOptions[RSK_GREG_HINT], &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], + &mOptions[RSK_OOT_HINT], &mOptions[RSK_BIGGORON_HINT], &mOptions[RSK_BIG_POES_HINT], &mOptions[RSK_CHICKENS_HINT], @@ -964,6 +966,7 @@ void Settings::CreateOptions() { &mOptions[RSK_GREG_HINT], &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], + &mOptions[RSK_OOT_HINT], &mOptions[RSK_WARP_SONG_HINTS], &mOptions[RSK_BIGGORON_HINT], &mOptions[RSK_BIG_POES_HINT], @@ -1183,6 +1186,7 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Greg the Rupee Hint", RSK_GREG_HINT }, { "Miscellaneous Settings:Saria's Hint", RSK_SARIA_HINT }, { "Miscellaneous Settings:Frog Ocarina Game Hint", RSK_FROGS_HINT }, + { "Miscellaneous Settings:Ocarina of Time Hint", RSK_OOT_HINT }, { "Miscellaneous Settings:10 GS Hint", RSK_KAK_10_SKULLS_HINT }, { "Miscellaneous Settings:20 GS Hint", RSK_KAK_20_SKULLS_HINT }, { "Miscellaneous Settings:30 GS Hint", RSK_KAK_30_SKULLS_HINT }, @@ -2293,6 +2297,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_GREG_HINT: case RSK_SARIA_HINT: case RSK_FROGS_HINT: + case RSK_OOT_HINT: case RSK_KAK_10_SKULLS_HINT: case RSK_KAK_20_SKULLS_HINT: case RSK_KAK_30_SKULLS_HINT: diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index bf7a93f17..f413a86e0 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -88,6 +88,7 @@ std::unordered_map StaticData::hintNames = { {RH_BIG_POES_HINT, CustomMessage("Big Poe Reward Hint")}, {RH_BIGGORON_HINT, CustomMessage("Biggoron Claim Check Hint")}, {RH_FROGS_HINT, CustomMessage("Final Frogs in River Hint")}, + {RH_OOT_HINT, CustomMessage("Sheik in Temple of Time Hint")}, {RH_KAK_10_SKULLS_HINT, CustomMessage("10 Skulls Hint")}, {RH_KAK_20_SKULLS_HINT, CustomMessage("20 Skulls Hint")}, {RH_KAK_30_SKULLS_HINT, CustomMessage("30 Skulls Hint")}, @@ -209,6 +210,7 @@ std::unordered_map StaticData::staticHintInfoMap {RH_CHICKENS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_CHICKENS_HINT}, RSK_CHICKENS_HINT, true, {RC_KAK_ANJU_AS_CHILD})}, {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK})}, {RH_FROGS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_FROGS_HINT}, RSK_FROGS_HINT, true, {RC_ZR_FROGS_OCARINA_GAME})}, + {RH_OOT_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_OOT_HINT}, RSK_OOT_HINT, true, {RC_HF_OCARINA_OF_TIME_ITEM, RC_SONG_FROM_OCARINA_OF_TIME}, {}, {RC_TOT_SHEIK_HINT})}, {RH_KAK_10_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_10_SKULLS_HINT, true, {RC_KAK_10_GOLD_SKULLTULA_REWARD}, {}, {}, false, 10)}, {RH_KAK_20_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_20_SKULLS_HINT, true, {RC_KAK_20_GOLD_SKULLTULA_REWARD}, {}, {}, false, 20)}, {RH_KAK_30_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_30_SKULLS_HINT, true, {RC_KAK_30_GOLD_SKULLTULA_REWARD}, {}, {}, false, 30)}, From 8b001da317d7c14025f09c9a059971b85f528faa Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Sat, 6 Jul 2024 03:13:49 +0200 Subject: [PATCH 265/300] Check tracker show logic (#3972) * Initial Implementation * Fix missing locations * Update locacc_castle_town.cpp --------- Co-authored-by: Christopher Leggett --- .../randomizer/3drando/location_access.cpp | 42 +++- .../randomizer/3drando/location_access.hpp | 19 +- .../locacc_bottom_of_the_well.cpp | 50 ++--- .../location_access/locacc_castle_town.cpp | 135 +++++++------ .../location_access/locacc_death_mountain.cpp | 118 +++++------ .../location_access/locacc_deku_tree.cpp | 50 ++--- .../locacc_dodongos_cavern.cpp | 68 +++---- .../location_access/locacc_fire_temple.cpp | 76 ++++---- .../location_access/locacc_forest_temple.cpp | 74 +++---- .../location_access/locacc_ganons_castle.cpp | 84 ++++---- .../locacc_gerudo_training_grounds.cpp | 78 ++++---- .../location_access/locacc_gerudo_valley.cpp | 72 +++---- .../location_access/locacc_hyrule_field.cpp | 184 +++++++++--------- .../location_access/locacc_ice_cavern.cpp | 32 +-- .../locacc_jabujabus_belly.cpp | 52 ++--- .../location_access/locacc_kakariko.cpp | 116 +++++------ .../location_access/locacc_lost_woods.cpp | 116 +++++------ .../location_access/locacc_shadow_temple.cpp | 102 +++++----- .../location_access/locacc_spirit_temple.cpp | 116 +++++------ .../location_access/locacc_water_temple.cpp | 60 +++--- .../location_access/locacc_zoras_domain.cpp | 108 +++++----- .../randomizer/randomizer_check_tracker.cpp | 18 ++ 22 files changed, 920 insertions(+), 850 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index e389e440e..ddda3dbab 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -260,9 +260,9 @@ void AreaTable_Init() { //name, scene, hint text, events, locations, exits areaTable[RR_ROOT] = Area("Root", "", RA_LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LINKS_POCKET, {[]{return true;}}), - LocationAccess(RC_TRIFORCE_COMPLETED, {[]{return logic->CanCompleteTriforce;}}), - LocationAccess(RC_SARIA_SONG_HINT, {[]{return logic->CanUse(RG_SARIAS_SONG);}}), + LOCATION(RC_LINKS_POCKET, true), + LOCATION(RC_TRIFORCE_COMPLETED, logic->CanCompleteTriforce), + LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)), }, { //Exits Entrance(RR_ROOT_EXITS, {[]{return true;}}) @@ -363,6 +363,42 @@ void AreaTable_Init() { */ } +void ReplaceFirstInString(std::string& s, std::string const& toReplace, std::string const& replaceWith) { + size_t pos = s.find(toReplace); + if (pos == std::string::npos) { + return; + } + s.replace(pos, toReplace.length(), replaceWith); +} + +void ReplaceAllInString(std::string& s, std::string const& toReplace, std::string const& replaceWith) { + std::string buf; + size_t pos = 0; + size_t prevPos; + + buf.reserve(s.size()); + + while (true) { + prevPos = pos; + pos = s.find(toReplace, pos); + if (pos == std::string::npos) { + break; + } + buf.append(s, prevPos, pos - prevPos); + buf += replaceWith; + pos += toReplace.size(); + } + + buf.append(s, prevPos, s.size() - prevPos); + s.swap(buf); +} + +std::string CleanCheckConditionString(std::string condition) { + ReplaceAllInString(condition, "logic->", ""); + ReplaceAllInString(condition, "randoCtx->", ""); + return condition; +} + namespace Areas { const auto GetAllAreas() { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 7a4024c69..1492e82ec 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -70,12 +70,24 @@ private: std::vector conditions_met; }; +std::string CleanCheckConditionString(std::string condition); + +#define LOCATION(check, condition) LocationAccess(check, {[]{return condition;}}, CleanCheckConditionString(#condition)) + //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(RandomizerCheck location_, std::vector conditions_met_) - : location(location_) { + : location(location_), condition_str("") { + conditions_met.resize(2); + for (size_t i = 0; i < conditions_met_.size(); i++) { + conditions_met[i] = conditions_met_[i]; + } + } + + explicit LocationAccess(RandomizerCheck location_, std::vector conditions_met_, std::string condition_str_) + : location(location_), condition_str(condition_str_) { conditions_met.resize(2); for (size_t i = 0; i < conditions_met_.size(); i++) { conditions_met[i] = conditions_met_[i]; @@ -106,9 +118,14 @@ public: return location; } + std::string GetConditionStr() const { + return condition_str; + } + protected: RandomizerCheck location; std::vector conditions_met; + std::string condition_str; //Makes sure shop locations are buyable bool CanBuy() const; diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp index 37312b84b..4f5ab4086 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp @@ -25,23 +25,23 @@ void AreaTable_Init_BottomOfTheWell() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, {[]{return logic->HasExplosives;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return (logic->Swim || logic->CanUse(RG_ZELDAS_LULLABY)) && logic->Sticks || logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && (logic->KokiriSword || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return logic->HasExplosives || (((logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))) || logic->CanUse(RG_DINS_FIRE) || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_BASEMENT))) && logic->GoronBracelet);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return logic->Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return logic->Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Boomerang;}}), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives), + LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, (logic->Swim || logic->CanUse(RG_ZELDAS_LULLABY)) && logic->Sticks || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->KokiriSword || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)))), + LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasExplosives || (((logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))) || logic->CanUse(RG_DINS_FIRE) || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_BASEMENT))) && logic->GoronBracelet)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, logic->Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3)), + LOCATION(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, logic->Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3)), + LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Boomerang), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}), @@ -57,11 +57,11 @@ void AreaTable_Init_BottomOfTheWell() { //EventAccess(&WallFairy, {[]{return WallFairy || logic->Slingshot;}}), }, { //Locations - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return logic->KokiriSword || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return logic->HasExplosives || (randoCtx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->Boomerang);}}), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->KokiriSword || (logic->Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND))), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, logic->HasExplosives || (randoCtx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->Boomerang)), //Trick: logic->HasExplosives || (LogicBotWMQDeadHandKey && logic->Boomerang) - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, {[]{return logic->CanChildAttack;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, {[]{return logic->CanChildAttack && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, logic->CanChildAttack), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, logic->CanChildAttack && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2)), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}), @@ -71,10 +71,10 @@ void AreaTable_Init_BottomOfTheWell() { areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Area("Bottom of the Well MQ Middle", "Bottom of the Well", RA_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, {[]{return true;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, {[]{return logic->HasExplosives && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, {[]{return true;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return logic->CanChildAttack && (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) || logic->HasExplosives);}}), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->HasExplosives && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, logic->CanChildAttack && (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) || logic->HasExplosives)), //Trick: logic->CanChildAttack && (LogicBotWMQPits || logic->HasExplosives) }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index 4dc4af7e0..f1f1e0d27 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -38,22 +38,22 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairyWithoutSuns;}}), }, { //Locations - LocationAccess(RC_TOT_LEFTMOST_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_TOT_LEFT_CENTER_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_TOT_RIGHTMOST_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_TOT_LEFTMOST_GOSSIP_STONE, true), + LOCATION(RC_TOT_LEFT_CENTER_GOSSIP_STONE, true), + LOCATION(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, true), + LOCATION(RC_TOT_RIGHTMOST_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_THE_MARKET, {[]{return true;}}), + Entrance(RR_THE_MARKET, {[]{return true;}}), Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}), }); areaTable[RR_TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", RA_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return logic->IsAdult && logic->CanTriggerLACS;}}), - LocationAccess(RC_ALTAR_HINT_CHILD, {[]{return logic->IsChild;}}), - LocationAccess(RC_ALTAR_HINT_ADULT, {[]{return logic->IsAdult;}}), - LocationAccess(RC_TOT_SHEIK_HINT, {[]{return logic->IsAdult;}}), + LOCATION(RC_TOT_LIGHT_ARROWS_CUTSCENE, logic->IsAdult && logic->CanTriggerLACS), + LOCATION(RC_ALTAR_HINT_CHILD, logic->IsChild), + LOCATION(RC_ALTAR_HINT_ADULT, logic->IsAdult), + LOCATION(RC_TOT_SHEIK_HINT, logic->IsAdult), }, { //Exits Entrance(RR_TOT_ENTRANCE, {[]{return true;}}), @@ -65,9 +65,9 @@ void AreaTable_Init_CastleTown() { //EventAccess(&logic->TimeTravel, {[]{return true;}}), }, { //Locations - LocationAccess(RC_TOT_MASTER_SWORD, {[]{return logic->IsAdult;}}), - LocationAccess(RC_GIFT_FROM_SAGES, {[]{return logic->IsAdult;}}), - LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return logic->ForestMedallion && logic->IsAdult;}}), + LOCATION(RC_TOT_MASTER_SWORD, logic->IsAdult), + LOCATION(RC_GIFT_FROM_SAGES, logic->IsAdult), + LOCATION(RC_SHEIK_AT_TEMPLE, logic->ForestMedallion && logic->IsAdult), }, { //Exits Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}), @@ -87,10 +87,10 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->BugRock, {[]{return true;}}), }, { //Locations - LocationAccess(RC_HC_MALON_EGG, {[]{return true;}}), - LocationAccess(RC_HC_GS_TREE, {[]{return logic->CanChildAttack;}}), - LocationAccess(RC_HC_MALON_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_HC_ROCK_WALL_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_HC_MALON_EGG, true), + LOCATION(RC_HC_GS_TREE, logic->CanChildAttack), + LOCATION(RC_HC_MALON_GOSSIP_STONE, true), + LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}), @@ -103,8 +103,8 @@ void AreaTable_Init_CastleTown() { //Events }, { //Locations - LocationAccess(RC_HC_ZELDAS_LETTER, {[]{return true;}}), - LocationAccess(RC_SONG_FROM_IMPA, {[]{return true;}}), + LOCATION(RC_HC_ZELDAS_LETTER, true), + LOCATION(RC_SONG_FROM_IMPA, true), }, { //Exits Entrance(RR_HYRULE_CASTLE_GROUNDS, {[]{return true;}}), @@ -112,7 +112,7 @@ void AreaTable_Init_CastleTown() { areaTable[RR_HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_HC_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_HC_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}), @@ -125,8 +125,8 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->WanderingBugs, {[]{return logic->WanderingBugs || logic->CanBlastOrSmash;}}), }, { //Locations - LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (logic->CanBlastOrSmash && logic->HookshotOrBoomerang) || (logic->Boomerang && randoCtx->GetTrickOption(RT_HC_STORMS_GS));}}), - LocationAccess(RC_HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return logic->CanBlastOrSmash;}}), + LOCATION(RC_HC_GS_STORMS_GROTTO, (logic->CanBlastOrSmash && logic->HookshotOrBoomerang) || (logic->Boomerang && randoCtx->GetTrickOption(RT_HC_STORMS_GS))), + LOCATION(RC_HC_STORMS_GROTTO_GOSSIP_STONE, logic->CanBlastOrSmash), }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}), @@ -136,8 +136,7 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->BuiltRainbowBridge, {[]{return logic->CanBuildRainbowBridge;}}), }, { //Locations //the terrain was lowered such that you can't get this GS with a simple sword slash - LocationAccess(RC_OGC_GS, {[]{return logic->CanJumpslash || logic->CanUseProjectile - || (logic->CanShield && logic->CanUse(RG_MEGATON_HAMMER)) || logic->CanUse(RG_DINS_FIRE);}}), + LOCATION(RC_OGC_GS, logic->CanJumpslash || logic->CanUseProjectile || (logic->CanShield && logic->CanUse(RG_MEGATON_HAMMER)) || logic->CanUse(RG_DINS_FIRE)), }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return logic->AtNight;}}), @@ -147,7 +146,7 @@ void AreaTable_Init_CastleTown() { areaTable[RR_OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_OGC_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_OGC_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}), @@ -168,8 +167,8 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_10_BIG_POES, {[]{return logic->IsAdult && logic->BigPoeKill;}}), - LocationAccess(RC_MARKET_GS_GUARD_HOUSE, {[]{return logic->IsChild;}}), + LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && logic->BigPoeKill), + LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild), }, { //Exits Entrance(RR_MARKET_ENTRANCE, {[]{return true;}}), @@ -177,14 +176,14 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_BAZAAR] = Area("Market Bazaar", "Market Bazaar", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_BAZAAR_ITEM_1, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_2, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_3, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_4, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_5, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_6, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_7, {[]{return true;}}), - LocationAccess(RC_MARKET_BAZAAR_ITEM_8, {[]{return true;}}), + LOCATION(RC_MARKET_BAZAAR_ITEM_1, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_2, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_3, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_4, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_5, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_6, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_7, true), + LOCATION(RC_MARKET_BAZAAR_ITEM_8, true), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -195,7 +194,7 @@ void AreaTable_Init_CastleTown() { EventAccess(&logic->SkullMask, {[]{return logic->SkullMask || (logic->ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link'd pocket EventAccess(&logic->MaskOfTruth, {[]{return logic->MaskOfTruth || (logic->SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->HasAllStones)));}}), }, { - LocationAccess(RC_MASK_SHOP_HINT, {[]{return true;}}), + LOCATION(RC_MASK_SHOP_HINT, true), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -203,7 +202,7 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "Market Shooting Gallery", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_SHOOTING_GALLERY_REWARD, {[]{return logic->IsChild && logic->ChildsWallet;}}), + LOCATION(RC_MARKET_SHOOTING_GALLERY_REWARD, logic->IsChild && logic->ChildsWallet), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -211,9 +210,9 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "Market Bombchu Bowling", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return logic->CanPlayBowling;}}), - LocationAccess(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return logic->CanPlayBowling;}}), - LocationAccess(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, {[]{return logic->CanPlayBowling;}}), + LOCATION(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, logic->CanPlayBowling), + LOCATION(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, logic->CanPlayBowling), + LOCATION(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, logic->CanPlayBowling), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -221,14 +220,14 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_POTION_SHOP] = Area("Market Potion Shop", "Market Potion Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_3, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_4, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_5, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_6, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_7, {[]{return true;}}), - LocationAccess(RC_MARKET_POTION_SHOP_ITEM_8, {[]{return true;}}), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_1, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_2, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_3, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_4, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_5, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_6, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_7, true), + LOCATION(RC_MARKET_POTION_SHOP_ITEM_8, true), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -236,18 +235,18 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GREG_HINT, {[]{return true;}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LOCATION(RC_GREG_HINT, true), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -255,14 +254,14 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "Market Bombchu Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_3, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_4, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_5, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_6, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_7, {[]{return true;}}), - LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_8, {[]{return true;}}), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_1, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_2, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_3, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_4, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_5, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_6, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_7, true), + LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_8, true), }, { //Exits Entrance(RR_MARKET_BACK_ALLEY, {[]{return true;}}), @@ -270,7 +269,7 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "Market Dog Lady House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_MARKET_LOST_DOG, {[]{return logic->IsChild && logic->AtNight;}}), + LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight), }, { //Exits Entrance(RR_MARKET_BACK_ALLEY, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp index e4a8fbb63..6627c2286 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp @@ -10,11 +10,11 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives || logic->GoronBracelet));}}), }, { //Locations - LocationAccess(RC_DMT_CHEST, {[]{return logic->CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->GoronBracelet);}}), - LocationAccess(RC_DMT_FREESTANDING_POH, {[]{return logic->CanTakeDamage || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (logic->HasExplosives || logic->GoronBracelet));}}), - LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && (logic->HasExplosives || logic->GoronBracelet || (randoCtx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->CanTakeDamage || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)));}}), - LocationAccess(RC_DMT_GS_NEAR_KAK, {[]{return logic->CanBlastOrSmash;}}), - LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (randoCtx->GetTrickOption(RT_DMT_HOOKSHOT_LOWER_GS) && logic->CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (randoCtx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || randoCtx->GetTrickOption(RT_DMT_JS_LOWER_GS)) && logic->CanGetNightTimeGS;}}), + LOCATION(RC_DMT_CHEST, logic->CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->GoronBracelet)), + LOCATION(RC_DMT_FREESTANDING_POH, logic->CanTakeDamage || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (logic->HasExplosives || logic->GoronBracelet))), + LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanPlantBugs && (logic->HasExplosives || logic->GoronBracelet || (randoCtx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->CanTakeDamage || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), + LOCATION(RC_DMT_GS_NEAR_KAK, logic->CanBlastOrSmash), + LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || (randoCtx->GetTrickOption(RT_DMT_HOOKSHOT_LOWER_GS) && logic->CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (randoCtx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || randoCtx->GetTrickOption(RT_DMT_JS_LOWER_GS)) && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_KAK_BEHIND_GATE, {[]{return true;}}), @@ -31,11 +31,11 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->BugRock, {[]{return logic->BugRock || logic->IsChild;}}), }, { //Locations - LocationAccess(RC_DMT_TRADE_BROKEN_SWORD, {[]{return logic->IsAdult && logic->BrokenSword;}}), - LocationAccess(RC_DMT_TRADE_EYEDROPS, {[]{return logic->IsAdult && logic->Eyedrops;}}), - LocationAccess(RC_DMT_TRADE_CLAIM_CHECK, {[]{return logic->IsAdult && logic->ClaimCheck;}}), - LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || randoCtx->GetTrickOption(RT_DMT_UPPER_GS)) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_DMT_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->BrokenSword), + LOCATION(RC_DMT_TRADE_EYEDROPS, logic->IsAdult && logic->Eyedrops), + LOCATION(RC_DMT_TRADE_CLAIM_CHECK, logic->IsAdult && logic->ClaimCheck), + LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->AtNight && (logic->CanUse(RG_MEGATON_HAMMER) || randoCtx->GetTrickOption(RT_DMT_UPPER_GS)) && logic->CanGetNightTimeGS), + LOCATION(RC_DMT_GOSSIP_STONE, true), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}), @@ -52,8 +52,8 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMT_COW_GROTTO_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_DMT_COW_GROTTO_BEEHIVE, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_DMT_COW_GROTTO_COW, logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_DMT_COW_GROTTO_BEEHIVE, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}), @@ -62,11 +62,11 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_DMT_STORMS_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_DMT_STORMS_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_DMT_STORMS_GROTTO_CHEST, true), + LOCATION(RC_DMT_STORMS_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}), @@ -74,7 +74,7 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMT_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_DMT_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}), @@ -91,17 +91,17 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->StopGCRollingGoronAsAdult, {[]{return logic->StopGCRollingGoronAsAdult || (logic->IsAdult && (logic->GoronBracelet || logic->HasExplosives || logic->Bow || (randoCtx->GetTrickOption(RT_GC_LINK_GORON_DINS) && logic->CanUse(RG_DINS_FIRE))));}}), }, { //Locations - LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (randoCtx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives && logic->CanUse(RG_HOVER_BOOTS));}}), - LocationAccess(RC_GC_MAZE_CENTER_CHEST, {[]{return logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS);}}), - LocationAccess(RC_GC_MAZE_RIGHT_CHEST, {[]{return logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS);}}), - LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return logic->IsChild && logic->GoronCityChildFire && (logic->Bombs || (logic->GoronBracelet && randoCtx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->HasBombchus && randoCtx->GetTrickOption(RT_GC_POT)));}}), - LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return logic->IsChild && (logic->HasExplosives || (logic->GoronBracelet && randoCtx->GetTrickOption(RT_GC_ROLLING_STRENGTH)));}}), - LocationAccess(RC_GC_ROLLING_GORON_AS_ADULT, {[]{return logic->StopGCRollingGoronAsAdult;}}), - LocationAccess(RC_GC_GS_BOULDER_MAZE, {[]{return logic->IsChild && logic->CanBlastOrSmash;}}), - LocationAccess(RC_GC_GS_CENTER_PLATFORM, {[]{return logic->CanAdultAttack;}}), - LocationAccess(RC_GC_MEDIGORON, {[]{return logic->IsAdult && logic->AdultsWallet && (logic->CanBlastOrSmash || logic->GoronBracelet);}}), - LocationAccess(RC_GC_MAZE_GOSSIP_STONE, {[]{return logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS);}}), - LocationAccess(RC_GC_MEDIGORON_GOSSIP_STONE, {[]{return logic->CanBlastOrSmash || logic->GoronBracelet;}}), + LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (randoCtx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->GoronCityChildFire && (logic->Bombs || (logic->GoronBracelet && randoCtx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->HasBombchus && randoCtx->GetTrickOption(RT_GC_POT)))), + LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives || (logic->GoronBracelet && randoCtx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))), + LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->StopGCRollingGoronAsAdult), + LOCATION(RC_GC_GS_BOULDER_MAZE, logic->IsChild && logic->CanBlastOrSmash), + LOCATION(RC_GC_GS_CENTER_PLATFORM, logic->CanAdultAttack), + LOCATION(RC_GC_MEDIGORON, logic->IsAdult && logic->AdultsWallet && (logic->CanBlastOrSmash || logic->GoronBracelet)), + LOCATION(RC_GC_MAZE_GOSSIP_STONE, logic->CanBlastOrSmash || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MEDIGORON_GOSSIP_STONE, logic->CanBlastOrSmash || logic->GoronBracelet), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}), @@ -125,7 +125,7 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->GoronCityChildFire, {[]{return logic->GoronCityChildFire || (logic->IsChild && logic->CanUse(RG_STICKS));}}), }, { //Locations - LocationAccess(RC_GC_DARUNIAS_JOY, {[]{return logic->IsChild && logic->CanUse(RG_SARIAS_SONG);}}), + LOCATION(RC_GC_DARUNIAS_JOY, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), }, { //Exits Entrance(RR_GORON_CITY, {[]{return true;}}), @@ -140,14 +140,14 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_GC_SHOP] = Area("GC Shop", "GC Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GC_SHOP_ITEM_1, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_2, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_3, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_4, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_5, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_6, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_7, {[]{return true;}}), - LocationAccess(RC_GC_SHOP_ITEM_8, {[]{return true;}}), + LOCATION(RC_GC_SHOP_ITEM_1, true), + LOCATION(RC_GC_SHOP_ITEM_2, true), + LOCATION(RC_GC_SHOP_ITEM_3, true), + LOCATION(RC_GC_SHOP_ITEM_4, true), + LOCATION(RC_GC_SHOP_ITEM_5, true), + LOCATION(RC_GC_SHOP_ITEM_6, true), + LOCATION(RC_GC_SHOP_ITEM_7, true), + LOCATION(RC_GC_SHOP_ITEM_8, true), }, { //Exits Entrance(RR_GORON_CITY, {[]{return true;}}), @@ -155,10 +155,10 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_GC_GROTTO] = Area("GC Grotto", "GC Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_CENTER, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GC_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_GC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku), + LOCATION(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku), + LOCATION(RC_GC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku), + LOCATION(RC_GC_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_GC_GROTTO_PLATFORM, {[]{return true;}}), @@ -176,9 +176,9 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || (logic->HasExplosives && logic->CanSummonGossipFairyWithoutSuns && (logic->FireTimer >= 16 || logic->Hearts >= 3));}}), }, { //Locations - LocationAccess(RC_DMC_WALL_FREESTANDING_POH, {[]{return logic->FireTimer >= 16 || logic->Hearts >= 3;}}), - LocationAccess(RC_DMC_GS_CRATE, {[]{return (logic->FireTimer >= 8 || logic->Hearts >= 3) && logic->IsChild && logic->CanChildAttack;}}), - LocationAccess(RC_DMC_GOSSIP_STONE, {[]{return logic->HasExplosives && (logic->FireTimer >= 16 || logic->Hearts >= 3);}}), + LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer >= 16 || logic->Hearts >= 3), + LOCATION(RC_DMC_GS_CRATE, (logic->FireTimer >= 8 || logic->Hearts >= 3) && logic->IsChild && logic->CanChildAttack), + LOCATION(RC_DMC_GOSSIP_STONE, logic->HasExplosives && (logic->FireTimer >= 16 || logic->Hearts >= 3)), }, { //Exits Entrance(RR_DMC_UPPER_NEARBY, {[]{return true;}}), @@ -189,7 +189,7 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMC_LADDER_AREA_NEARBY] = Area("DMC Ladder Area Nearby", "Death Mountain Crater", RA_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMC_DEKU_SCRUB, {[]{return logic->IsChild && logic->CanStunDeku;}}), + LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku), }, { //Exits Entrance(RR_DMC_UPPER_NEARBY, {[]{return logic->Hearts >= 3;}}), @@ -214,8 +214,8 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", RA_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return logic->IsAdult && logic->Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (randoCtx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->HoverBoots));}}), - LocationAccess(RC_SHEIK_IN_CRATER, {[]{return logic->IsAdult && (logic->FireTimer >= 8 || logic->Hearts >= 3);}}), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, logic->IsAdult && logic->Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (randoCtx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->HoverBoots))), + LOCATION(RC_SHEIK_IN_CRATER, logic->IsAdult && (logic->FireTimer >= 8 || logic->Hearts >= 3)), }, { //Exits Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return logic->FireTimer >= 48;}}), @@ -226,7 +226,7 @@ void AreaTable_Init_DeathMountain() { EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_DMC_CENTRAL_LOCAL) && logic->CanUse(RG_SONG_OF_STORMS));}}), }, { //Locations - LocationAccess(RC_DMC_GS_BEAN_PATCH, {[]{return (logic->FireTimer >= 8 || logic->Hearts >= 3) && logic->CanPlantBugs && logic->CanChildAttack;}}), + LOCATION(RC_DMC_GS_BEAN_PATCH, (logic->FireTimer >= 8 || logic->Hearts >= 3) && logic->CanPlantBugs && logic->CanChildAttack), }, { //Exits Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return true;}}), @@ -237,7 +237,7 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMC_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_DMC_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_DMC_LOWER_LOCAL, {[]{return true;}}), @@ -245,11 +245,11 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_DMC_UPPER_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_DMC_UPPER_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_DMC_UPPER_GROTTO_CHEST, true), + LOCATION(RC_DMC_UPPER_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_DMC_UPPER_LOCAL, {[]{return true;}}), @@ -257,10 +257,10 @@ void AreaTable_Init_DeathMountain() { areaTable[RR_DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "DMC Hammer Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DMC_HAMMER_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku), + LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku), + LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku), + LOCATION(RC_DMC_HAMMER_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_DMC_LOWER_LOCAL, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index 39654e63e..dd7c665f7 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -25,7 +25,7 @@ void AreaTable_Init_DekuTree() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_DEKU_TREE_MAP_CHEST, {[]{return true;}}), + LOCATION(RC_DEKU_TREE_MAP_CHEST, true), }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return true;}}), @@ -44,8 +44,8 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Area("Deku Tree Slingshot Room", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_SLINGSHOT_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, {[]{return true;}}), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), + LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, true), }, { //Exits Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}), @@ -57,9 +57,9 @@ void AreaTable_Init_DekuTree() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_DEKU_TREE_COMPASS_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_GS_COMPASS_ROOM, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_DEKU_TREE_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_GS_COMPASS_ROOM, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_DEKU_TREE_LOBBY, {[]{return logic->HasFireSourceWithTorch || logic->CanUse(RG_FAIRY_BOW);}}), @@ -73,9 +73,9 @@ void AreaTable_Init_DekuTree() { /*Glitched*/[]{return logic->CanUse(RG_MEGATON_HAMMER);}}), }, { //Locations - LocationAccess(RC_DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_GS_BASEMENT_GATE, {[]{return logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return logic->CanUseProjectile || logic->CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->CanJumpslash);}}), + LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), + LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanUseProjectile || logic->CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->CanJumpslash)), }, { //Exits Entrance(RR_DEKU_TREE_LOBBY, {[]{return true;}}), @@ -127,7 +127,7 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_BASEMENT_BACK_ROOM] = Area("Deku Tree Basement Back Room", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return true;}}), @@ -161,11 +161,11 @@ void AreaTable_Init_DekuTree() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_MAP_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), - LocationAccess(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, {[]{return logic->HasFireSourceWithTorch || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW));}}), - LocationAccess(RC_DEKU_TREE_MQ_BASEMENT_CHEST, {[]{return logic->HasFireSourceWithTorch || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW));}}), - LocationAccess(RC_DEKU_TREE_MQ_GS_LOBBY, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanAdultAttack || logic->CanChildAttack), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, logic->HasFireSourceWithTorch || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, logic->HasFireSourceWithTorch || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return true;}}), @@ -178,11 +178,11 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_COMPASS_CHEST, {[]{return true;}}), - LocationAccess(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return logic->HookshotOrBoomerang && + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, logic->HookshotOrBoomerang && Here(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return logic->HasBombchus || (logic->Bombs && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult)) || - (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}}), + (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));})), }, { //Exits Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}), @@ -190,7 +190,7 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, {[]{return true;}}), + LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), }, { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return randoCtx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && (logic->DekuShield || logic->HylianShield)) || @@ -200,7 +200,7 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Area("Deku Tree MQ Basement Water Room Back", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, {[]{return logic->CanUse(RG_SONG_OF_TIME);}}), + LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME)), }, { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return Here(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE) || @@ -212,8 +212,8 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Area("Deku Tree MQ Basement Back Room", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, {[]{return (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (logic->CanUse(RG_SONG_OF_TIME) && logic->HookshotOrBoomerang);}}), - LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, {[]{return logic->HasFireSourceWithTorch && logic->HookshotOrBoomerang;}}), + LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (logic->CanUse(RG_SONG_OF_TIME) && logic->HookshotOrBoomerang)), + LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, logic->HasFireSourceWithTorch && logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return logic->IsChild;}}), @@ -222,7 +222,7 @@ void AreaTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_TREE_MQ_DEKU_SCRUB, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku), }, { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return logic->IsChild;}}), @@ -264,8 +264,8 @@ void AreaTable_Init_DekuTree() { }, { // Locations - LocationAccess(RC_QUEEN_GOHMA, { [] { return logic->DekuTreeClear; } }), - LocationAccess(RC_DEKU_TREE_QUEEN_GOHMA_HEART, { [] { return logic->DekuTreeClear; } }), + LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear), + LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_HEART, logic->DekuTreeClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index 9c7202b68..7cb2dbf0a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -30,9 +30,9 @@ void AreaTable_Init_DodongosCavern() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || (logic->CanSummonGossipFairy && Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBlastOrSmash || logic->GoronBracelet;}));}}), }, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_MAP_CHEST, {[]{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBlastOrSmash || logic->GoronBracelet;});}}), - LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, {[]{return logic->CanStunDeku || logic->GoronBracelet;}}), - LocationAccess(RC_DODONGOS_CAVERN_GOSSIP_STONE, {[]{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBlastOrSmash || logic->GoronBracelet;});}}), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBlastOrSmash || logic->GoronBracelet;})), + LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, logic->CanStunDeku || logic->GoronBracelet), + LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBlastOrSmash || logic->GoronBracelet;})), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return true;}}), @@ -52,7 +52,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return logic->CanUse(RG_SCARECROW) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_DC_SCARECROW_GS) && (logic->CanAdultAttack || logic->CanChildAttack));}}), + LOCATION(RC_DODONGOS_CAVERN_GS_SCARECROW, logic->CanUse(RG_SCARECROW) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_DC_SCARECROW_GS) && (logic->CanAdultAttack || logic->CanChildAttack))), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}), @@ -62,7 +62,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SE_ROOM] = Area("Dodongos Cavern SE Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}), @@ -91,7 +91,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_NEAR_DODONGO_ROOM] = Area("Dodongos Cavern Near Dodongo Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, logic->CanStunDeku), }, { //Exits Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}), @@ -106,8 +106,8 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->HookshotOrBoomerang;}) || logic->CanUse(RG_LONGSHOT);}}), - LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return logic->IsAdult || logic->CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && logic->CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_DC_VINES_GS));}}), + LOCATION(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->HookshotOrBoomerang;}) || logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, logic->IsAdult || logic->CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && logic->CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_DC_VINES_GS))), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}), @@ -116,7 +116,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_COMPASS_ROOM] = Area("Dodongos Cavern Compass Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_COMPASS_CHEST, {[]{return true;}}), + LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, true), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->GoronBracelet;}}), @@ -130,7 +130,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Area("Dodongos Cavern Bomb Room Lower", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}), + LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, true), }, { //Exits Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->GoronBracelet);});}}), @@ -140,8 +140,8 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, logic->CanStunDeku), + LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, logic->CanStunDeku), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}), @@ -170,7 +170,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, {[]{return true;}}), + LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, true), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}), @@ -180,7 +180,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_FAR_BRIDGE] = Area("Dodongos Cavern Far Bridge", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->CanBlastOrSmash;});}}), + LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return logic->CanBlastOrSmash;})), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}), @@ -199,7 +199,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BACK_ROOM] = Area("Dodongos Cavern Back Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_GS_BACK_ROOM, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_DODONGOS_CAVERN_GS_BACK_ROOM, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}), @@ -222,17 +222,17 @@ void AreaTable_Init_DodongosCavern() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairy;}}), }, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, {[]{return true;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return logic->CanAdultAttack || logic->CanChildAttack || logic->Nuts;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return logic->CanBlastOrSmash || (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE) || (logic->IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || logic->HoverBoots || logic->Hookshot));}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) && (logic->CanChildAttack || logic->CanAdultAttack);}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return logic->CanBlastOrSmash;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_DODONGOS_CAVERN_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanAdultAttack || logic->CanChildAttack || logic->Nuts), + LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource), + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, logic->CanBlastOrSmash || (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE) || (logic->IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || logic->HoverBoots || logic->Hookshot))), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && (logic->CanChildAttack || logic->CanAdultAttack)), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, logic->CanBlastOrSmash), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku), + LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, true), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBlastOrSmash || (((logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE)) && logic->CanTakeDamage);});}}), @@ -244,7 +244,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Area("Dodongos Cavern MQ Lower Right Side", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, logic->CanStunDeku), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}) || logic->GoronBracelet || @@ -254,8 +254,8 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA] = Area("Dodongos Cavern MQ Bomb Bag Area", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, {[]{return true;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}) || logic->GoronBracelet || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives) && logic->HookshotOrBoomerang;}}), + LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (Here(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}) || logic->GoronBracelet || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives) && logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return true;}}), @@ -266,8 +266,8 @@ void AreaTable_Init_DodongosCavern() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}), + LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, true), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}), @@ -300,9 +300,9 @@ void AreaTable_Init_DodongosCavern() { }, { // Locations - LocationAccess(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, { [] { return true; } }), - LocationAccess(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, { [] { return logic->DodongosCavernClear; } }), - LocationAccess(RC_KING_DODONGO, { [] { return logic->DodongosCavernClear; } }), + LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->DodongosCavernClear), + LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index de814b314..b3c2e5387 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -34,7 +34,7 @@ void AreaTable_Init_FireTemple() { EventAccess(&logic->FairyPot, {[]{return logic->FairyPot || (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}}), }, { //Locations - LocationAccess(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}), @@ -49,7 +49,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_TILES] = Area("Fire Temple Loop Tiles", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, {[]{return true;}}), @@ -58,7 +58,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Area("Fire Temple Loop Flare Dancer", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, {[]{return (logic->HasExplosives || logic->CanUse(RG_MEGATON_HAMMER)) && logic->IsAdult;}}), + LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, (logic->HasExplosives || logic->CanUse(RG_MEGATON_HAMMER)) && logic->IsAdult), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_TILES, {[]{return true;}}), @@ -77,7 +77,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_GORON_ROOM] = Area("Fire Temple Loop Goron Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return logic->FireLoopSwitch;}}), @@ -101,7 +101,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON] = Area("Fire Temple Big Lava Room North Goron", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}), @@ -109,7 +109,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES] = Area("Fire Temple Big Lava Room North Tiles", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, {[]{return logic->CanAdultAttack || logic->HookshotOrBoomerang;}}), + LOCATION(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, logic->CanAdultAttack || logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}), @@ -117,7 +117,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON] = Area("Fire Temple Big Lava Room South Goron", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}), @@ -131,7 +131,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SHORTCUT_ROOM] = Area("Fire Temple Shortcut Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, {[]{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;})), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 4);}}), @@ -147,8 +147,8 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Area("Fire Temple Boulder Maze Lower", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, {[]{return logic->HasExplosives && (logic->IsAdult || logic->HookshotOrBoomerang);}}), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, logic->HasExplosives && (logic->IsAdult || logic->HookshotOrBoomerang)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}), @@ -159,7 +159,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM] = Area("Fire Temple Boulder Maze Lower Side Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}), @@ -183,7 +183,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MAP_AREA] = Area("Fire Temple Map Area", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MAP_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return true;}}), @@ -191,7 +191,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Area("Fire Temple Boulder Maze Upper", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return logic->HasExplosives;}}), @@ -202,7 +202,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, {[]{return logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE);}}), + LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}), @@ -211,8 +211,8 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_EAST_PEAK] = Area("Fire Temple East Peak", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_SCARECROW_CHEST, {[]{return true;}}), - LocationAccess(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, {[]{return logic->CanUseProjectile;}}), + LOCATION(RC_FIRE_TEMPLE_SCARECROW_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, logic->CanUseProjectile), }, { //Exits Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return true;}}), @@ -243,7 +243,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM] = Area("Fire Temple Fire Maze Side Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_COMPASS_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}), @@ -251,7 +251,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER);});}}), + LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER);})), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 8);}}), @@ -289,7 +289,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_WEST_PEAK] = Area("Fire Temple West Peak", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return logic->CanTakeDamage;}}), @@ -315,8 +315,8 @@ void AreaTable_Init_FireTemple() { if (randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ()) { areaTable[RR_FIRE_TEMPLE_MQ_LOWER] = Area("Fire Temple MQ Lower", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, {[]{return logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->Bombs || logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return logic->IsAdult && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_GORON_TUNIC)) && (((logic->CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasFireSource) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && ((randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_QUADRUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OCTUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_SEXDECUPLE)) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT)))));}}), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->Bombs || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->IsAdult && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_GORON_TUNIC)) && (((logic->CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasFireSource) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && ((randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_QUADRUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OCTUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_SEXDECUPLE)) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT)))))), //Trick: logic->IsAdult && (LogicFewerTunicRequirements || logic->CanUse(RG_GORON_TUNIC)) && (((logic->CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && logic->CanUse(RG_FAIRY_BOW))) && logic->HasFireSource) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT))))) }, { //Exits @@ -331,8 +331,8 @@ void AreaTable_Init_FireTemple() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, {[]{return logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_HOOKSHOT) || (logic->HasExplosives && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG))));}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER);}}), + LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_HOOKSHOT) || (logic->HasExplosives && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG))))), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), }, {}); areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, { @@ -341,11 +341,11 @@ void AreaTable_Init_FireTemple() { //Trick: logic->HasFireSource && (logic->Bow || LogicFireMQBKChest) && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || LogicFireSongOfTime) }, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return logic->HasFireSource && (logic->Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}}), + LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasFireSource && (logic->Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), //Trick: logic->HasFireSource && (logic->Bow || LogicFireMQBKChest) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT) - LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return logic->HasFireSource && logic->HasExplosives && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST));}}), + LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource && logic->HasExplosives && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST))), //Trick: logic->HasFireSource && logic->HasExplosives && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest) - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, {[]{return true;}}), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, true), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return logic->IsAdult && logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(RR_FIRE_TEMPLE, 2) && (logic->HasFireSource || (randoCtx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->HoverBoots));}}), @@ -354,8 +354,8 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Area("Fire Temple MQ Lower Maze", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return logic->HasExplosives && (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives && (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE))), //Trick: logic->HasExplosives && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult()) }, { //Exits @@ -369,9 +369,9 @@ void AreaTable_Init_FireTemple() { EventAccess(&logic->FairyPot, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}}), }, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, {[]{return true;}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, {[]{return logic->HasExplosives;}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, {[]{return logic->IsAdult && ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOOKSHOT) && logic->HasExplosives) || logic->CanUse(RG_LONGSHOT));}}), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->HasExplosives), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->IsAdult && ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOOKSHOT) && logic->HasExplosives) || logic->CanUse(RG_LONGSHOT))), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_UPPER, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3) && logic->IsAdult && ((logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_FIRE_ARROWS));}}), @@ -379,14 +379,14 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return ((logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)) && logic->CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, ((logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)) && logic->CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)), //Trick: (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze - LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && logic->SmallKeys(RR_FIRE_TEMPLE, 4);}}), + LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, ((logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && logic->SmallKeys(RR_FIRE_TEMPLE, 4)), //Trick: ((logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && logic->SmallKeys(RR_FIRE_TEMPLE, 4) - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) || logic->HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, logic->CanUse(RG_SONG_OF_TIME) || logic->HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)), //Trick: logic->CanUse(RG_SONG_OF_TIME) || logic->HoverBoots || LogicFireMQFlameMaze - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return logic->HasExplosives;}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_FIRE_TEMPLE, 5)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && logic->IsAdult && logic->CanUse(RG_LONGSHOT));}}), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, logic->HasExplosives), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_FIRE_TEMPLE, 5)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && logic->IsAdult && logic->CanUse(RG_LONGSHOT))), //Trick: (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && logic->IsAdult && logic->CanUse(RG_LONGSHOT)) }, {}); } @@ -412,8 +412,8 @@ void AreaTable_Init_FireTemple() { }, { // Locations - LocationAccess(RC_FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return logic->FireTempleClear; } }), - LocationAccess(RC_VOLVAGIA, { [] { return logic->FireTempleClear; } }), + LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear), + LOCATION(RC_VOLVAGIA, logic->FireTempleClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index 4d46b80dc..959c192ea 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -21,8 +21,8 @@ void AreaTable_Init_ForestTemple() { if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla()) { areaTable[RR_FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, {[]{return true;}}), - LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (logic->IsAdult && logic->Bombs) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->HasBombchus || logic->CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslash || (logic->IsChild && logic->Bombs)));}}), + LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->IsAdult && logic->Bombs) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->HasBombchus || logic->CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslash || (logic->IsChild && logic->Bombs)))), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -40,7 +40,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->ForestTempleMeg, {[]{return logic->ForestTempleMeg || (logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_GS_LOBBY, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}), @@ -64,7 +64,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER);}}), + LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}), @@ -76,7 +76,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, {[]{return logic->CanUse(RG_LONGSHOT) || Here(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return logic->HookshotOrBoomerang;});}}), + LOCATION(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, logic->CanUse(RG_LONGSHOT) || Here(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return logic->HookshotOrBoomerang;})), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_SONG_OF_TIME);}}), @@ -104,8 +104,8 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return logic->CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && logic->IsAdult && randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->HoverBoots);}}), - LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return logic->CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && logic->CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives;});}}), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && logic->IsAdult && randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && logic->HoverBoots)), + LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && logic->CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives;})), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}), @@ -127,7 +127,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MAP_CHEST, {[]{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->HasExplosives || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT)) && (logic->Nuts || logic->HookshotOrBoomerang || logic->CanShield));});}}), + LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->HasExplosives || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT)) && (logic->Nuts || logic->HookshotOrBoomerang || logic->CanShield));})), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->HasExplosives || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT)) && (logic->Nuts || logic->HookshotOrBoomerang || logic->CanShield));});}}), @@ -136,7 +136,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_SEWER] = Area("Forest Temple Sewer", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_WELL_CHEST, {[]{return HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}), @@ -150,7 +150,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FLOORMASTER_ROOM] = Area("Forest Temple Floormaster Room", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, {[]{return logic->CanAdultDamage || logic->CanChildDamage;}}), + LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanAdultDamage || logic->CanChildDamage), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return true;}}), @@ -164,7 +164,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Area("Forest Temple Block Push Room", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, {[]{return logic->GoronBracelet && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT));}}), + LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->GoronBracelet && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))), }, { //Exits Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}), @@ -181,7 +181,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NW Corridor Straightened", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, {[]{return true;}}), @@ -193,7 +193,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->ForestTempleJoelle, {[]{return logic->ForestTempleJoelle || logic->CanUse(RG_FAIRY_BOW);}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_RED_POE_CHEST, {[]{return logic->ForestTempleJoelle;}}), + LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return logic->SmallKeys(RR_FOREST_TEMPLE, 3);}}), @@ -202,7 +202,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_UPPER_STALFOS] = Area("Forest Temple Upper Stalfos", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_BOW_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER);}}), + LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER);}}), @@ -214,7 +214,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->ForestTempleBeth, {[]{return logic->ForestTempleBeth || logic->CanUse(RG_FAIRY_BOW);}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_BLUE_POE_CHEST, {[]{return logic->ForestTempleBeth;}}), + LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth), }, { //Exits Entrance(RR_FOREST_TEMPLE_UPPER_STALFOS, {[]{return true;}}), @@ -241,7 +241,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Area("Forest Temple Falling Room", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}), @@ -265,8 +265,8 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BOSS_REGION] = Area("Forest Temple Boss Region", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_BASEMENT_CHEST, {[]{return true;}}), - LocationAccess(RC_FOREST_TEMPLE_GS_BASEMENT, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}), @@ -280,8 +280,8 @@ void AreaTable_Init_ForestTemple() { if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ()) { areaTable[RR_FOREST_TEMPLE_MQ_LOBBY] = Area("Forest Temple MQ Lobby", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, {[]{return logic->CanJumpslash || logic->Bombs || logic->CanUse(RG_STICKS) || logic->Nuts || logic->HookshotOrBoomerang || logic->CanUse(RG_DINS_FIRE) || logic->KokiriSword || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOVER_BOOTS);}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, logic->CanJumpslash || logic->Bombs || logic->CanUse(RG_STICKS) || logic->Nuts || logic->HookshotOrBoomerang || logic->CanUse(RG_DINS_FIRE) || logic->KokiriSword || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -293,8 +293,8 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, {[]{return (logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild) && (logic->CanJumpslash || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_STICKS) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->KokiriSword);}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER);}}), + LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild) && (logic->CanJumpslash || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_STICKS) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->KokiriSword)), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT);}}), @@ -308,7 +308,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE] = Area("Forest Temple MQ After Block Puzzle", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return logic->SmallKeys(RR_FOREST_TEMPLE, 3);}}), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(RR_FOREST_TEMPLE, 3)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_BOW_REGION, {[]{return logic->SmallKeys(RR_FOREST_TEMPLE, 4);}}), @@ -319,7 +319,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE] = Area("Forest Temple MQ Outdoor Ledge", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, {[]{return logic->CanJumpslash;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanJumpslash), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return true;}}), @@ -327,7 +327,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_NW_OUTDOORS] = Area("Forest Temple MQ NW Outdoors", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (logic->IsAdult && (logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_FOREST_MQ_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT)))) || logic->ProgressiveScale >= 2;}}), @@ -341,9 +341,9 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->DekuBabaNuts, {[]{return logic->DekuBabaNuts || (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT));}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return logic->HookshotOrBoomerang || (logic->IsAdult && logic->CanUse(RG_FIRE_ARROWS) && (logic->CanUse(RG_SONG_OF_TIME) || (logic->CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))));}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_WELL, {[]{return (logic->IsAdult && ((logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_FAIRY_BOW))) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT));}}), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT))), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->HookshotOrBoomerang || (logic->IsAdult && logic->CanUse(RG_FIRE_ARROWS) && (logic->CanUse(RG_SONG_OF_TIME) || (logic->CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))))), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, (logic->IsAdult && ((logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_FAIRY_BOW))) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT))), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME));}}), @@ -352,7 +352,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES] = Area("Forest Temple MQ Outdoors Top Ledges", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}), @@ -362,7 +362,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE] = Area("Forest Temple MQ NE Outdoors Ledge", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}), @@ -374,9 +374,9 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->ForestTempleJoAndBeth, {[]{return logic->ForestTempleJoAndBeth || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_BOW_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER);}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_MAP_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}}), + LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return logic->SmallKeys(RR_FOREST_TEMPLE, 5) && ((logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || logic->CanUse(RG_DINS_FIRE));}}), @@ -387,7 +387,7 @@ void AreaTable_Init_ForestTemple() { EventAccess(&logic->ForestTempleAmyAndMeg, {[]{return logic->ForestTempleAmyAndMeg || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && logic->SmallKeys(RR_FOREST_TEMPLE, 6));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return true;}}), @@ -395,7 +395,7 @@ void AreaTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Area("Forest Temple MQ Boss Region", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, {[]{return true;}}), + LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), }, { //Exits Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->BossKeyForestTemple;}}), @@ -425,8 +425,8 @@ void AreaTable_Init_ForestTemple() { }, { // Locations - LocationAccess(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, { [] { return logic->ForestTempleClear; } }), - LocationAccess(RC_PHANTOM_GANON, { [] { return logic->ForestTempleClear; } }), + LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear), + LOCATION(RC_PHANTOM_GANON, logic->ForestTempleClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp index baa3cb0fc..b00630e27 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp @@ -22,7 +22,7 @@ void AreaTable_Init_GanonsCastle() { if (randoCtx->GetDungeon(GANONS_CASTLE)->IsVanilla()) { areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHEIK_HINT_GC, {[]{return true;}}), + LOCATION(RC_SHEIK_HINT_GC, true), }, { //Exits Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return true;}}), @@ -46,10 +46,10 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->FreeFairies, {[]{return true;}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, logic->CanStunDeku), }, {}); areaTable[RR_GANONS_CASTLE_FOREST_TRIAL] = Area("Ganon's Castle Forest Trial", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -57,7 +57,7 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->ForestTrialClear, {[]{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->FireArrows || logic->DinsFire);}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, {[]{return logic->CanAdultDamage || logic->CanChildDamage;}}), + LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanAdultDamage || logic->CanChildDamage), }, {}); areaTable[RR_GANONS_CASTLE_FIRE_TRIAL] = Area("Ganon's Castle Fire Trial", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -72,8 +72,8 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->WaterTrialClear, {[]{return logic->BlueFire && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, {[]{return true;}}), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, true), }, {}); areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -81,8 +81,8 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->ShadowTrialClear, {[]{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MEGATON_HAMMER) && ((logic->FireArrows && (randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->DinsFire && (randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))))));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild;}}), - LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_DINS_FIRE)));}}), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_DINS_FIRE)))), }, {}); areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -91,8 +91,8 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->SpiritTrialClear, {[]{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || randoCtx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->HasBombchus && ((randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslash) || logic->CanUse(RG_HOOKSHOT));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanJumpslash;}}), - LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH));}}), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanJumpslash), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), }, {}); areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -100,22 +100,22 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->LightTrialClear, {[]{return logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_GANONS_CASTLE, 2) && (randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_GANONS_CASTLE, 1);}}), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, randoCtx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_GANONS_CASTLE, 1)), }, {}); } areaTable[RR_GANONS_CASTLE_TOWER] = Area("Ganon's Castle Tower", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GANONS_TOWER_BOSS_KEY_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GANONDORF_HINT, {[]{return logic->BossKeyGanonsCastle && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), - LocationAccess(RC_GANON, {[]{return logic->HasBossSoul(RG_GANON_SOUL) && logic->BossKeyGanonsCastle && logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MASTER_SWORD);}}), + LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GANONDORF_HINT, logic->BossKeyGanonsCastle && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), + LOCATION(RC_GANON, logic->HasBossSoul(RG_GANON_SOUL) && logic->BossKeyGanonsCastle && logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MASTER_SWORD)), }, {}); /*--------------------------- @@ -124,7 +124,7 @@ void AreaTable_Init_GanonsCastle() { if (randoCtx->GetDungeon(GANONS_CASTLE)->IsMQ()) { areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHEIK_HINT_MQ_GC, {[]{return true;}}), + LOCATION(RC_SHEIK_HINT_MQ_GC, true), }, { //Exits Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return (logic->CanUse(RG_MASTER_SWORD) || (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword))));}}), @@ -148,11 +148,11 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->FreeFairies, {[]{return true;}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, {[]{return logic->CanStunDeku;}}), + LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, logic->CanStunDeku), + LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, logic->CanStunDeku), }, {}); areaTable[RR_GANONS_CASTLE_MQ_FOREST_TRIAL] = Area("Ganon's Castle MQ Forest Trial", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -160,9 +160,9 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->ForestTrialClear, {[]{return logic->IsAdult && logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->CanUse(RG_SONG_OF_TIME);}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HasFireSource;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HookshotOrBoomerang;}}), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HasFireSource), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HookshotOrBoomerang), }, {}); areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -177,7 +177,7 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->BlueFireAccess, {[]{return logic->BlueFireAccess || (logic->HasBottle && logic->CanJumpslash);}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, {[]{return logic->BlueFire;}}), + LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire), }, {}); areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -186,8 +186,8 @@ void AreaTable_Init_GanonsCastle() { //Trick: logic->IsAdult && logic->CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HoverBoots || (logic->Hookshot && (logic->HasFireSource || LogicShadowTrialMQ))) }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return logic->IsAdult && ((logic->Bow && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_HOVER_BOOTS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HasExplosives || logic->GoronBracelet || logic->CanUse(RG_DINS_FIRE))));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return logic->IsAdult && logic->Bow && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HoverBoots || (logic->Hookshot && (logic->HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))));}}), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->IsAdult && ((logic->Bow && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_HOVER_BOOTS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HasExplosives || logic->GoronBracelet || logic->CanUse(RG_DINS_FIRE))))), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->IsAdult && logic->Bow && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HoverBoots || (logic->Hookshot && (logic->HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))))), //Trick: logic->IsAdult && logic->Bow && (LogicLensCastleMQ || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HoverBoots || (logic->Hookshot && (logic->HasFireSource || LogicShadowTrialMQ))) }, {}); @@ -197,12 +197,12 @@ void AreaTable_Init_GanonsCastle() { EventAccess(&logic->NutPot, {[]{return logic->NutPot || (logic->Hammer && logic->HasBombchus && logic->IsAdult && ((logic->CanUse(RG_FIRE_ARROWS) && logic->MirrorShield) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return logic->IsAdult && (logic->Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->Hammer;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return logic->IsAdult && (logic->Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->Hammer && logic->HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}}), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->IsAdult && (logic->Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->Hammer), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, logic->IsAdult && (logic->Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->Hammer && logic->HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, logic->IsAdult && logic->Hammer && logic->HasBombchus && ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), }, {}); areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -211,7 +211,7 @@ void AreaTable_Init_GanonsCastle() { //Trick: logic->IsAdult && logic->CanUse(RG_LIGHT_ARROWS) && logic->SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->Hookshot || LogicLightTrialMQ) }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->CanUse(RG_ZELDAS_LULLABY)), }, {}); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp index f48bac91c..c0a2ab2bc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp @@ -21,10 +21,10 @@ void AreaTable_Init_GerudoTrainingGrounds() { if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsVanilla()) { areaTable[RR_GERUDO_TRAINING_GROUNDS_LOBBY] = Area("Gerudo Training Grounds Lobby", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, {[]{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, {[]{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, {[]{return logic->HasExplosives && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->HasExplosives && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}), @@ -35,11 +35,11 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (randoCtx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 4);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 6);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 7);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 9);}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (randoCtx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 4)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 6)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 7)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 9)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 9);}}), @@ -47,9 +47,9 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds Central Maze Right", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, {[]{return true;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, true), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return logic->CanUse(RG_HOOKSHOT);}}), @@ -58,7 +58,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM] = Area("Gerudo Training Grounds Lava Room", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME) && logic->IronBoots && logic->WaterTimer >= 24;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME) && logic->IronBoots && logic->WaterTimer >= 24), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild;}}), @@ -67,8 +67,8 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS));}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAdultAttack || logic->CanChildAttack), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS))), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_FAIRY_BOW);}}), @@ -77,7 +77,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER] = Area("Gerudo Training Grounds Eye Statue Lower", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, {[]{return logic->CanUse(RG_FAIRY_BOW);}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return true;}}), @@ -85,7 +85,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER] = Area("Gerudo Training Grounds Eye Statue Upper", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, {[]{return logic->CanUse(RG_FAIRY_BOW);}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, logic->CanUse(RG_FAIRY_BOW)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return true;}}), @@ -93,7 +93,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM] = Area("Gerudo Training Grounds Heavy Block Room", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, {[]{return logic->CanJumpslash;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanJumpslash), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (randoCtx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)));}}), @@ -102,10 +102,10 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, {[]{return logic->CanJumpslash;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanJumpslash), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanJumpslash), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, logic->CanJumpslash), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, logic->CanJumpslash), }, {}); } @@ -115,12 +115,12 @@ void AreaTable_Init_GerudoTrainingGrounds() { if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsMQ()) { areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY] = Area("Gerudo Training Grounds MQ Lobby", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 1);}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 1)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}), @@ -133,7 +133,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { //EventAccess(&WallFairy, {[]{return WallFairy || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW));}}), }, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, {[]{return logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return (logic->Bow || (logic->CanUse(RG_LONGSHOT) && logic->HasFireSource)) && logic->CanUse(RG_HOVER_BOOTS) && logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), @@ -141,12 +141,12 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER] = Area("Gerudo Training Grounds MQ Underwater", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return logic->HasFireSource && logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer >= 24 && logic->CanTakeDamage;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasFireSource && logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer >= 24 && logic->CanTakeDamage), }, {}); areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE] = Area("Gerudo Training Grounds MQ Left Side", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->HasExplosives;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->HasExplosives), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || randoCtx->GetTrickOption(RT_GTG_MQ_WIHTOUT_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT));}}), @@ -158,8 +158,8 @@ void AreaTable_Init_GerudoTrainingGrounds() { EventAccess(&logic->BlueFireAccess, {[]{return logic->BlueFireAccess || logic->HasBottle;}}), }, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, {[]{return logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, {[]{return logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return logic->IsAdult && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire && (logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}}), @@ -168,9 +168,9 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS] = Area("Gerudo Training Grounds MQ Back Areas", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, {[]{return logic->CanUse(RG_FAIRY_BOW);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, {[]{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, {[]{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->HasExplosives;}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->HasExplosives), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}), @@ -179,9 +179,9 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds MQ Central Maze Right", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, {[]{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3);}}), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return logic->IsAdult && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->Bow));}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp index a81627656..554003434 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp @@ -9,7 +9,7 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->BugRock, {[]{return logic->BugRock || logic->IsChild;}}), }, { //Locations - LocationAccess(RC_GV_GS_SMALL_BRIDGE, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), + LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -25,10 +25,10 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_GV_UPPER_STREAM) && logic->CanUse(RG_SONG_OF_STORMS));}}), }, { //Locations - LocationAccess(RC_GV_WATERFALL_FREESTANDING_POH, {[]{return logic->IsChild || logic->Swim;}}),//can use cucco as child - LocationAccess(RC_GV_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), - LocationAccess(RC_GV_COW, {[]{return logic->IsChild && logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_GV_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->Swim),//can use cucco as child + LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanPlantBugs && logic->CanChildAttack), + LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_GV_GOSSIP_STONE, true), }, { //Exits Entrance(RR_GV_LOWER_STREAM, {[]{return true;}}), @@ -48,7 +48,7 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_GV_CRATE_LEDGE] = Area("GV Crate Ledge", "Gerudo Valley", RA_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GV_CRATE_FREESTANDING_POH, {[]{return true;}}), + LOCATION(RC_GV_CRATE_FREESTANDING_POH, true), }, { //Exits Entrance(RR_GV_LOWER_STREAM, {[]{return true;}}), @@ -59,10 +59,10 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->BrokenSwordAccess, {[]{return logic->IsAdult && (logic->PoachersSawAccess || logic->PoachersSaw);}}), }, { //Locations - LocationAccess(RC_GV_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER);}}), - LocationAccess(RC_GV_TRADE_SAW, {[]{return logic->IsAdult && logic->PoachersSaw;}}), - LocationAccess(RC_GV_GS_BEHIND_TENT, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_GV_GS_PILLAR, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), + LOCATION(RC_GV_CHEST, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->PoachersSaw), + LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}), @@ -85,9 +85,9 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_GV_STORMS_GROTTO] = Area("GV Storms Grotto", "GV Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GV_DEKU_SCRUB_GROTTO_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_GV_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku), + LOCATION(RC_GV_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku), + LOCATION(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}), @@ -100,16 +100,16 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->GtG_GateOpen, {[]{return logic->GtG_GateOpen || (logic->IsAdult && logic->GerudoToken && logic->ChildsWallet);}}), }, { //Locations - LocationAccess(RC_GF_CHEST, {[]{return logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SCARECROW)) || logic->CanUse(RG_LONGSHOT);}}), - LocationAccess(RC_GF_HBA_1000_POINTS, {[]{return logic->ChildsWallet && logic->GerudoToken && logic->CanRideEpona && logic->Bow && logic->AtDay;}}), - LocationAccess(RC_GF_HBA_1500_POINTS, {[]{return logic->ChildsWallet && logic->GerudoToken && logic->CanRideEpona && logic->Bow && logic->AtDay;}}), - LocationAccess(RC_GF_NORTH_F1_CARPENTER, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (logic->GerudoToken || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN));}}), - LocationAccess(RC_GF_SOUTH_F1_CARPENTER, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GF_SOUTH_F2_CARPENTER, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GF_GERUDO_MEMBERSHIP_CARD, {[]{return logic->CanFinishGerudoFortress;}}), - LocationAccess(RC_GF_GS_ARCHERY_RANGE, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->GerudoToken && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return logic->IsAdult && logic->AtNight && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)) && (logic->GerudoToken || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN) || randoCtx->GetTrickOption(RT_GF_JUMP)) && logic->CanGetNightTimeGS;}}), + LOCATION(RC_GF_CHEST, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SCARECROW)) || logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_GF_HBA_1000_POINTS, logic->ChildsWallet && logic->GerudoToken && logic->CanRideEpona && logic->Bow && logic->AtDay), + LOCATION(RC_GF_HBA_1500_POINTS, logic->ChildsWallet && logic->GerudoToken && logic->CanRideEpona && logic->Bow && logic->AtDay), + LOCATION(RC_GF_NORTH_F1_CARPENTER, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GF_NORTH_F2_CARPENTER, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (logic->GerudoToken || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN))), + LOCATION(RC_GF_SOUTH_F1_CARPENTER, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GF_SOUTH_F2_CARPENTER, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), + LOCATION(RC_GF_GERUDO_MEMBERSHIP_CARD, logic->CanFinishGerudoFortress), + LOCATION(RC_GF_GS_ARCHERY_RANGE, logic->IsAdult && logic->HookshotOrBoomerang && logic->GerudoToken && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->AtNight && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)) && (logic->GerudoToken || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN) || randoCtx->GetTrickOption(RT_GF_JUMP)) && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}), @@ -147,9 +147,9 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_WASTELAND_CHEST, {[]{return logic->HasFireSource;}}), - LocationAccess(RC_WASTELAND_BOMBCHU_SALESMAN, {[]{return logic->AdultsWallet && (logic->CanJumpslash || logic->CanUse(RG_HOVER_BOOTS)) ;}}), - LocationAccess(RC_WASTELAND_GS, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource), + LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->AdultsWallet && (logic->CanJumpslash || logic->CanUse(RG_HOVER_BOOTS)) ), + LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return randoCtx->GetTrickOption(RT_LENS_HW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), @@ -168,11 +168,11 @@ void AreaTable_Init_GerudoValley() { EventAccess(&logic->BugRock, {[]{return true;}}), }, { //Locations - LocationAccess(RC_COLOSSUS_FREESTANDING_POH, {[]{return logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS);}}), - LocationAccess(RC_COLOSSUS_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), - LocationAccess(RC_COLOSSUS_GS_TREE, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return logic->IsAdult && logic->AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && logic->CanAdultAttack) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_COLOSSUS_GS) && logic->CanUse(RG_HOOKSHOT))) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_COLOSSUS_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_COLOSSUS_FREESTANDING_POH, logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS)), + LOCATION(RC_COLOSSUS_GS_BEAN_PATCH, logic->CanPlantBugs && logic->CanChildAttack), + LOCATION(RC_COLOSSUS_GS_TREE, logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_COLOSSUS_GS_HILL, logic->IsAdult && logic->AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && logic->CanAdultAttack) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_COLOSSUS_GS) && logic->CanUse(RG_HOOKSHOT))) && logic->CanGetNightTimeGS), + LOCATION(RC_COLOSSUS_GOSSIP_STONE, true), }, { //Exits Entrance(RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, {[]{return logic->HasExplosives;}}), @@ -183,7 +183,7 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY] = Area("Desert Colossus From Spirit Entryway", "Desert Colossus", RA_DESERT_COLOSSUS, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHEIK_AT_COLOSSUS, {[]{return true;}}), + LOCATION(RC_SHEIK_AT_COLOSSUS, true), }, { //Exist Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}), @@ -191,7 +191,7 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_COLOSSUS_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_COLOSSUS_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}), @@ -199,9 +199,9 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_COLOSSUS_GROTTO] = Area("Colossus Grotto", "Colossus Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_COLOSSUS_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku), + LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku), + LOCATION(RC_COLOSSUS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp index 8c3d6a5b1..d5d966308 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp @@ -9,8 +9,8 @@ void AreaTable_Init_HyruleField() { EventAccess(&logic->BigPoeKill, {[]{return logic->CanUse(RG_FAIRY_BOW) && logic->CanRideEpona && logic->HasBottle;}}), }, { //Locations - LocationAccess(RC_HF_OCARINA_OF_TIME_ITEM, {[]{return logic->IsChild && logic->HasAllStones;}}), - LocationAccess(RC_SONG_FROM_OCARINA_OF_TIME, {[]{return logic->IsChild && logic->HasAllStones;}}), + LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->HasAllStones), + LOCATION(RC_SONG_FROM_OCARINA_OF_TIME, logic->IsChild && logic->HasAllStones), }, { //Exits Entrance(RR_LW_BRIDGE, {[]{return true;}}), @@ -32,11 +32,11 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_HF_SOUTHEAST_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, true), + LOCATION(RC_HF_SOUTHEAST_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -44,11 +44,11 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_HF_OPEN_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_HF_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_HF_OPEN_GROTTO_CHEST, true), + LOCATION(RC_HF_OPEN_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -56,8 +56,8 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "HF Inside Fence Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_HF_DEKU_SCRUB_GROTTO, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_HF_DEKU_SCRUB_GROTTO, logic->CanStunDeku), + LOCATION(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -65,9 +65,9 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_HF_GS_COW_GROTTO, {[]{return logic->HasFireSource && logic->HookshotOrBoomerang;}}), - LocationAccess(RC_HF_COW_GROTTO_COW, {[]{return logic->HasFireSource && logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_HF_COW_GROTTO_GOSSIP_STONE, {[]{return logic->HasFireSource;}}), + LOCATION(RC_HF_GS_COW_GROTTO, logic->HasFireSource && logic->HookshotOrBoomerang), + LOCATION(RC_HF_COW_GROTTO_COW, logic->HasFireSource && logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_HF_COW_GROTTO_GOSSIP_STONE, logic->HasFireSource), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -75,11 +75,11 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_HF_NEAR_MARKET_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, true), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -95,7 +95,7 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "HF Near Kak Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_HF_GS_NEAR_KAK_GROTTO, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_HF_GS_NEAR_KAK_GROTTO, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -103,7 +103,7 @@ void AreaTable_Init_HyruleField() { areaTable[RR_HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "HF Tektite Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return logic->ProgressiveScale >= 2 || logic->CanUse(RG_IRON_BOOTS);}}), + LOCATION(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, logic->ProgressiveScale >= 2 || logic->CanUse(RG_IRON_BOOTS)), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -119,16 +119,16 @@ void AreaTable_Init_HyruleField() { EventAccess(&logic->AdultScarecrow, {[]{return logic->AdultScarecrow || (logic->IsAdult && logic->Ocarina && logic->OcarinaButtons >= 2);}}), }, { //Locations - LocationAccess(RC_LH_UNDERWATER_ITEM, {[]{return logic->IsChild && logic->CanDive;}}), - LocationAccess(RC_LH_SUN, {[]{return logic->IsAdult && logic->WaterTempleClear && logic->CanUse(RG_FAIRY_BOW);}}), - LocationAccess(RC_LH_FREESTANDING_POH, {[]{return logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA));}}), - LocationAccess(RC_LH_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), - LocationAccess(RC_LH_GS_LAB_WALL, {[]{return logic->IsChild && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslash)) && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LH_GS_SMALL_ISLAND, {[]{return logic->IsChild && logic->CanChildAttack && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LH_GS_TREE, {[]{return logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LH_LAB_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_LH_SOUTHEAST_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_LH_SOUTHWEST_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->CanDive), + LOCATION(RC_LH_SUN, logic->IsAdult && logic->WaterTempleClear && logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA))), + LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanPlantBugs && logic->CanChildAttack), + LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslash)) && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanChildAttack && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_LH_GS_TREE, logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_LH_LAB_GOSSIP_STONE, true), + LOCATION(RC_LH_SOUTHEAST_GOSSIP_STONE, true), + LOCATION(RC_LH_SOUTHWEST_GOSSIP_STONE, true), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -156,9 +156,9 @@ void AreaTable_Init_HyruleField() { EventAccess(&logic->EyedropsAccess, {[]{return logic->EyedropsAccess || (logic->IsAdult && (logic->EyeballFrogAccess || (logic->EyeballFrog && logic->DisableTradeRevert)));}}), }, { //Locations - LocationAccess(RC_LH_LAB_DIVE, {[]{return logic->ProgressiveScale >= 2 || (randoCtx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));}}), - LocationAccess(RC_LH_TRADE_FROG, {[]{return logic->IsAdult && logic->EyeballFrog;}}), - LocationAccess(RC_LH_GS_LAB_CRATE, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT);}}), + LOCATION(RC_LH_LAB_DIVE, logic->ProgressiveScale >= 2 || (randoCtx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_LH_TRADE_FROG, logic->IsAdult && logic->EyeballFrog), + LOCATION(RC_LH_GS_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)), }, { //Exits Entrance(RR_LAKE_HYLIA, {[]{return true;}}), @@ -167,42 +167,42 @@ void AreaTable_Init_HyruleField() { // TODO: should some of these helpers be done via events instead? areaTable[RR_LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", RA_NONE, DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LH_CHILD_FISHING, {[]{return logic->CanFish && logic->IsChild;}}), - LocationAccess(RC_LH_CHILD_FISH_1, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_2, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_3, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_4, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_5, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_6, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_7, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_8, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_9, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_10, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_11, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_12, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_13, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_14, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_FISH_15, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_LOACH_1, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_CHILD_LOACH_2, {[]{return logic->CanGetChildFish;}}), - LocationAccess(RC_LH_ADULT_FISHING, {[]{return logic->CanFish && logic->IsAdult;}}), - LocationAccess(RC_LH_ADULT_FISH_1, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_2, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_3, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_4, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_5, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_6, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_7, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_8, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_9, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_10, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_11, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_12, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_13, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_14, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_FISH_15, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_LH_ADULT_LOACH, {[]{return logic->CanGetAdultFish;}}), - LocationAccess(RC_FISHING_POLE_HINT,{[]{return true;}}), + LOCATION(RC_LH_CHILD_FISHING, logic->CanFish && logic->IsChild), + LOCATION(RC_LH_CHILD_FISH_1, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_2, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_3, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_4, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_5, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_6, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_7, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_8, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_9, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_10, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_11, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_12, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_13, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_14, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_15, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_LOACH_1, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_LOACH_2, logic->CanGetChildFish), + LOCATION(RC_LH_ADULT_FISHING, logic->CanFish && logic->IsAdult), + LOCATION(RC_LH_ADULT_FISH_1, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_2, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_3, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_4, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_5, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_6, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_7, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_8, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_9, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_10, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_11, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_12, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_13, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_14, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_15, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_LOACH, logic->CanGetAdultFish), + LOCATION(RC_FISHING_POLE_HINT,true), }, { //Exits Entrance(RR_LH_FISHING_ISLAND, {[]{return true;}}), @@ -210,10 +210,10 @@ void AreaTable_Init_HyruleField() { areaTable[RR_LH_GROTTO] = Area("LH Grotto", "LH Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_CENTER, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LH_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_LH_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku), + LOCATION(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku), + LOCATION(RC_LH_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku), + LOCATION(RC_LH_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_LAKE_HYLIA, {[]{return true;}}), @@ -225,11 +225,11 @@ void AreaTable_Init_HyruleField() { EventAccess(&logic->LinksCow, {[]{return logic->LinksCow || (logic->ChildsWallet && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay);}}), }, { //Locations - LocationAccess(RC_SONG_FROM_MALON, {[]{return logic->IsChild && logic->ZeldasLetter && logic->Ocarina && logic->AtDay;}}), - LocationAccess(RC_LLR_GS_TREE, {[]{return logic->IsChild;}}), - LocationAccess(RC_LLR_GS_RAIN_SHED, {[]{return logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LLR_GS_HOUSE_WINDOW, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LLR_GS_BACK_WALL, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), + LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->ZeldasLetter && logic->Ocarina && logic->AtDay), + LOCATION(RC_LLR_GS_TREE, logic->IsChild), + LOCATION(RC_LLR_GS_RAIN_SHED, logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_LLR_GS_HOUSE_WINDOW, logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_LLR_GS_BACK_WALL, logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -241,7 +241,7 @@ void AreaTable_Init_HyruleField() { areaTable[RR_LLR_TALONS_HOUSE] = Area("LLR Talons House", "LLR Talons House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LLR_TALONS_CHICKENS, {[]{return logic->ChildsWallet && logic->IsChild && logic->AtDay && logic->ZeldasLetter;}}), + LOCATION(RC_LLR_TALONS_CHICKENS, logic->ChildsWallet && logic->IsChild && logic->AtDay && logic->ZeldasLetter), }, { //Exits Entrance(RR_LON_LON_RANCH, {[]{return true;}}), @@ -249,8 +249,8 @@ void AreaTable_Init_HyruleField() { areaTable[RR_LLR_STABLES] = Area("LLR Stables", "LLR Stables", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LLR_STABLES_LEFT_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_LLR_STABLES_RIGHT_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), + LOCATION(RC_LLR_STABLES_LEFT_COW, logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_LLR_STABLES_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)), }, { //Exits Entrance(RR_LON_LON_RANCH, {[]{return true;}}), @@ -258,9 +258,9 @@ void AreaTable_Init_HyruleField() { areaTable[RR_LLR_TOWER] = Area("LLR Tower", "LLR Tower", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LLR_FREESTANDING_POH, {[]{return logic->IsChild;}}), - LocationAccess(RC_LLR_TOWER_LEFT_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_LLR_TOWER_RIGHT_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), + LOCATION(RC_LLR_FREESTANDING_POH, logic->IsChild), + LOCATION(RC_LLR_TOWER_LEFT_COW, logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_LLR_TOWER_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)), }, { //Exits Entrance(RR_LON_LON_RANCH, {[]{return true;}}), @@ -268,10 +268,10 @@ void AreaTable_Init_HyruleField() { areaTable[RR_LLR_GROTTO] = Area("LLR Grotto", "LLR Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LLR_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku), + LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku), + LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku), + LOCATION(RC_LLR_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_LON_LON_RANCH, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp index 4e5827258..7f5873ba1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp @@ -30,14 +30,14 @@ void AreaTable_Init_IceCavern() { EventAccess(&logic->BlueFireAccess, {[]{return logic->BlueFireAccess || (logic->IsAdult && logic->HasBottle);}}), }, { //Locations - LocationAccess(RC_ICE_CAVERN_MAP_CHEST, {[]{return logic->BlueFire && logic->IsAdult;}}), - LocationAccess(RC_ICE_CAVERN_COMPASS_CHEST, {[]{return logic->BlueFire;}}), - LocationAccess(RC_ICE_CAVERN_IRON_BOOTS_CHEST, {[]{return logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_DINS_FIRE));}}), - LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_DINS_FIRE)) && logic->IsAdult;}}), - LocationAccess(RC_ICE_CAVERN_FREESTANDING_POH, {[]{return logic->BlueFire;}}), - LocationAccess(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, {[]{return logic->HookshotOrBoomerang;}}), - LocationAccess(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, {[]{return logic->BlueFire && logic->HookshotOrBoomerang;}}), - LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return logic->BlueFire && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_ICE_BLOCK_GS) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}}), + LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire && logic->IsAdult), + LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, logic->BlueFire), + LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_DINS_FIRE))), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_DINS_FIRE)) && logic->IsAdult), + LOCATION(RC_ICE_CAVERN_FREESTANDING_POH, logic->BlueFire), + LOCATION(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, logic->HookshotOrBoomerang), + LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, logic->BlueFire && logic->HookshotOrBoomerang), + LOCATION(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, logic->BlueFire && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_ICE_BLOCK_GS) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)))), }, {}); } @@ -61,23 +61,23 @@ void AreaTable_Init_IceCavern() { EventAccess(&logic->BlueFireAccess, {[]{return logic->BlueFireAccess || (logic->HasBottle && logic->CanJumpslash);}}), }, { //Locations - LocationAccess(RC_ICE_CAVERN_MQ_MAP_CHEST, {[]{return logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUseProjectile);}}), + LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives || logic->CanUseProjectile)), }, {}); areaTable[RR_ICE_CAVERN_MQ_IRON_BOOTS_REGION] = Area("Ice Cavern MQ Iron Boots Region", "Ice Cavern", RA_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, {[]{return logic->IsAdult && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER));}}), - LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return logic->IsAdult && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER));}}), - LocationAccess(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), - LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return logic->CanUse(RG_SCARECROW) || (logic->HoverBoots && logic->CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_ICE_MQ_SCARECROW) && logic->IsAdult);}}), + LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->IsAdult && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER))), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->IsAdult && (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER))), + LOCATION(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, logic->CanAdultAttack || logic->CanChildAttack), + LOCATION(RC_ICE_CAVERN_MQ_GS_SCARECROW, logic->CanUse(RG_SCARECROW) || (logic->HoverBoots && logic->CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_ICE_MQ_SCARECROW) && logic->IsAdult)), //Tricks: (logic->CanUse(RG_SCARECROW) || (logic->HoverBoots && logic->CanUse(RG_LONGSHOT)) || LogicIceMQScarecrow) && logic->IsAdult }, {}); areaTable[RR_ICE_CAVERN_MQ_COMPASS_ROOM] = Area("Ice Cavern MQ Compass Room", "Ice Cavern", RA_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}), - LocationAccess(RC_ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return logic->HasExplosives;}}), - LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS);}}), + LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, true), + LOCATION(RC_ICE_CAVERN_MQ_FREESTANDING_POH, logic->HasExplosives), + LOCATION(RC_ICE_CAVERN_MQ_GS_RED_ICE, logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS)), //Trick: logic->CanUse(RG_SONG_OF_TIME) || LogicIceMQRedIceGS }, {}); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 2816dd43a..2e4b88164 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -43,8 +43,8 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MAIN_LOWER] = Area("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, {[]{return logic->HookshotOrBoomerang;}}), - LocationAccess(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, {[]{return logic->HookshotOrBoomerang;}}), + LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, logic->HookshotOrBoomerang), + LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, logic->HookshotOrBoomerang), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}), @@ -57,7 +57,7 @@ void AreaTable_Init_JabuJabusBelly() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, {[]{return true;}}), + LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, true), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return logic->Swim;}}), @@ -74,7 +74,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_LIFT_LOWER] = Area("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return logic->Swim && (logic->IsChild || logic->CanDive || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku;}}), + LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->Swim && (logic->IsChild || logic->CanDive || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}), @@ -93,7 +93,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_BOOMERANG_ROOM] = Area("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, {[]{return true;}}), + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, true), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), @@ -101,7 +101,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MAP_ROOM] = Area("Jabu Jabus Belly Map Room", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_MAP_CHEST, {[]{return logic->CanUse(RG_BOOMERANG);}}), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->CanUse(RG_BOOMERANG)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), @@ -109,7 +109,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_COMPASS_ROOM] = Area("Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_COMPASS_CHEST, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), @@ -148,7 +148,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM] = Area("Jabu Jabus Belly Near Boss Room", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, {[]{return logic->CanAdultAttack || logic->CanChildAttack;}}), + LOCATION(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, logic->CanAdultAttack || logic->CanChildAttack), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), @@ -165,8 +165,8 @@ void AreaTable_Init_JabuJabusBelly() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, {[]{return logic->CanBlastOrSmash;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, {[]{return logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT);}}), + LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->CanBlastOrSmash), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}), @@ -175,14 +175,14 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_MAIN] = Area("Jabu Jabus Belly MQ Main", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))) || ChildCanAccess(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return (logic->IsChild || logic->CanDive || logic->CanUse(RG_IRON_BOOTS) || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->HasBombchus || (randoCtx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG)));}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_STICKS) || logic->Bombs;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG));}}), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))) || ChildCanAccess(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, (logic->IsChild || logic->CanDive || logic->CanUse(RG_IRON_BOOTS) || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->HasBombchus || (randoCtx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG)))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_STICKS) || logic->Bombs), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG))), //Trick: logic->CanUse(RG_SONG_OF_TIME) || (LogicJabuMQSoTGS && logic->IsChild && logic->CanUse(RG_BOOMERANG)) }, { //Exits @@ -192,9 +192,9 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, {[]{return true;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, {[]{return logic->Swim && (logic->Sticks || logic->CanUse(RG_DINS_FIRE));}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (randoCtx->GetTrickOption(RT_LENS_JABU_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_HOOKSHOT);});}}), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, logic->Swim && (logic->Sticks || logic->CanUse(RG_DINS_FIRE))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, (randoCtx->GetTrickOption(RT_LENS_JABU_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_HOOKSHOT);})), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), @@ -206,9 +206,9 @@ void AreaTable_Init_JabuJabusBelly() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_MQ_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return logic->CanUse(RG_BOOMERANG) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT));}}), + LOCATION(RC_JABU_JABUS_BELLY_MQ_COW, logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), @@ -237,8 +237,8 @@ void AreaTable_Init_JabuJabusBelly() { }, { // Locations - LocationAccess(RC_JABU_JABUS_BELLY_BARINADE_HEART, { [] { return logic->JabuJabusBellyClear; } }), - LocationAccess(RC_BARINADE, { [] { return logic->JabuJabusBellyClear; } }), + LOCATION(RC_JABU_JABUS_BELLY_BARINADE_HEART, logic->JabuJabusBellyClear), + LOCATION(RC_BARINADE, logic->JabuJabusBellyClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp index b33cc9381..708163784 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp @@ -11,15 +11,15 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->KakarikoVillageGateOpen, {[]{return logic->KakarikoVillageGateOpen || (logic->IsChild && (logic->ZeldasLetter || randoCtx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN)));}}), }, { //Locations - LocationAccess(RC_SHEIK_IN_KAKARIKO, {[]{return logic->IsAdult && logic->ForestMedallion && logic->FireMedallion && logic->WaterMedallion;}}), - LocationAccess(RC_KAK_ANJU_AS_CHILD, {[]{return logic->IsChild && logic->AtDay;}}), - LocationAccess(RC_KAK_ANJU_AS_ADULT, {[]{return logic->IsAdult && logic->AtDay;}}), - LocationAccess(RC_KAK_TRADE_POCKET_CUCCO, {[]{return logic->IsAdult && logic->AtDay && logic->PocketEgg && logic->WakeUpAdultTalon;}}), - LocationAccess(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, {[]{return logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KAK_GS_SKULLTULA_HOUSE, {[]{return logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KAK_GS_GUARDS_HOUSE, {[]{return logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KAK_GS_TREE, {[]{return logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return logic->IsChild && (logic->Slingshot || logic->HasBombchus || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslash)) && logic->AtNight && logic->CanGetNightTimeGS;}}), + LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->ForestMedallion && logic->FireMedallion && logic->WaterMedallion), + LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay), + LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay), + LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && logic->PocketEgg && logic->WakeUpAdultTalon), + LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_KAK_GS_WATCHTOWER, logic->IsChild && (logic->Slingshot || logic->HasBombchus || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslash)) && logic->AtNight && logic->CanGetNightTimeGS), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -47,7 +47,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_IMPAS_ROOFTOP] = Area("Kak Impas Rooftop", "Kakariko Village", RA_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return logic->IsAdult && logic->AtNight && logic->CanGetNightTimeGS && (logic->CanJumpslash || logic->CanUseProjectile);}}), + LOCATION(RC_KAK_GS_ABOVE_IMPAS_HOUSE, logic->IsAdult && logic->AtNight && logic->CanGetNightTimeGS && (logic->CanJumpslash || logic->CanUseProjectile)), }, { //Exits Entrance(RR_KAK_IMPAS_LEDGE, {[]{return true;}}), @@ -56,7 +56,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", RA_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_MAN_ON_ROOF, {[]{return true;}}), + LOCATION(RC_KAK_MAN_ON_ROOF, true), }, { //Exits Entrance(RR_KAK_BACKYARD, {[]{return true;}}), @@ -80,12 +80,12 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "Kak House of Skulltula", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_10_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 10;}}), - LocationAccess(RC_KAK_20_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 20;}}), - LocationAccess(RC_KAK_30_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 30;}}), - LocationAccess(RC_KAK_40_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 40;}}), - LocationAccess(RC_KAK_50_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 50;}}), - LocationAccess(RC_KAK_100_GOLD_SKULLTULA_REWARD, {[]{return logic->GoldSkulltulaTokens >= 100;}}) + LOCATION(RC_KAK_10_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 10), + LOCATION(RC_KAK_20_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 20), + LOCATION(RC_KAK_30_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 30), + LOCATION(RC_KAK_40_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 40), + LOCATION(RC_KAK_50_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 50), + LOCATION(RC_KAK_100_GOLD_SKULLTULA_REWARD, logic->GoldSkulltulaTokens >= 100) }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -99,7 +99,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "Kak Impas House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}), + LOCATION(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, true), }, { //Exits Entrance(RR_KAK_IMPAS_LEDGE, {[]{return true;}}), @@ -108,7 +108,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_IMPAS_HOUSE_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}), + LOCATION(RC_KAK_IMPAS_HOUSE_COW, logic->CanUse(RG_EPONAS_SONG)), }, {}); areaTable[RR_KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, { @@ -116,9 +116,9 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->DrainWell, {[]{return logic->DrainWell || (logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS));}}), }, { //Locations - LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return logic->CanUse(RG_BOOMERANG) || logic->DampesWindmillAccess || (logic->IsAdult && randoCtx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslash && randoCtx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH));}}), + LOCATION(RC_KAK_WINDMILL_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG) || logic->DampesWindmillAccess || (logic->IsAdult && randoCtx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslash && randoCtx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH))), //PoH as child not added to trick options yet (needs uncommenting in randomizer_tricks.cpp) - LocationAccess(RC_SONG_FROM_WINDMILL, {[]{return logic->IsAdult && logic->Ocarina;}}), + LOCATION(RC_SONG_FROM_WINDMILL, logic->IsAdult && logic->Ocarina), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -126,14 +126,14 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_BAZAAR] = Area("Kak Bazaar", "Kak Bazaar", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_BAZAAR_ITEM_1, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_2, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_3, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_4, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_5, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_6, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_7, {[]{return true;}}), - LocationAccess(RC_KAK_BAZAAR_ITEM_8, {[]{return true;}}), + LOCATION(RC_KAK_BAZAAR_ITEM_1, true), + LOCATION(RC_KAK_BAZAAR_ITEM_2, true), + LOCATION(RC_KAK_BAZAAR_ITEM_3, true), + LOCATION(RC_KAK_BAZAAR_ITEM_4, true), + LOCATION(RC_KAK_BAZAAR_ITEM_5, true), + LOCATION(RC_KAK_BAZAAR_ITEM_6, true), + LOCATION(RC_KAK_BAZAAR_ITEM_7, true), + LOCATION(RC_KAK_BAZAAR_ITEM_8, true), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -141,7 +141,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "Kak Shooting Gallery", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_SHOOTING_GALLERY_REWARD, {[]{return logic->ChildsWallet && logic->IsAdult && logic->Bow;}}), + LOCATION(RC_KAK_SHOOTING_GALLERY_REWARD, logic->ChildsWallet && logic->IsAdult && logic->Bow), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -149,14 +149,14 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "Kak Potion Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_POTION_SHOP_ITEM_1, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_2, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_3, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_4, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_5, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_6, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_7, {[]{return logic->IsAdult;}}), - LocationAccess(RC_KAK_POTION_SHOP_ITEM_8, {[]{return logic->IsAdult;}}), + LOCATION(RC_KAK_POTION_SHOP_ITEM_1, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_2, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_3, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_4, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_5, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_6, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_7, logic->IsAdult), + LOCATION(RC_KAK_POTION_SHOP_ITEM_8, logic->IsAdult), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -178,8 +178,8 @@ void AreaTable_Init_Kakariko() { } }), }, { - LocationAccess(RC_KAK_TRADE_ODD_MUSHROOM, { [] { return logic->IsAdult && logic->OddMushroom; } }), - LocationAccess(RC_KAK_GRANNYS_SHOP, { [] { return logic->IsAdult && logic->OddMushroom && logic->AdultsWallet; } }), + LOCATION(RC_KAK_TRADE_ODD_MUSHROOM, logic->IsAdult && logic->OddMushroom), + LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && logic->OddMushroom && logic->AdultsWallet), }, { // Exits @@ -188,7 +188,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "Kak Redead Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KAK_REDEAD_GROTTO_CHEST, {[]{return logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), + LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanUse(RG_STICKS) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), @@ -196,11 +196,11 @@ void AreaTable_Init_Kakariko() { areaTable[RR_KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_KAK_OPEN_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_KAK_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_KAK_OPEN_GROTTO_CHEST, true), + LOCATION(RC_KAK_OPEN_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_KAK_BACKYARD, {[]{return true;}}), @@ -213,10 +213,10 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->BugRock, {[]{return true;}}), }, { //Locations - LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG));}}), - LocationAccess(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return logic->ChildsWallet && logic->IsChild && logic->AtNight;}}), //TODO: This needs to change - LocationAccess(RC_GRAVEYARD_GS_WALL, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_GRAVEYARD_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), + LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, logic->ChildsWallet && logic->IsChild && logic->AtNight), //TODO: This needs to change + LOCATION(RC_GRAVEYARD_GS_WALL, logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_GRAVEYARD_GS_BEAN_PATCH, logic->CanPlantBugs && logic->CanChildAttack), }, { //Exits Entrance(RR_GRAVEYARD_SHIELD_GRAVE, {[]{return logic->IsAdult || logic->AtNight;}}), @@ -230,7 +230,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "Graveyard Shield Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}), + LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, true), //Free Fairies }, { //Exits @@ -239,7 +239,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return logic->CanUse(RG_SUNS_SONG);}}), + LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG)), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), @@ -247,8 +247,8 @@ void AreaTable_Init_Kakariko() { areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "Graveyard Composers Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, {[]{return logic->HasFireSource;}}), - LocationAccess(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, {[]{return logic->CanUseProjectile || logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER);}}), + LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource), + LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile || logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), @@ -260,8 +260,8 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->DampesWindmillAccess, {[]{return logic->DampesWindmillAccess || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME));}}), }, { //Locations - LocationAccess(RC_GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}), - LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return logic->IsAdult || randoCtx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH);}}), + LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), + LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->IsAdult || randoCtx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), @@ -270,7 +270,7 @@ void AreaTable_Init_Kakariko() { areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DAMPE_HINT, {[]{return logic->IsAdult;}}), + LOCATION(RC_DAMPE_HINT, logic->IsAdult), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), @@ -281,7 +281,7 @@ void AreaTable_Init_Kakariko() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairyWithoutSuns;}}), }, { //Locations - LocationAccess(RC_GRAVEYARD_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_GRAVEYARD_GOSSIP_STONE, true), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp index c7214d6ca..2f9732b46 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp @@ -11,11 +11,11 @@ void AreaTable_Init_LostWoods() { EventAccess(&logic->ShowedMidoSwordAndShield, {[]{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->KokiriSword && logic->DekuShield);}}), }, { //Locations - LocationAccess(RC_KF_KOKIRI_SWORD_CHEST, {[]{return logic->IsChild;}}), - LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return logic->IsChild && logic->CanChildAttack && logic->AtNight && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KF_GS_BEAN_PATCH, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), - LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return logic->IsAdult && logic->AtNight && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_KF_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), + LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanChildAttack && logic->AtNight && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS), + LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanPlantBugs && logic->CanChildAttack), + LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && logic->AtNight && (logic->HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS), + LOCATION(RC_KF_GOSSIP_STONE, true), }, { //Exits Entrance(RR_KF_LINKS_HOUSE, {[]{return true;}}), @@ -37,8 +37,8 @@ void AreaTable_Init_LostWoods() { EventAccess(&logic->ShowedMidoSwordAndShield, {[]{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->KokiriSword && logic->DekuShield);}}), }, { //Locations - LocationAccess(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, true), + LOCATION(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, true), }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return logic->IsChild || (randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield));}}), @@ -47,7 +47,7 @@ void AreaTable_Init_LostWoods() { areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KF_LINKS_HOUSE_COW, {[]{return logic->IsAdult && logic->CanUse(RG_EPONAS_SONG) && logic->LinksCow;}}), + LOCATION(RC_KF_LINKS_HOUSE_COW, logic->IsAdult && logic->CanUse(RG_EPONAS_SONG) && logic->LinksCow), }, { //Exits Entrance(RR_KOKIRI_FOREST, {[]{return true;}}) @@ -55,10 +55,10 @@ void AreaTable_Init_LostWoods() { areaTable[RR_KF_MIDOS_HOUSE] = Area("KF Mido's House", "KF Mido's House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, {[]{return true;}}), + LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, true), + LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, true), + LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, true), + LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, true), }, { //Exits Entrance(RR_KOKIRI_FOREST, {[]{return true;}}), @@ -81,14 +81,14 @@ void AreaTable_Init_LostWoods() { areaTable[RR_KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "KF Kokiri Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_KF_SHOP_ITEM_1, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_2, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_3, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_4, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_5, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_6, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_7, {[]{return true;}}), - LocationAccess(RC_KF_SHOP_ITEM_8, {[]{return true;}}), + LOCATION(RC_KF_SHOP_ITEM_1, true), + LOCATION(RC_KF_SHOP_ITEM_2, true), + LOCATION(RC_KF_SHOP_ITEM_3, true), + LOCATION(RC_KF_SHOP_ITEM_4, true), + LOCATION(RC_KF_SHOP_ITEM_5, true), + LOCATION(RC_KF_SHOP_ITEM_6, true), + LOCATION(RC_KF_SHOP_ITEM_7, true), + LOCATION(RC_KF_SHOP_ITEM_8, true), }, { //Exits Entrance(RR_KOKIRI_FOREST, {[]{return true;}}), @@ -96,11 +96,11 @@ void AreaTable_Init_LostWoods() { areaTable[RR_KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_KF_STORMS_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_KF_STORMS_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), + LOCATION(RC_KF_STORMS_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_KOKIRI_FOREST, {[]{return true;}}) @@ -120,9 +120,9 @@ void AreaTable_Init_LostWoods() { EventAccess(&logic->BugShrub, {[]{return logic->IsChild && logic->CanCutShrubs;}}), }, { //Locations - LocationAccess(RC_LW_SKULL_KID, {[]{return logic->IsChild && logic->CanUse(RG_SARIAS_SONG);}}), - LocationAccess(RC_LW_TRADE_COJIRO, {[]{return logic->IsAdult && logic->Cojiro;}}), - LocationAccess(RC_LW_TRADE_ODD_POTION, {[]{return logic->IsAdult && logic->OddPoultice && logic->Cojiro;}}), + LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), + LOCATION(RC_LW_TRADE_COJIRO, logic->IsAdult && logic->Cojiro), + LOCATION(RC_LW_TRADE_ODD_POTION, logic->IsAdult && logic->OddPoultice && logic->Cojiro), //all 5 buttons are logically required for memory game //because the chances of being able to beat it //every time you attempt it are as follows: @@ -131,11 +131,11 @@ void AreaTable_Init_LostWoods() { //3 buttons => 3.75% //4 buttons => 25.3125% //5 buttons => 100% - LocationAccess(RC_LW_OCARINA_MEMORY_GAME, {[]{return logic->IsChild && logic->Ocarina && logic->OcarinaButtons >= 5;}}), - LocationAccess(RC_LW_TARGET_IN_WOODS, {[]{return logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT);}}), - LocationAccess(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, {[]{return logic->IsChild && logic->CanStunDeku;}}), - LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, {[]{return logic->CanPlantBugs && logic->CanChildAttack;}}), - LocationAccess(RC_LW_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_LW_OCARINA_MEMORY_GAME, logic->IsChild && logic->Ocarina && logic->OcarinaButtons >= 5), + LOCATION(RC_LW_TARGET_IN_WOODS, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku), + LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanPlantBugs && logic->CanChildAttack), + LOCATION(RC_LW_GOSSIP_STONE, true), }, { //Exits Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}), @@ -151,10 +151,10 @@ void AreaTable_Init_LostWoods() { EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}}), }, { //Locations - LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, {[]{return logic->IsChild && logic->CanStunDeku;}}), - LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, {[]{return logic->IsChild && logic->CanStunDeku;}}), - LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return logic->IsAdult && logic->AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && logic->CanAdultAttack) || (randoCtx->GetTrickOption(RT_LW_GS_BEAN) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->HasBombchus || logic->CanUse(RG_DINS_FIRE)))) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return logic->CanPlantBugs && (logic->CanChildAttack || (randoCtx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->DekuShield));}}), + LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku), + LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku), + LOCATION(RC_LW_GS_ABOVE_THEATER, logic->IsAdult && logic->AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && logic->CanAdultAttack) || (randoCtx->GetTrickOption(RT_LW_GS_BEAN) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->HasBombchus || logic->CanUse(RG_DINS_FIRE)))) && logic->CanGetNightTimeGS), + LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, logic->CanPlantBugs && (logic->CanChildAttack || (randoCtx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->DekuShield))), }, { //Exits Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}), @@ -166,11 +166,11 @@ void AreaTable_Init_LostWoods() { areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, true), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_THE_LOST_WOODS, {[]{return true;}}), @@ -178,8 +178,8 @@ void AreaTable_Init_LostWoods() { areaTable[RR_DEKU_THEATER] = Area("Deku Theater", "Deku Theater", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DEKU_THEATER_SKULL_MASK, {[]{return logic->IsChild && logic->SkullMask;}}), - LocationAccess(RC_DEKU_THEATER_MASK_OF_TRUTH, {[]{return logic->IsChild && logic->MaskOfTruth;}}), + LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->SkullMask), + LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->MaskOfTruth), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, {[]{return true;}}), @@ -187,9 +187,9 @@ void AreaTable_Init_LostWoods() { areaTable[RR_LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "LW Scrubs Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LW_DEKU_SCRUB_GROTTO_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku), + LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku), + LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, {[]{return true;}}), @@ -207,12 +207,12 @@ void AreaTable_Init_LostWoods() { EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CanSummonGossipFairyWithoutSuns;}}), }, { //Locations - LocationAccess(RC_SONG_FROM_SARIA, {[]{return logic->IsChild && logic->ZeldasLetter;}}), - LocationAccess(RC_SHEIK_IN_FOREST, {[]{return logic->IsAdult;}}), - LocationAccess(RC_SFM_GS, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_SFM_MAZE_LOWER_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_SFM_MAZE_UPPER_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_SFM_SARIA_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_SONG_FROM_SARIA, logic->IsChild && logic->ZeldasLetter), + LOCATION(RC_SHEIK_IN_FOREST, logic->IsAdult), + LOCATION(RC_SFM_GS, logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_SFM_MAZE_LOWER_GOSSIP_STONE, true), + LOCATION(RC_SFM_MAZE_UPPER_GOSSIP_STONE, true), + LOCATION(RC_SFM_SARIA_GOSSIP_STONE, true), }, { //Exits Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}), @@ -231,7 +231,7 @@ void AreaTable_Init_LostWoods() { areaTable[RR_SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SFM_WOLFOS_GROTTO_CHEST, {[]{return logic->IsAdult || logic->Slingshot || logic->Sticks || logic->KokiriSword || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD);}}), + LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->IsAdult || logic->Slingshot || logic->Sticks || logic->KokiriSword || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), }, { //Exits Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}), @@ -239,9 +239,9 @@ void AreaTable_Init_LostWoods() { areaTable[RR_SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_SFM_STORMS_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku), + LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku), + LOCATION(RC_SFM_STORMS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}), @@ -249,7 +249,7 @@ void AreaTable_Init_LostWoods() { areaTable[RR_LW_BRIDGE_FROM_FOREST] = Area("LW Bridge From Forest", "Lost Woods", RA_THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_LW_GIFT_FROM_SARIA, {[]{return true;}}), + LOCATION(RC_LW_GIFT_FROM_SARIA, true), }, { //Exits Entrance(RR_LW_BRIDGE, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp index c742c9c2d..b95262ab3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp @@ -24,8 +24,8 @@ void AreaTable_Init_ShadowTemple() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MAP_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), + LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))), }, { //Exits Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -37,9 +37,9 @@ void AreaTable_Init_ShadowTemple() { EventAccess(&logic->FairyPot, {[]{return true;}}), //This fairy pot is only on 3DS }, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_COMPASS_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, {[]{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return false;}}), + LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, false), }, { //Exits Entrance(RR_SHADOW_TEMPLE_HUGE_PIT, {[]{return logic->HasExplosives && logic->IsAdult && logic->SmallKeys(RR_SHADOW_TEMPLE, 1, 2);}}), @@ -48,16 +48,16 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_HUGE_PIT] = Area("Shadow Temple Huge Pit", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot && (logic->Bombs || logic->GoronBracelet || (randoCtx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && logic->HasBombchus));}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return logic->Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->HoverBoots);}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot;}}), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_FREESTANDING_KEY, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot && (logic->Bombs || logic->GoronBracelet || (randoCtx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && logic->HasBombchus))), + LOCATION(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->HoverBoots)), + LOCATION(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, logic->SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot), }, { //Exits Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot && logic->SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}), @@ -65,10 +65,10 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}), + LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, {[]{return logic->CanJumpslash && logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}), @@ -76,10 +76,10 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, {[]{return logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, {[]{return logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return logic->CanAdultAttack;}}), + LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, logic->CanAdultAttack), }, { //Exits Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && logic->HasBombchus)) && logic->SmallKeys(RR_SHADOW_TEMPLE, 5) && logic->CanUse(RG_HOVER_BOOTS) && logic->BossKeyShadowTemple;}}) @@ -100,15 +100,15 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA] = Area("Shadow Temple MQ Dead Hand Area", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return logic->CanJumpslash && logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanJumpslash && logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)), }, {}); areaTable[RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Area("Shadow Temple MQ First Beamos", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, {[]{return logic->CanAdultAttack || logic->Nuts;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, {[]{return logic->CanAdultAttack || logic->Nuts;}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanAdultAttack || logic->Nuts), + LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, logic->CanAdultAttack || logic->Nuts), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, {[]{return logic->HasExplosives && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}}), @@ -116,9 +116,9 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO))), //Trick: logic->CanUse(RG_SONG_OF_TIME) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO))), //Trick: logic->CanUse(RG_SONG_OF_TIME) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) }, { //Exits @@ -128,14 +128,14 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Area("Shadow Temple MQ Lower Huge Pit", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_LONGSHOT);}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return logic->CanJumpslash && logic->HoverBoots && logic->SmallKeys(RR_SHADOW_TEMPLE, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HoverBoots && logic->SmallKeys(RR_SHADOW_TEMPLE, 3) && logic->Hookshot && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && - randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return logic->Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->HoverBoots);}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->IsAdult && logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && logic->HoverBoots) || logic->GoronBracelet), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanJumpslash && logic->HoverBoots && logic->SmallKeys(RR_SHADOW_TEMPLE, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && logic->HoverBoots && logic->SmallKeys(RR_SHADOW_TEMPLE, 3) && logic->Hookshot && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && + randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->HoverBoots)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return logic->HoverBoots && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->Hookshot && logic->SmallKeys(RR_SHADOW_TEMPLE, 4);}}), @@ -146,11 +146,11 @@ void AreaTable_Init_ShadowTemple() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, {[]{return logic->CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, {[]{return true;}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanJumpslash), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->SmallKeys(RR_SHADOW_TEMPLE, 5);}}), @@ -158,8 +158,8 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return logic->Bow || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && logic->HasBombchus);}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, logic->Bow || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && logic->HasBombchus)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return logic->Bow && logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult && logic->CanUse(RG_LONGSHOT);}}), @@ -168,11 +168,11 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, {[]{return logic->CanUse(RG_DINS_FIRE) && logic->SmallKeys(RR_SHADOW_TEMPLE, 6);}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return logic->CanUse(RG_DINS_FIRE) && logic->SmallKeys(RR_SHADOW_TEMPLE, 6);}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->SmallKeys(RR_SHADOW_TEMPLE, 6)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->SmallKeys(RR_SHADOW_TEMPLE, 6)), //below previously returned true - LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return logic->CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND);}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, logic->CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)), + LOCATION(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, true), }, {}); } @@ -201,8 +201,8 @@ void AreaTable_Init_ShadowTemple() { }, { // Locations - LocationAccess(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, { [] { return logic->ShadowTempleClear; } }), - LocationAccess(RC_BONGO_BONGO, { [] { return logic->ShadowTempleClear; } }), + LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->ShadowTempleClear), + LOCATION(RC_BONGO_BONGO, logic->ShadowTempleClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index c859aeb8d..7feb1b064 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -31,9 +31,9 @@ void AreaTable_Init_SpiritTemple() { EventAccess(&logic->NutCrate, {[]{return true;}}), }, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot)));}}), - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot))) && (logic->Sticks || logic->CanUse(RG_DINS_FIRE));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot)));}}), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot)))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot))) && (logic->Sticks || logic->CanUse(RG_DINS_FIRE))), + LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, (logic->Boomerang || logic->Slingshot || (logic->HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (logic->HasExplosives || ((logic->Nuts || logic->Boomerang) && (logic->Sticks || logic->KokiriSword || logic->Slingshot)))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}}), @@ -41,12 +41,12 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child));}}), - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, {[]{return logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), + LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || (logic->CanTakeDamage && (logic->CanJumpslash || logic->HasProjectile(HasProjectileAge::Child))) || (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || - ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->CanTakeDamage && logic->CanJumpslash)));}}), + ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->CanTakeDamage && logic->CanJumpslash)))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return logic->HasExplosives || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}}), @@ -54,11 +54,11 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY);}}), - LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasBombchus || (logic->Bombs && logic->IsAdult && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash);}}), - LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3);}}), - LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3);}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) && (logic->Bow || logic->Hookshot || logic->HasBombchus || (logic->Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)));}}), + LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasBombchus || (logic->Bombs && logic->IsAdult && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3)), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3)), + LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && (logic->Bow || logic->Hookshot || logic->HasBombchus || (logic->Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}}), @@ -66,7 +66,7 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && (logic->CanUse(RG_DINS_FIRE) || (((logic->MagicMeter && logic->FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->Bow && logic->Sticks))) || @@ -74,26 +74,26 @@ void AreaTable_Init_SpiritTemple() { logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->Bow)) && - logic->CanUse(RG_SILVER_GAUNTLETS));}}), - LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + logic->CanUse(RG_SILVER_GAUNTLETS))), + LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && (logic->CanUse(RG_DINS_FIRE) || (((logic->MagicMeter && logic->FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->Bow && logic->Sticks))) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->Bow)) && - logic->CanUse(RG_SILVER_GAUNTLETS));}}), - LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY);}}), - LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->Hookshot || logic->HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (logic->HasExplosives && logic->Boomerang && logic->Hookshot) || + logic->CanUse(RG_SILVER_GAUNTLETS))), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->Hookshot || logic->HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), + LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives && logic->Boomerang && logic->Hookshot) || (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives) || (logic->Hookshot && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->Boomerang && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->Boomerang && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))))), + LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->Boomerang && (logic->Hookshot || logic->HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || (randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives && logic->CanUse(RG_BOOMERANG)) || - (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->Hookshot || logic->HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)));}}), + (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->Hookshot || logic->HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, {[]{return logic->CanJumpslash || logic->HasExplosives;}}), @@ -103,8 +103,8 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTDOOR_HANDS] = Area("Spirit Temple Outdoor Hands", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->Longshot && logic->HasExplosives) || logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives;}}), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->Longshot && logic->HasExplosives) || logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasExplosives), }, { //Exits Entrance(RR_DESERT_COLOSSUS, {[]{return (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)) || (logic->CanUse(RG_SILVER_GAUNTLETS) && ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->HasExplosives) || logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)));}}), @@ -112,9 +112,9 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (logic->MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasExplosives;}}), - LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives;}}), - LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives;}}), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasExplosives), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && (randoCtx->GetTrickOption(RT_SPIRIT_WALL) || logic->CanUse(RG_LONGSHOT) || logic->HasBombchus || ((logic->Bombs || logic->Nuts || logic->CanUse(RG_DINS_FIRE)) && (logic->Bow || logic->CanUse(RG_HOOKSHOT) || logic->Hammer)));}}), @@ -122,8 +122,8 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && ((logic->CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (logic->Bow && logic->Hookshot));}}), - LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (logic->MirrorShield && logic->CanAdultAttack) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}}), + LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && ((logic->CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (logic->Bow && logic->Hookshot))), + LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->MirrorShield && logic->CanAdultAttack) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return logic->MirrorShield && logic->HasExplosives && logic->Hookshot;}}), @@ -144,9 +144,9 @@ void AreaTable_Init_SpiritTemple() { if (randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ()) { areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Area("Spirit Temple MQ Lobby", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, {[]{return true;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanBlastOrSmash;}) && ((logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)));}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, {[]{return logic->HasBombchus || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT))) || (logic->IsChild && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)));}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanBlastOrSmash;}) && ((logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->HasBombchus || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT))) || (logic->IsChild && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)))), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -159,10 +159,10 @@ void AreaTable_Init_SpiritTemple() { EventAccess(&logic->FairyPot, {[]{return logic->FairyPot || (logic->KokiriSword && logic->HasBombchus && logic->Slingshot);}}), }, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer;});}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return logic->KokiriSword && logic->HasBombchus && logic->Slingshot && logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return logic->KokiriSword || logic->Bombs;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return logic->HasBombchus && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Slingshot && (logic->CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME)));})));}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer;})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->KokiriSword && logic->HasBombchus && logic->Slingshot && logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, logic->KokiriSword || logic->Bombs), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->HasBombchus && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Slingshot && (logic->CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME)));})))), //Trick: logic->HasBombchus && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Slingshot && (logic->CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME))))) }, { //Exits @@ -171,14 +171,14 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_ADULT] = Area("Spirit Temple MQ Adult", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash || logic->CanUse(RG_HOVER_BOOTS));}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME) && (logic->MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash || logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME) && (logic->MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return logic->MirrorShield && logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE) && logic->Bow));}}), @@ -190,11 +190,11 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->Bow && logic->Slingshot);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->IsAdult;}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->Bow && logic->Slingshot)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->IsAdult), //Trick: logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || logic->IsAdult - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->Boomerang && (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || logic->IsAdult;}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->Boomerang && (logic->CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || logic->IsAdult), //Trick: (LogicSpiritMQSunBlockGS && logic->Boomerang && (logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT)) || logic->IsAdult }, { //Exits @@ -206,16 +206,16 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, {[]{return true;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, {[]{return logic->Hammer;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, {[]{return true;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby;}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Hammer), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby), }, {}); areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}}), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return logic->MirrorShield && logic->Hookshot;}}), @@ -231,12 +231,12 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Area("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return true;}}), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), }, {}); areaTable[RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND] = Area("Spirit Temple MQ Silver Gauntlets Hand", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return true;}}), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true), }, {}); } @@ -263,8 +263,8 @@ void AreaTable_Init_SpiritTemple() { }, { // Locations - LocationAccess(RC_SPIRIT_TEMPLE_TWINROVA_HEART, { [] { return logic->SpiritTempleClear; } }), - LocationAccess(RC_TWINROVA, { [] { return logic->SpiritTempleClear; } }), + LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->SpiritTempleClear), + LOCATION(RC_TWINROVA, logic->SpiritTempleClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp index e9a0b8678..2534ebef3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp @@ -50,7 +50,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MAP_ROOM] = Area("Water Temple Map Room", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_MAP_CHEST, {[]{return (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT);}}), + LOCATION(RC_WATER_TEMPLE_MAP_CHEST, (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT)), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT);}}), @@ -58,7 +58,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CRACKED_WALL] = Area("Water Temple Cracked Wall", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, {[]{return logic->HasExplosives;}}), + LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, logic->HasExplosives), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return true;}}), @@ -66,7 +66,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_TORCH_ROOM] = Area("Water Temple Torch Room", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_TORCHES_CHEST, {[]{return (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT);}}), + LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT)), }, { //Exits Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return (logic->MagicMeter && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_HOOKSHOT);}}), @@ -80,7 +80,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, {[]{return logic->CanUse(RG_LONGSHOT) || Here(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->IsAdult && logic->HookshotOrBoomerang) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));});}}), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_LONGSHOT) || Here(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (logic->IsAdult && logic->HookshotOrBoomerang) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));})), }, { //Exits Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return logic->SmallKeys(RR_WATER_TEMPLE, 4);}}), @@ -112,7 +112,7 @@ void AreaTable_Init_WaterTemple() { EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_WATER_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}), + LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, true), }, { //Exits Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (logic->CanUse(RG_IRON_BOOTS) || (logic->IsAdult && randoCtx->GetTrickOption(RT_WATER_BK_JUMP_DIVE)) || logic->IsChild || logic->CanDive) && logic->SmallKeys(RR_WATER_TEMPLE, 5);}}), @@ -120,7 +120,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_BEHIND_GATE, {[]{return (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}}), + LOCATION(RC_WATER_TEMPLE_GS_BEHIND_GATE, (logic->CanJumpslash || logic->CanUse(RG_MEGATON_HAMMER)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)))), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_IRON_BOOTS);}}), @@ -134,8 +134,8 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Area("Water Temple Dragon Room", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->HasBombchus)) || (logic->IsChild && randoCtx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasBombchus))) && (logic->CanDive || logic->CanUse(RG_IRON_BOOTS))) || - Here(RR_WATER_TEMPLE_RIVER, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanDive || logic->CanUse(RG_IRON_BOOTS))) || randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));});}}), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->HasBombchus)) || (logic->IsChild && randoCtx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasBombchus))) && (logic->CanDive || logic->CanUse(RG_IRON_BOOTS))) || + Here(RR_WATER_TEMPLE_RIVER, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW) && ((randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->CanDive || logic->CanUse(RG_IRON_BOOTS))) || randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));})), }, { //Exits Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return true;}}), @@ -153,7 +153,7 @@ void AreaTable_Init_WaterTemple() { EventAccess(&logic->WaterTempleMiddle, {[]{return logic->WaterTempleMiddle || logic->CanUse(RG_ZELDAS_LULLABY);}}), }, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return logic->CanUse(RG_LONGSHOT) || (((randoCtx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (randoCtx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->WaterTempleHigh && logic->HookshotOrBoomerang);}}), + LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((randoCtx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (randoCtx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->WaterTempleHigh && logic->HookshotOrBoomerang)), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}), @@ -162,7 +162,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT] = Area("Water Temple Central Pillar Basement", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, {[]{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer >= 40;}}), + LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer >= 40), }, { //Exits Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer >= 16;}}), @@ -170,7 +170,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_EAST_MIDDLE] = Area("Water Temple East Middle", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_COMPASS_CHEST, {[]{return logic->CanUseProjectile;}}), + LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_IRON_BOOTS);}}), @@ -192,7 +192,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_CORRIDOR] = Area("Water Temple Block Corridor", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, {[]{return logic->GoronBracelet && (logic->WaterTempleLow || logic->WaterTempleMiddle);}}), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->GoronBracelet && (logic->WaterTempleLow || logic->WaterTempleMiddle)), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_HOOKSHOT);}}), @@ -200,7 +200,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_RANG_FALLING_PLATFORM_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT));}}), + LOCATION(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, logic->CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_RANG_FALLING_PLATFORM_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT))), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_WATER_TEMPLE, 4);}}), @@ -221,7 +221,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_LONGSHOT_ROOM] = Area("Water Temple Longshot Room", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_LONGSHOT_CHEST, {[]{return true;}}), + LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, true), }, { //Exits Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, {[]{return true;}}), @@ -230,8 +230,8 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_RIVER_CHEST, {[]{return (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}}), - LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_WATER_RIVER_GS) && logic->CanUse(RG_LONGSHOT));}}), + LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_WATER_TEMPLE_GS_RIVER, (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_WATER_RIVER_GS) && logic->CanUse(RG_LONGSHOT))), }, { //Exits Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, {[]{return (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}}), @@ -261,8 +261,8 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_MAP_CHEST, {[]{return logic->HasFireSource && logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_ZORA_TUNIC) && logic->CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS)) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_SONG_OF_TIME)));}}), + LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->HasFireSource && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->IsAdult && logic->CanUse(RG_ZORA_TUNIC) && logic->CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS)) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_SONG_OF_TIME)))), //Trick: logic->IsAdult && logic->CanUse(RG_ZORA_TUNIC) && logic->CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && logic->CanUse(RG_FIRE_ARROWS)) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_SONG_OF_TIME))) }, { //Exits @@ -271,11 +271,11 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS] = Area("Water Temple MQ Lowered Water Levels", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, {[]{return ((logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || logic->CanUse(RG_DINS_FIRE) || Here(RR_WATER_TEMPLE_MQ_LOBBY, []{return logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasExplosives;})) && - (logic->CanJumpslash || logic->CanUseProjectile);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, {[]{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, {[]{return logic->CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, {[]{return logic->IsAdult && logic->CanUse(RG_LONGSHOT);}}), + LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, ((logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || logic->CanUse(RG_DINS_FIRE) || Here(RR_WATER_TEMPLE_MQ_LOBBY, []{return logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasExplosives;})) && + (logic->CanJumpslash || logic->CanUseProjectile)), + LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, logic->IsAdult && logic->CanUse(RG_LONGSHOT)), }, {}); areaTable[RR_WATER_TEMPLE_MQ_DARK_LINK_REGION] = Area("Water Temple MQ Dark Link Region", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, { @@ -284,8 +284,8 @@ void AreaTable_Init_WaterTemple() { EventAccess(&logic->NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return logic->IsAdult && logic->WaterTimer >= 24 && logic->CanUse(RG_DINS_FIRE) && (randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE) || logic->CanDive || logic->CanUse(RG_IRON_BOOTS));}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_RIVER, {[]{return true;}}), + LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->IsAdult && logic->WaterTimer >= 24 && logic->CanUse(RG_DINS_FIRE) && (randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE) || logic->CanDive || logic->CanUse(RG_IRON_BOOTS))), + LOCATION(RC_WATER_TEMPLE_MQ_GS_RIVER, true), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, {[]{return logic->IsAdult && logic->WaterTimer >= 24 && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_IRON_BOOTS);}}), @@ -293,9 +293,9 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return logic->HoverBoots || logic->CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, {[]{return logic->CanUse(RG_FIRE_ARROWS) && (logic->HoverBoots || logic->CanUse(RG_SCARECROW));}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return randoCtx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) || (logic->SmallKeys(RR_WATER_TEMPLE, 2) && (logic->HoverBoots || logic->CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && logic->CanJumpslash);}}), + LOCATION(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, logic->HoverBoots || logic->CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)), + LOCATION(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, logic->CanUse(RG_FIRE_ARROWS) && (logic->HoverBoots || logic->CanUse(RG_SCARECROW))), + LOCATION(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, randoCtx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) || (logic->SmallKeys(RR_WATER_TEMPLE, 2) && (logic->HoverBoots || logic->CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && logic->CanJumpslash)), //Trick: LogicWaterMQLockedGS || (logic->SmallKeys(RR_WATER_TEMPLE, 2) && (logic->HoverBoots || logic->CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump)) }, {}); } @@ -323,8 +323,8 @@ void AreaTable_Init_WaterTemple() { }, { // Locations - LocationAccess(RC_WATER_TEMPLE_MORPHA_HEART, { [] { return logic->WaterTempleClear; } }), - LocationAccess(RC_MORPHA, { [] { return logic->WaterTempleClear; } }), + LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->WaterTempleClear), + LOCATION(RC_MORPHA, logic->WaterTempleClear), }, { // Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index dddad29a1..2344c13a8 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -6,7 +6,7 @@ using namespace Rando; void AreaTable_Init_ZorasDomain() { areaTable[RR_ZR_FRONT] = Area("ZR Front", "Zora River", RA_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ZR_GS_TREE, {[]{return logic->IsChild && logic->CanChildAttack;}}), + LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanChildAttack), }, { //Exits Entrance(RR_ZORAS_RIVER, {[]{return logic->IsAdult || logic->CanBlastOrSmash;}}), @@ -21,21 +21,21 @@ void AreaTable_Init_ZorasDomain() { EventAccess(&logic->BugShrub, {[]{return logic->BugShrub || logic->CanCutShrubs;}}), }, { //Locations - LocationAccess(RC_ZR_MAGIC_BEAN_SALESMAN, {[]{return logic->ChildsWallet && logic->IsChild;}}), - LocationAccess(RC_ZR_FROGS_OCARINA_GAME, {[]{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_SARIAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_SONG_OF_STORMS);}}), - LocationAccess(RC_ZR_FROGS_IN_THE_RAIN, {[]{return logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS);}}), - LocationAccess(RC_ZR_FROGS_ZELDAS_LULLABY, {[]{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY);}}), - LocationAccess(RC_ZR_FROGS_EPONAS_SONG, {[]{return logic->IsChild && logic->CanUse(RG_EPONAS_SONG);}}), - LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return logic->IsChild && logic->CanUse(RG_SARIAS_SONG);}}), - LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return logic->IsChild && logic->CanUse(RG_SUNS_SONG);}}), - LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return logic->IsChild && logic->CanUse(RG_SONG_OF_TIME);}}), - LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return logic->IsChild || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && randoCtx->GetTrickOption(RT_ZR_LOWER));}}), - LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return logic->IsChild || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && randoCtx->GetTrickOption(RT_ZR_UPPER));}}), - LocationAccess(RC_ZR_GS_LADDER, {[]{return logic->IsChild && logic->AtNight && logic->CanChildAttack && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZR_GS_NEAR_RAISED_GROTTOS, {[]{return logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZR_GS_ABOVE_BRIDGE, {[]{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->ChildsWallet && logic->IsChild), + LOCATION(RC_ZR_FROGS_OCARINA_GAME, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_SARIAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_ZR_FROGS_IN_THE_RAIN, logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_ZR_FROGS_ZELDAS_LULLABY, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_ZR_FROGS_EPONAS_SONG, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_ZR_FROGS_SARIAS_SONG, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), + LOCATION(RC_ZR_FROGS_SUNS_SONG, logic->IsChild && logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_ZR_FROGS_SONG_OF_TIME, logic->IsChild && logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, logic->IsChild || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && randoCtx->GetTrickOption(RT_ZR_LOWER))), + LOCATION(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, logic->IsChild || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && randoCtx->GetTrickOption(RT_ZR_UPPER))), + LOCATION(RC_ZR_GS_LADDER, logic->IsChild && logic->AtNight && logic->CanChildAttack && logic->CanGetNightTimeGS), + LOCATION(RC_ZR_GS_NEAR_RAISED_GROTTOS, logic->IsAdult && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_ZR_GS_ABOVE_BRIDGE, logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, true), + LOCATION(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, true), }, { //Exits Entrance(RR_ZR_FRONT, {[]{return true;}}), @@ -54,11 +54,11 @@ void AreaTable_Init_ZorasDomain() { areaTable[RR_ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, { //Locations - LocationAccess(RC_ZR_OPEN_GROTTO_CHEST, {[]{return true;}}), - LocationAccess(RC_ZR_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}), - LocationAccess(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, {[]{return logic->CanBreakLowerBeehives;}}), - LocationAccess(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, {[]{return logic->CanBreakLowerBeehives;}}), + LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), + LOCATION(RC_ZR_OPEN_GROTTO_FISH, logic->HasBottle), + LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, true), + LOCATION(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, logic->CanBreakLowerBeehives), + LOCATION(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, logic->CanBreakLowerBeehives), }, { //Exits Entrance(RR_ZORAS_RIVER, {[]{return true;}}), @@ -74,9 +74,9 @@ void AreaTable_Init_ZorasDomain() { areaTable[RR_ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "ZR Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return logic->CanStunDeku;}}), - LocationAccess(RC_ZR_STORMS_GROTTO_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku), + LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku), + LOCATION(RC_ZR_STORMS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_ZORAS_RIVER, {[]{return true;}}), @@ -93,19 +93,19 @@ void AreaTable_Init_ZorasDomain() { EventAccess(&logic->DeliverLetter, {[]{return logic->DeliverLetter || (logic->RutosLetter && logic->IsChild && randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN));}}), }, { //Locations - LocationAccess(RC_ZD_DIVING_MINIGAME, {[]{return logic->Swim && logic->ChildsWallet && logic->IsChild;}}), - LocationAccess(RC_ZD_CHEST, {[]{return logic->IsChild && logic->CanUse(RG_STICKS);}}), - LocationAccess(RC_ZD_KING_ZORA_THAWED, {[]{return logic->KingZoraThawed;}}), - LocationAccess(RC_ZD_TRADE_PRESCRIPTION, {[]{return logic->KingZoraThawed && logic->Prescription;}}), - LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return logic->IsAdult && logic->AtNight && (logic->HookshotOrBoomerang || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->Bow || (logic->MagicMeter && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (randoCtx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslash)) && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZD_FISH_1, {[]{return logic->IsChild && logic->HasBottle;}}), - LocationAccess(RC_ZD_FISH_2, {[]{return logic->IsChild && logic->HasBottle;}}), - LocationAccess(RC_ZD_FISH_3, {[]{return logic->IsChild && logic->HasBottle;}}), - LocationAccess(RC_ZD_FISH_4, {[]{return logic->IsChild && logic->HasBottle;}}), - LocationAccess(RC_ZD_FISH_5, {[]{return logic->IsChild && logic->HasBottle;}}), - LocationAccess(RC_ZD_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, {[]{return logic->CanBreakUpperBeehives;}}), - LocationAccess(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_ZD_DIVING_MINIGAME, logic->Swim && logic->ChildsWallet && logic->IsChild), + LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS)), + LOCATION(RC_ZD_KING_ZORA_THAWED, logic->KingZoraThawed), + LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->KingZoraThawed && logic->Prescription), + LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && logic->AtNight && (logic->HookshotOrBoomerang || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->Bow || (logic->MagicMeter && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (randoCtx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslash)) && logic->CanGetNightTimeGS), + LOCATION(RC_ZD_FISH_1, logic->IsChild && logic->HasBottle), + LOCATION(RC_ZD_FISH_2, logic->IsChild && logic->HasBottle), + LOCATION(RC_ZD_FISH_3, logic->IsChild && logic->HasBottle), + LOCATION(RC_ZD_FISH_4, logic->IsChild && logic->HasBottle), + LOCATION(RC_ZD_FISH_5, logic->IsChild && logic->HasBottle), + LOCATION(RC_ZD_GOSSIP_STONE, true), + LOCATION(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, logic->CanBreakUpperBeehives), + LOCATION(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return true;}}), @@ -117,7 +117,7 @@ void AreaTable_Init_ZorasDomain() { areaTable[RR_ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", RA_ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, {[]{return logic->CanBreakUpperBeehives;}}), + LOCATION(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, logic->CanBreakUpperBeehives), }, { //Exits Entrance(RR_ZORAS_DOMAIN, {[]{return logic->DeliverLetter || randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && logic->IsAdult);}}), @@ -126,14 +126,14 @@ void AreaTable_Init_ZorasDomain() { areaTable[RR_ZD_SHOP] = Area("ZD Shop", "ZD Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ZD_SHOP_ITEM_1, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_2, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_3, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_4, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_5, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_6, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_7, {[]{return true;}}), - LocationAccess(RC_ZD_SHOP_ITEM_8, {[]{return true;}}), + LOCATION(RC_ZD_SHOP_ITEM_1, true), + LOCATION(RC_ZD_SHOP_ITEM_2, true), + LOCATION(RC_ZD_SHOP_ITEM_3, true), + LOCATION(RC_ZD_SHOP_ITEM_4, true), + LOCATION(RC_ZD_SHOP_ITEM_5, true), + LOCATION(RC_ZD_SHOP_ITEM_6, true), + LOCATION(RC_ZD_SHOP_ITEM_7, true), + LOCATION(RC_ZD_SHOP_ITEM_8, true), }, { //Exits Entrance(RR_ZORAS_DOMAIN, {[]{return true;}}), @@ -153,13 +153,13 @@ void AreaTable_Init_ZorasDomain() { EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}}), }, { //Locations - LocationAccess(RC_ZF_ICEBERC_FREESTANDING_POH, {[]{return logic->IsAdult;}}), - LocationAccess(RC_ZF_BOTTOM_FREESTANDING_POH, {[]{return logic->IsAdult && logic->IronBoots && logic->WaterTimer >= 24;}}), - LocationAccess(RC_ZF_GS_TREE, {[]{return logic->IsChild;}}), - LocationAccess(RC_ZF_GS_ABOVE_THE_LOG, {[]{return logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZF_GS_HIDDEN_CAVE, {[]{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBlastOrSmash && logic->HookshotOrBoomerang && logic->IsAdult && logic->AtNight && logic->CanGetNightTimeGS;}}), - LocationAccess(RC_ZF_FAIRY_GOSSIP_STONE, {[]{return true;}}), - LocationAccess(RC_ZF_JABU_GOSSIP_STONE, {[]{return true;}}), + LOCATION(RC_ZF_ICEBERC_FREESTANDING_POH, logic->IsAdult), + LOCATION(RC_ZF_BOTTOM_FREESTANDING_POH, logic->IsAdult && logic->IronBoots && logic->WaterTimer >= 24), + LOCATION(RC_ZF_GS_TREE, logic->IsChild), + LOCATION(RC_ZF_GS_ABOVE_THE_LOG, logic->IsChild && logic->HookshotOrBoomerang && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_ZF_GS_HIDDEN_CAVE, logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBlastOrSmash && logic->HookshotOrBoomerang && logic->IsAdult && logic->AtNight && logic->CanGetNightTimeGS), + LOCATION(RC_ZF_FAIRY_GOSSIP_STONE, true), + LOCATION(RC_ZF_JABU_GOSSIP_STONE, true), }, { //Exits Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return true;}}), @@ -170,7 +170,7 @@ void AreaTable_Init_ZorasDomain() { areaTable[RR_ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_ZF_GREAT_FAIRY_REWARD, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}), + LOCATION(RC_ZF_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 36263197a..76c293950 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -5,6 +5,7 @@ #include "dungeon.h" #include "../../OTRGlobals.h" #include "../../UIWidgets.hpp" +#include "3drando/location_access.hpp" #include #include @@ -927,6 +928,8 @@ void CheckTrackerWindow::DrawElement() { return; } + AreaTable_Init(); + ImGui::TableNextRow(0, headerHeight); ImGui::TableNextColumn(); UIWidgets::EnhancementCheckbox( @@ -1561,6 +1564,19 @@ void DrawLocation(RandomizerCheck rc) { ImGui::Text(" (%s)", txt.c_str()); ImGui::PopStyleColor(); } + + if (CVarGetInteger("gCheckTrackerOptionShowLogic", 0)) { + std::vector locationsInRegion = areaTable[itemLoc->GetParentRegionKey()].locations; + for (auto& locationInRegion : locationsInRegion) { + if (locationInRegion.GetLocation() == rc) { + std::string conditionStr = locationInRegion.GetConditionStr(); + if (conditionStr != "true") { + UIWidgets::InsertHelpHoverText(conditionStr); + } + return; + } + } + } } static std::set rainbowCVars = { @@ -1698,6 +1714,8 @@ void CheckTrackerSettingsWindow::DrawElement() { RecalculateAreaTotals(); } UIWidgets::Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings."); + UIWidgets::EnhancementCheckbox("Show Logic", "gCheckTrackerOptionShowLogic"); + UIWidgets::Tooltip("If enabled, will show a check's logic when hovering over it."); // Filtering settings UIWidgets::PaddedSeparator(); From 7a17fe221fd9a4b912a5d8ea1cb75cd2b46e3800 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sun, 7 Jul 2024 21:22:23 -0400 Subject: [PATCH 266/300] Don't play the intro cutscene on child spawn even if location is shuffled (#4226) * Don't play the intro cutscene on child spawn even if location is shuffled. * Fix condition to not always skip cutscene when IS_RANDO is true. * Fix typo --- soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp | 5 +++-- soh/soh/Enhancements/randomizer/settings.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp index 95e9c2d10..f9dc8c239 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp @@ -11,8 +11,9 @@ extern "C" { void SkipIntro_Register() { REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO)) { - if (gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || + IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true)) { + if (gSaveContext.entranceIndex == (IS_RANDO ? Entrance_GetOverride(ENTR_LINKS_HOUSE_0) : ENTR_LINKS_HOUSE_0) && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.cutsceneIndex = 0; *should = false; } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index a67bbddab..cbaf774f0 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -65,7 +65,7 @@ void Settings::CreateOptions() { mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] = Option::Bool("Grottos Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]); mOptions[RSK_SHUFFLE_OWL_DROPS] = Option::Bool("Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]); mOptions[RSK_SHUFFLE_WARP_SONGS] = Option::Bool("Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]); - mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpanws"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]); + mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]); mOptions[RSK_MIXED_ENTRANCE_POOLS] = Option::Bool("Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances"), mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]); mOptions[RSK_MIX_DUNGEON_ENTRANCES] = Option::Bool("Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons"), mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE); mOptions[RSK_MIX_BOSS_ENTRANCES] = Option::Bool("Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses"), mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE); From 77770ba3b2d93b96220909fefe0ef85b2c55ecf3 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 9 Jul 2024 23:57:28 +0100 Subject: [PATCH 267/300] fix hint crash on windows (#4227) --- soh/soh/Enhancements/custom-message/CustomMessageManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index dd0591181..1386673d9 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -184,7 +184,7 @@ CustomMessage CustomMessage::operator+(const CustomMessage& right) const { newColors.push_back(color); } std::vector newCapital = capital; - newCapital.insert(capital.end(), right.GetCapital().begin(), right.GetCapital().end()); + newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end()); return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW), messages[LANGUAGE_GER] + right.GetGerman(MF_RAW), messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), From a0fda39a75a4c628e2a19249bb7e736d540acf72 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:38:52 +0100 Subject: [PATCH 268/300] Force Warp Song Hints off when Warp Songs are not shuffled (#4229) --- soh/soh/Enhancements/randomizer/settings.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index cbaf774f0..0d702e480 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1739,6 +1739,12 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_HINT_DISTRIBUTION].Unhide(); } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), RO_GENERIC_ON)) { + mOptions[RSK_WARP_SONG_HINTS].Enable(); + } else { + mOptions[RSK_WARP_SONG_HINTS].Disable("This option is disabled since warp song locations not shuffled."); + } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), RO_GENERIC_OFF)) { mOptions[RSK_MALON_HINT].Enable(); } else { @@ -2039,6 +2045,10 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio mOptions[RSK_KEYSANITY].SetSelectedIndex(3); } + if (!mOptions[RSK_SHUFFLE_WARP_SONGS]) { + mOptions[RSK_WARP_SONG_HINTS].SetSelectedIndex(RO_GENERIC_OFF); + } + if (!mOptions[RSK_SHUFFLE_COWS]) { mOptions[RSK_MALON_HINT].SetSelectedIndex(RO_GENERIC_OFF); } From ba82bfbba6d89e0d0f0626d50515e5f7dfae7a14 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 13 Jul 2024 16:51:54 -0400 Subject: [PATCH 269/300] Fix spawn shuffle when starting age is adult/random. (#4230) * Fix spawn shuffle when starting age is adult. * Handle adult start without spawn shuffle * Handle correct entrance for adult start + spawn shuffle and add comments. * Fix grotto spawn cutscene skips. * Fix an issue with randomized starting age. --- .../TimeSavers/SkipCutscene/SkipIntro.cpp | 35 +++++++++++++++---- soh/soh/Enhancements/randomizer/savefile.cpp | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp index f9dc8c239..2402f841c 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp @@ -5,18 +5,41 @@ extern "C" { #include "z64save.h" #include "functions.h" + #include "soh/Enhancements/randomizer/randomizer_grotto.h" extern PlayState* gPlayState; extern SaveContext gSaveContext; } void SkipIntro_Register() { REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || - IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true)) { - if (gSaveContext.entranceIndex == (IS_RANDO ? Entrance_GetOverride(ENTR_LINKS_HOUSE_0) : ENTR_LINKS_HOUSE_0) && gSaveContext.cutsceneIndex == 0xFFF1) { - gSaveContext.cutsceneIndex = 0; - *should = false; - } + // If we're playing rando and if starting age is adult and/or overworld spawns are shuffled we need to skip + // the cutscene regardless of the enhancement being on. + bool adultStart = gSaveContext.linkAge == LINK_AGE_ADULT; + bool shuffleOverworldSpawns = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true); + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || (IS_RANDO && (adultStart || shuffleOverworldSpawns))) { + // Calculate spawn location. Start with vanilla, Link's house. + int32_t spawnEntrance = ENTR_LINKS_HOUSE_0; + // If we're not in rando, we can skip all of the below. + if (IS_RANDO) { + // If starting age is shuffled, use vanilla adult spawn/prelude warp. + if (adultStart) { + spawnEntrance = ENTR_TEMPLE_OF_TIME_7; + } + // If we're shuffling overworld spawns we'll need to get the Entrance Override + if (shuffleOverworldSpawns) { + // If we're shuffling overworld spawns the adult spawn is ENTR_HYRULE_FIELD_10 instead of + // ENTR_TEMPLE_OF_TIME_7, so that spawn and Prelude don't share an entrance. + if (adultStart){ + spawnEntrance = ENTR_HYRULE_FIELD_10; + } + spawnEntrance = Grotto_OverrideSpecialEntrance(Entrance_GetOverride(spawnEntrance)); + } + } + // Skip the intro cutscene for whatever the spawnEntrance is calculated to be. + if (gSaveContext.entranceIndex == spawnEntrance) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } } }); } diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index e8998b4a4..4900e4a70 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -331,7 +331,7 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.adultTradeItems = 0; } - int startingAge = Randomizer_GetSettingValue(RSK_STARTING_AGE); + int startingAge = OTRGlobals::Instance->gRandoContext->GetSettings()->ResolvedStartingAge(); switch (startingAge) { case RO_AGE_ADULT: // Adult gSaveContext.linkAge = LINK_AGE_ADULT; From 73be4e55591f547df1a27884fdddbae36f603e07 Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 15 Jul 2024 22:24:38 -0400 Subject: [PATCH 270/300] Bump LUS for 2cyc color combiner fix (#4221) --- CMakeLists.txt | 2 +- libultraship | 2 +- .../cosmetics/authenticGfxPatches.cpp | 16 ---------------- soh/soh/SohGui.cpp | 3 +++ 4 files changed, 5 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 490489f55..02b765622 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Set GBI version ################################################################################ -add_compile_definitions(F3DEX_GBI_2) +set(GBI_UCODE F3DEX_GBI_2) ################################################################################ # Sub-projects diff --git a/libultraship b/libultraship index 9907ebfd6..31e9b009f 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 9907ebfd66ff5bf903ecb7327cca69014993772b +Subproject commit 31e9b009f94e7074a847c7954926cba354cd7c72 diff --git a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp index f31eedd2c..6b74769c1 100644 --- a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp +++ b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp @@ -9,7 +9,6 @@ extern "C" { #include "objects/object_gi_soldout/object_gi_soldout.h" #include "objects/object_ik/object_ik.h" #include "objects/object_link_child/object_link_child.h" -#include "objects/object_ru2/object_ru2.h" uint32_t ResourceMgr_GameHasMasterQuest(); uint32_t ResourceMgr_GameHasOriginal(); @@ -189,25 +188,10 @@ void PatchIronKnuckleTextureOverflow() { } } -void PatchPrincessRutoEaring() { - // FAST3D: This is a hack for the issue of both TEXEL0 and TEXEL1 using the same texture with different settings. - // Ruto's earring uses both TEXEL0 and TEXEL1 to render. The issue is that it never loads anything into TEXEL1, so - // it reuses whatever happens to be there, which is the water temple brick texture. It just so happens that the - // earring texture loads into the same place in TMEM as the brick texture, so when it comes to rendering, TEXEL1 - // uses the earring texture with different clamp settings, and it displays without noticeable error. However, both - // texel samplers are not intended to be used for the same texture with different settings, so this misuse confuses - // our texture cache, and we load the wrong settings for the earrings texture. This patch is a hack that replaces - // TEXEL1 with TEXEL0, which is most likely the original intention, and all is well. - ResourceMgr_PatchGfxByName(gAdultRutoHeadDL, "RutoEaringTileFix", 162, - gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED, - TEXEL0, 0, PRIM_LOD_FRAC, COMBINED)); -} - void ApplyAuthenticGfxPatches() { PatchDekuStickTextureOverflow(); PatchFreezardTextureOverflow(); PatchIronKnuckleTextureOverflow(); - PatchPrincessRutoEaring(); } // Patches the Sold Out GI DL to render the texture in the mirror boundary diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 25763525d..71a366021 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -206,6 +206,9 @@ namespace SohGui { } void Destroy() { + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); + gui->RemoveAllGuiWindows(); + mModalWindow = nullptr; mAdvancedResolutionSettingsWindow = nullptr; mRandomizerSettingsWindow = nullptr; From 2ff795e2276fd8ff671423f636576dc0973dd473 Mon Sep 17 00:00:00 2001 From: Angelo Bulfone Date: Tue, 16 Jul 2024 14:39:18 -0600 Subject: [PATCH 271/300] Fix MQ Checks (#4234) --- .../Enhancements/randomizer/hook_handlers.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index e164eae16..303b8af42 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -3,6 +3,7 @@ #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/Enhancements/randomizer/randomizerTypes.h" +#include "soh/Enhancements/randomizer/dungeon.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" @@ -44,16 +45,25 @@ extern s32 func_80836898(PlayState* play, Player* player, PlayerFuncA74 func); #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +bool LocMatchesQuest(Rando::Location loc) { + if (loc.GetQuest() == RCQUEST_BOTH) { + return true; + } else { + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc.GetScene()); + return (dungeon->IsMQ() && loc.GetQuest() == RCQUEST_MQ) || (dungeon->IsVanilla() && loc.GetQuest() == RCQUEST_VANILLA); + } +} + RandomizerCheck GetRandomizerCheckFromFlag(int16_t flagType, int16_t flag) { for (auto& loc : Rando::StaticData::GetLocationTable()) { - if (loc.GetCollectionCheck().flag == flag && ( + if ((loc.GetCollectionCheck().flag == flag && ( (flagType == FLAG_INF_TABLE && loc.GetCollectionCheck().type == SPOILER_CHK_INF_TABLE) || (flagType == FLAG_EVENT_CHECK_INF && loc.GetCollectionCheck().type == SPOILER_CHK_EVENT_CHK_INF) || (flagType == FLAG_ITEM_GET_INF && loc.GetCollectionCheck().type == SPOILER_CHK_ITEM_GET_INF) || (flagType == FLAG_RANDOMIZER_INF && loc.GetCollectionCheck().type == SPOILER_CHK_RANDOMIZER_INF) ) || (loc.GetActorParams() == flag && flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) - ) { + ) && LocMatchesQuest(loc)) { return loc.GetRandomizerCheck(); } } @@ -67,7 +77,7 @@ RandomizerCheck GetRandomizerCheckFromSceneFlag(int16_t sceneNum, int16_t flagTy (flagType == FLAG_SCENE_TREASURE && loc.GetCollectionCheck().type == SPOILER_CHK_CHEST) || (flagType == FLAG_SCENE_COLLECTIBLE && loc.GetCollectionCheck().type == SPOILER_CHK_COLLECTABLE) || (flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) - )) { + ) && LocMatchesQuest(loc)) { return loc.GetRandomizerCheck(); } } From 8eb63049992f9dda531a0bc236161cbd1dae2821 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Wed, 17 Jul 2024 05:25:06 +0200 Subject: [PATCH 272/300] Rando: Keyring tristate (#3960) * Initial implementation * Fix build * Update UIWidgets.cpp * Update option.cpp * Update settings.cpp * Update settings.cpp * Apply Pepper0ni's patch Co-Authored-By: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> * Update option_descriptions.cpp --------- Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> --- soh/soh/Enhancements/randomizer/option.cpp | 23 +++++ soh/soh/Enhancements/randomizer/option.h | 2 + .../randomizer/option_descriptions.cpp | 3 +- .../Enhancements/randomizer/randomizerTypes.h | 6 ++ soh/soh/Enhancements/randomizer/settings.cpp | 93 +++++++++++-------- soh/soh/UIWidgets.cpp | 55 ++++++++++- soh/soh/UIWidgets.hpp | 4 +- 7 files changed, 141 insertions(+), 45 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp index acccb9c5b..36fdd1f8b 100644 --- a/soh/soh/Enhancements/randomizer/option.cpp +++ b/soh/soh/Enhancements/randomizer/option.cpp @@ -140,6 +140,9 @@ bool Option::RenderImGui() const { case WidgetType::Checkbox: changed = RenderCheckbox(); break; + case WidgetType::TristateCheckbox: + changed = RenderTristateCheckbox(); + break; case WidgetType::Combobox: changed = RenderCombobox(); break; @@ -209,6 +212,26 @@ bool Option::RenderCheckbox() const { return changed; } +bool Option::RenderTristateCheckbox() const { + bool changed = false; + if (disabled) { + UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); + } + int val = CVarGetInteger(cvarName.c_str(), defaultOption); + if (CustomCheckboxTristate(name.c_str(), &val, disabled, disabledGraphic)) { + CVarSetInteger(cvarName.c_str(), val); + changed = true; + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } + if (!description.empty()) { + UIWidgets::InsertHelpHoverText(description.c_str()); + } + if (disabled) { + UIWidgets::ReEnableComponent(disabledText.c_str()); + } + return changed; +} + bool Option::RenderCombobox() const { bool changed = false; if (disabled) { diff --git a/soh/soh/Enhancements/randomizer/option.h b/soh/soh/Enhancements/randomizer/option.h index 8ec4a32b1..57b3dae2c 100644 --- a/soh/soh/Enhancements/randomizer/option.h +++ b/soh/soh/Enhancements/randomizer/option.h @@ -34,6 +34,7 @@ enum class OptionCategory { */ enum class WidgetType { Checkbox, /** Default for Bools, not compatible if options.size() > 2. */ + TristateCheckbox, /** Compatible with U8s, not compatible if options.size() != 3. */ Combobox, /** Default for U8s, works with U8s and Bools. */ Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */ }; @@ -317,6 +318,7 @@ protected: private: bool RenderCheckbox() const; + bool RenderTristateCheckbox() const; bool RenderCombobox() const; bool RenderSlider() const; std::variant var; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 522007403..784d9d1f3 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -370,7 +370,8 @@ void Settings::CreateOptionDescriptions() { "\n" "Count - A specified amount of randomly selected dungeons will have their keys replaced with keyrings.\n" "\n" - "Selection - Hand select which dungeons will have their keys replaced with keyrings.\n" + "Selection - Hand select which dungeons will have their keys replaced with keyrings\n" + "(can also be left as random, in which case each one will have a 50% chance of being a keyring).\n" "\n" "Selecting key ring for dungeons will have no effect if Small Keys are set to Start With or Vanilla.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 43fddacea..80d62859c 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -3876,6 +3876,12 @@ typedef enum { RO_KEYRINGS_SELECTION, } RandoOptionKeyrings; +typedef enum { + RO_KEYRING_FOR_DUNGEON_OFF, + RO_KEYRING_FOR_DUNGEON_RANDOM, + RO_KEYRING_FOR_DUNGEON_ON, +} RandoOptionKeyringForDungeon; + //Ganon's Boss Key Settings (vanilla, own dungeon, start with, //overworld, anywhere, 100 GS reward) typedef enum { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 0d702e480..883a7c208 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -136,15 +136,15 @@ void Settings::CreateOptions() { mOptions[RSK_LACS_OPTIONS] = Option::U8("LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD); mOptions[RSK_KEYRINGS] = Option::U8("Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF); mOptions[RSK_KEYRINGS_RANDOM_COUNT] = Option::U8("Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8); - mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::Bool("Gerudo Fortress", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::Bool("Forest Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::Bool("Fire Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::Bool("Water Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::Bool("Spirit Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::Bool("Shadow Temple", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::Bool("Bottom of the Well", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_GTG] = Option::Bool("Gerudo Training Grounds", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", IMFLAG_NONE); - mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle")); + mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::U8("Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::U8("Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::U8("Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::U8("Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::U8("Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_GTG] = Option::U8("Gerudo Training Grounds Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::TristateCheckbox, 0); + mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::U8("Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::TristateCheckbox, 0); mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); @@ -1145,15 +1145,15 @@ void Settings::CreateOptions() { { "Shuffle Dungeon Items:LACS Reward Options", RSK_LACS_OPTIONS }, { "Shuffle Dungeon Items:Key Rings", RSK_KEYRINGS }, { "Shuffle Dungeon Items:Keyring Dungeon Count", RSK_KEYRINGS_RANDOM_COUNT }, - { "Shuffle Dungeon Items:Gerudo Fortress", RSK_KEYRINGS_GERUDO_FORTRESS }, - { "Shuffle Dungeon Items:Forest Temple", RSK_KEYRINGS_FOREST_TEMPLE }, - { "Shuffle Dungeon Items:Fire Temple", RSK_KEYRINGS_FIRE_TEMPLE }, - { "Shuffle Dungeon Items:Water Temple", RSK_KEYRINGS_WATER_TEMPLE }, - { "Shuffle Dungeon Items:Spirit Temple", RSK_KEYRINGS_SPIRIT_TEMPLE }, - { "Shuffle Dungeon Items:Shadow Temple", RSK_KEYRINGS_SHADOW_TEMPLE }, - { "Shuffle Dungeon Items:Bottom of the Well", RSK_KEYRINGS_BOTTOM_OF_THE_WELL }, - { "Shuffle Dungeon Items:GTG", RSK_KEYRINGS_GTG }, - { "Shuffle Dungeon Items:Ganon's Castle", RSK_KEYRINGS_GANONS_CASTLE }, + { "Shuffle Dungeon Items:Gerudo Fortress Keyring", RSK_KEYRINGS_GERUDO_FORTRESS }, + { "Shuffle Dungeon Items:Forest Temple Keyring", RSK_KEYRINGS_FOREST_TEMPLE }, + { "Shuffle Dungeon Items:Fire Temple Keyring", RSK_KEYRINGS_FIRE_TEMPLE }, + { "Shuffle Dungeon Items:Water Temple Keyring", RSK_KEYRINGS_WATER_TEMPLE }, + { "Shuffle Dungeon Items:Spirit Temple Keyring", RSK_KEYRINGS_SPIRIT_TEMPLE }, + { "Shuffle Dungeon Items:Shadow Temple Keyring", RSK_KEYRINGS_SHADOW_TEMPLE }, + { "Shuffle Dungeon Items:Bottom of the Well Keyring", RSK_KEYRINGS_BOTTOM_OF_THE_WELL }, + { "Shuffle Dungeon Items:GTG Keyring", RSK_KEYRINGS_GTG }, + { "Shuffle Dungeon Items:Ganon's Castle Keyring", RSK_KEYRINGS_GANONS_CASTLE }, { "World Settings:Starting Age", RSK_STARTING_AGE }, // TODO: Ammo Drop settings { "World Settings:Bombchu Drops", RSK_ENABLE_BOMBCHU_DROPS }, @@ -1952,39 +1952,44 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio if (mOptions[RSK_KEYRINGS]) { // Random Key Rings + auto keyrings = keyRingOptions; + if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_NORMAL) && mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) { + keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]); + } else { + mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); + } if (mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_RANDOM) || mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT)) { - auto keyrings = keyRingOptions; - if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_NORMAL) && mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) { - keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]); - } const uint32_t keyRingCount = mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT) ? mOptions[RSK_KEYRINGS_RANDOM_COUNT].Value() : Random(0, static_cast(keyrings.size())); Shuffle(keyrings); for (size_t i = 0; i < keyRingCount; i++) { - keyrings[i]->SetSelectedIndex(RO_GENERIC_ON); + keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON); + } + for (size_t i = keyRingCount; i < keyrings.size(); i++) { + keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); } } - if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL]) { + if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(BOTTOM_OF_THE_WELL)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_FOREST_TEMPLE]) { + if (mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(FOREST_TEMPLE)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_FIRE_TEMPLE]) { + if (mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(FIRE_TEMPLE)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_WATER_TEMPLE]) { + if (mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(WATER_TEMPLE)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE]) { + if (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(SPIRIT_TEMPLE)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE]) { + if (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(SHADOW_TEMPLE)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_GTG]) { + if (mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(GERUDO_TRAINING_GROUNDS)->SetKeyRing(); } - if (mOptions[RSK_KEYRINGS_GANONS_CASTLE]) { + if (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { ctx->GetDungeon(GANONS_CASTLE)->SetKeyRing(); } } @@ -2322,15 +2327,6 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_HBA_HINT: case RSK_WARP_SONG_HINTS: case RSK_SCRUB_TEXT_HINT: - case RSK_KEYRINGS_GERUDO_FORTRESS: - case RSK_KEYRINGS_FOREST_TEMPLE: - case RSK_KEYRINGS_FIRE_TEMPLE: - case RSK_KEYRINGS_WATER_TEMPLE: - case RSK_KEYRINGS_SHADOW_TEMPLE: - case RSK_KEYRINGS_SPIRIT_TEMPLE: - case RSK_KEYRINGS_BOTTOM_OF_THE_WELL: - case RSK_KEYRINGS_GTG: - case RSK_KEYRINGS_GANONS_CASTLE: case RSK_SHUFFLE_ENTRANCES: case RSK_SHUFFLE_OVERWORLD_ENTRANCES: case RSK_SHUFFLE_GROTTO_ENTRANCES: @@ -2365,6 +2361,23 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { mOptions[index].SetSelectedIndex(RO_KEYRINGS_SELECTION); } break; + case RSK_KEYRINGS_GERUDO_FORTRESS: + case RSK_KEYRINGS_FOREST_TEMPLE: + case RSK_KEYRINGS_FIRE_TEMPLE: + case RSK_KEYRINGS_WATER_TEMPLE: + case RSK_KEYRINGS_SHADOW_TEMPLE: + case RSK_KEYRINGS_SPIRIT_TEMPLE: + case RSK_KEYRINGS_BOTTOM_OF_THE_WELL: + case RSK_KEYRINGS_GTG: + case RSK_KEYRINGS_GANONS_CASTLE: + if (it.value() == "No") { + mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); + } else if (it.value() == "Random") { + mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_RANDOM); + } else if (it.value() == "Yes") { + mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON); + } + break; case RSK_SHUFFLE_MERCHANTS: if (it.value() == "Off") { mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_OFF); diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index d1bf0967a..5ceaa0012 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -127,7 +127,7 @@ namespace UIWidgets { draw_list->PathStroke(col, 0, thickness); } - bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) { + bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic, bool renderCrossWhenOff) { ImGuiWindow* window = ImGui::GetCurrentWindow(); if (window->SkipItems) { return false; @@ -168,9 +168,9 @@ namespace UIWidgets { } else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) { const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); - } else if (disabled && disabledGraphic == CheckboxGraphics::Cross) { + } else if ((!disabled && !*v && renderCrossWhenOff) || (disabled && disabledGraphic == CheckboxGraphics::Cross)) { const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f); + RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), disabled ? cross_col : check_col, square_sz - pad * 2.0f); } ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); @@ -185,6 +185,36 @@ namespace UIWidgets { return pressed; } + bool CustomCheckboxTristate(const char* label, int* v, bool disabled, CheckboxGraphics disabledGraphic) { + bool ret; + if (*v == 0) { + bool b = false; + ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true); + if (ret) { + *v = 1; + } + } else if (*v == 1) { + ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true); + bool b = true; + ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true); + if (ret) { + *v = 2; + } + ImGui::PopItemFlag(); + } else if (*v == 2) { + bool b = true; + ret = CustomCheckbox(label, &b, disabled, disabledGraphic, true); + if (ret) { + *v = 0; + } + } else { + SPDLOG_INFO("Invalid CheckBoxTristate value: {}", *v); + *v = 0; + return false; + } + return ret; + } + void ReEnableComponent(const char* disabledTooltipText) { // End of disable region of previous component ImGui::PopStyleVar(1); @@ -218,6 +248,25 @@ namespace UIWidgets { return changed; } + bool EnhancementCheckboxTristate(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) { + bool changed = false; + if (disabled) { + DisableComponent(ImGui::GetStyle().Alpha * 0.5f); + } + + int val = CVarGetInteger(cvarName, defaultValue); + if (CustomCheckboxTristate(text, &val, disabled, disabledGraphic)) { + CVarSetInteger(cvarName, val); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + changed = true; + } + + if (disabled) { + ReEnableComponent(disabledTooltipText); + } + return changed; + } + bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic, bool defaultValue) { ImGui::BeginGroup(); if (padTop) Spacer(0); diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 70580340c..809c4dd2d 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -68,12 +68,14 @@ namespace UIWidgets { void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); - bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic); + bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic, bool renderCrossWhenOff = false); + bool CustomCheckboxTristate(const char* label, int* v, bool disabled, CheckboxGraphics disabledGraphic); void ReEnableComponent(const char* disabledTooltipText); void DisableComponent(const float alpha); bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false); + bool EnhancementCheckboxTristate(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false); bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross, bool defaultValue = false); bool EnhancementCombobox(const char* cvarName, std::span comboArray, uint8_t defaultIndex, bool disabled = false, const char* disabledTooltipText = "", uint8_t disabledValue = -1); From f2958aea1ccf8419e0fd8b77324e77739c8c0da3 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Wed, 17 Jul 2024 05:25:28 +0200 Subject: [PATCH 273/300] Improved rando settings (#3980) * Initial implementation * center icons (#5) --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --- .../randomizer_entrance_tracker.cpp | 166 +++++++++--------- .../randomizer/randomizer_entrance_tracker.h | 10 ++ soh/soh/SohGui.cpp | 6 +- soh/soh/SohMenuBar.cpp | 55 +++++- 4 files changed, 146 insertions(+), 91 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp index af484449d..851bdf2d2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp @@ -639,6 +639,89 @@ void InitEntranceTrackingData() { SortEntranceListByType(destListSortedByType, 1); } +void EntranceTrackerSettingsWindow::DrawElement() { + ImGui::SetNextWindowSize(ImVec2(600, 375), ImGuiCond_FirstUseEver); + + if (!ImGui::Begin("Entrance Tracker Settings", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) { + ImGui::End(); + return; + } + + if (ImGui::BeginTable("entranceTrackerSettings", 1, ImGuiTableFlags_BordersInnerH)) { + + ImGui::TableNextColumn(); + + UIWidgets::Spacer(0); + ImGui::TextWrapped("The entrance tracker will only track shuffled entrances"); + UIWidgets::Spacer(0); + + ImGui::TableNextColumn(); + + if (ImGui::BeginTable("entranceTrackerSubSettings", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp)) { + + ImGui::TableNextColumn(); + + ImGui::Text("Sort By"); + UIWidgets::EnhancementRadioButton("To", CVAR_TRACKER_ENTRANCE("SortBy"), 0); + UIWidgets::Tooltip("Sort entrances by the original source entrance"); + UIWidgets::EnhancementRadioButton("From", CVAR_TRACKER_ENTRANCE("SortBy"), 1); + UIWidgets::Tooltip("Sort entrances by the overrided destination"); + + UIWidgets::Spacer(2.0f); + + ImGui::Text("List Items"); + UIWidgets::PaddedEnhancementCheckbox("Auto scroll", CVAR_TRACKER_ENTRANCE("AutoScroll"), true, false); + UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene"); + UIWidgets::PaddedEnhancementCheckbox("Highlight previous", CVAR_TRACKER_ENTRANCE("HighlightPrevious"), true, false); + UIWidgets::Tooltip("Highlight the previous entrance that Link came from"); + UIWidgets::PaddedEnhancementCheckbox("Highlight available", CVAR_TRACKER_ENTRANCE("HighlightAvailable"), true, false); + UIWidgets::Tooltip("Highlight available entrances in the current scene"); + UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), true, false); + UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group"); + bool disableHideReverseEntrances = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_ON; + static const char* disableHideReverseEntrancesText = "This option is disabled because \"Decouple Entrances\" is enabled."; + UIWidgets::PaddedEnhancementCheckbox("Hide reverse", CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), true, false, + disableHideReverseEntrances, disableHideReverseEntrancesText, UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::Tooltip("Hide reverse entrance transitions when Decouple Entrances is off"); + UIWidgets::Spacer(0); + + ImGui::TableNextColumn(); + + ImGui::Text("Group By"); + UIWidgets::EnhancementRadioButton("Area", CVAR_TRACKER_ENTRANCE("GroupBy"), 0); + UIWidgets::Tooltip("Group entrances by their area"); + UIWidgets::EnhancementRadioButton("Type", CVAR_TRACKER_ENTRANCE("GroupBy"), 1); + UIWidgets::Tooltip("Group entrances by their entrance type"); + + UIWidgets::Spacer(2.0f); + + ImGui::Text("Spoiler Reveal"); + UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", CVAR_TRACKER_ENTRANCE("ShowTo"), true, false); + UIWidgets::Tooltip("Reveal the \"To\" entrance for undiscovered entrances"); + UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", CVAR_TRACKER_ENTRANCE("ShowFrom"), true, false); + UIWidgets::Tooltip("Reveal the \"From\" entrance for undiscovered entrances"); + + ImGui::EndTable(); + } + + ImGui::TableNextColumn(); + + ImGui::SetNextItemOpen(false, ImGuiCond_Once); + if (ImGui::TreeNode("Legend")) { + ImGui::TextColored(ImColor(COLOR_ORANGE), "Last Entrance"); + ImGui::TextColored(ImColor(COLOR_GREEN), "Available Entrances"); + ImGui::TextColored(ImColor(COLOR_GRAY), "Undiscovered Entrances"); + ImGui::TreePop(); + } + + UIWidgets::Spacer(0); + + ImGui::EndTable(); + } + + ImGui::End(); +} + void EntranceTrackerWindow::DrawElement() { ImGui::SetNextWindowSize(ImVec2(600, 375), ImGuiCond_FirstUseEver); @@ -647,89 +730,6 @@ void EntranceTrackerWindow::DrawElement() { return; } - // Begin tracker settings - ImGui::SetNextItemOpen(false, ImGuiCond_Once); - if (ImGui::TreeNode("Tracker Settings")) { - // Reduce indentation from the tree node for the table - ImGui::SetCursorPosX((ImGui::GetCursorPosX() / 2) + 4.0f); - - if (ImGui::BeginTable("entranceTrackerSettings", 1, ImGuiTableFlags_BordersInnerH)) { - - ImGui::TableNextColumn(); - - UIWidgets::Spacer(0); - ImGui::TextWrapped("The entrance tracker will only track shuffled entrances"); - UIWidgets::Spacer(0); - - ImGui::TableNextColumn(); - - if (ImGui::BeginTable("entranceTrackerSubSettings", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp)) { - - ImGui::TableNextColumn(); - - ImGui::Text("Sort By"); - UIWidgets::EnhancementRadioButton("To", CVAR_TRACKER_ENTRANCE("SortBy"), 0); - UIWidgets::Tooltip("Sort entrances by the original source entrance"); - UIWidgets::EnhancementRadioButton("From", CVAR_TRACKER_ENTRANCE("SortBy"), 1); - UIWidgets::Tooltip("Sort entrances by the overrided destination"); - - UIWidgets::Spacer(2.0f); - - ImGui::Text("List Items"); - UIWidgets::PaddedEnhancementCheckbox("Auto scroll", CVAR_TRACKER_ENTRANCE("AutoScroll"), true, false); - UIWidgets::Tooltip("Automatically scroll to the first aviable entrance in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Highlight previous", CVAR_TRACKER_ENTRANCE("HighlightPrevious"), true, false); - UIWidgets::Tooltip("Highlight the previous entrance that Link came from"); - UIWidgets::PaddedEnhancementCheckbox("Highlight available", CVAR_TRACKER_ENTRANCE("HighlightAvailable"), true, false); - UIWidgets::Tooltip("Highlight available entrances in the current scene"); - UIWidgets::PaddedEnhancementCheckbox("Hide undiscovered", CVAR_TRACKER_ENTRANCE("CollapseUndiscovered"), true, false); - UIWidgets::Tooltip("Collapse undiscovered entrances towards the bottom of each group"); - bool disableHideReverseEntrances = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_DECOUPLED_ENTRANCES) == RO_GENERIC_ON; - static const char* disableHideReverseEntrancesText = "This option is disabled because \"Decouple Entrances\" is enabled."; - UIWidgets::PaddedEnhancementCheckbox("Hide reverse", CVAR_TRACKER_ENTRANCE("HideReverseEntrances"), true, false, - disableHideReverseEntrances, disableHideReverseEntrancesText, UIWidgets::CheckboxGraphics::Cross, true); - UIWidgets::Tooltip("Hide reverse entrance transitions when Decouple Entrances is off"); - UIWidgets::Spacer(0); - - ImGui::TableNextColumn(); - - ImGui::Text("Group By"); - UIWidgets::EnhancementRadioButton("Area", CVAR_TRACKER_ENTRANCE("GroupBy"), 0); - UIWidgets::Tooltip("Group entrances by their area"); - UIWidgets::EnhancementRadioButton("Type", CVAR_TRACKER_ENTRANCE("GroupBy"), 1); - UIWidgets::Tooltip("Group entrances by their entrance type"); - - UIWidgets::Spacer(2.0f); - - ImGui::Text("Spoiler Reveal"); - UIWidgets::PaddedEnhancementCheckbox("Show \"To\"", CVAR_TRACKER_ENTRANCE("ShowTo"), true, false); - UIWidgets::Tooltip("Reveal the \"To\" entrance for undiscovered entrances"); - UIWidgets::PaddedEnhancementCheckbox("Show \"From\"", CVAR_TRACKER_ENTRANCE("ShowFrom"), true, false); - UIWidgets::Tooltip("Reveal the \"From\" entrance for undiscovered entrances"); - - ImGui::EndTable(); - } - - ImGui::TableNextColumn(); - - ImGui::SetNextItemOpen(false, ImGuiCond_Once); - if (ImGui::TreeNode("Legend")) { - ImGui::TextColored(ImColor(COLOR_ORANGE), "Last Entrance"); - ImGui::TextColored(ImColor(COLOR_GREEN), "Available Entrances"); - ImGui::TextColored(ImColor(COLOR_GRAY), "Undiscovered Entrances"); - ImGui::TreePop(); - } - - UIWidgets::Spacer(0); - - ImGui::EndTable(); - } - - ImGui::TreePop(); - } else { - UIWidgets::PaddedSeparator(); - } - static ImGuiTextFilter locationSearch; uint8_t nextTreeState = 0; diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h index 87d736058..22e27a250 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h @@ -85,6 +85,16 @@ s16 GetLastEntranceOverride(); s16 GetCurrentGrottoId(); const EntranceData* GetEntranceData(s16); +class EntranceTrackerSettingsWindow : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + protected: + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; +}; + class EntranceTrackerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 7fde4f351..696825ec8 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -129,6 +129,7 @@ namespace SohGui { std::shared_ptr mGameplayStatsWindow; std::shared_ptr mCheckTrackerSettingsWindow; std::shared_ptr mCheckTrackerWindow; + std::shared_ptr mEntranceTrackerSettingsWindow; std::shared_ptr mEntranceTrackerWindow; std::shared_ptr mItemTrackerSettingsWindow; std::shared_ptr mItemTrackerWindow; @@ -191,8 +192,10 @@ namespace SohGui { gui->AddGuiWindow(mCheckTrackerWindow); mCheckTrackerSettingsWindow = std::make_shared(CVAR_WINDOW("CheckTrackerSettings"), "Check Tracker Settings"); gui->AddGuiWindow(mCheckTrackerSettingsWindow); - mEntranceTrackerWindow = std::make_shared(CVAR_WINDOW("EntranceTracker"),"Entrance Tracker"); + mEntranceTrackerWindow = std::make_shared(CVAR_WINDOW("EntranceTracker"), "Entrance Tracker"); gui->AddGuiWindow(mEntranceTrackerWindow); + mEntranceTrackerSettingsWindow = std::make_shared(CVAR_WINDOW("EntranceTrackerSettings"), "Entrance Tracker Settings"); + gui->AddGuiWindow(mEntranceTrackerSettingsWindow); mItemTrackerWindow = std::make_shared(CVAR_WINDOW("ItemTracker"), "Item Tracker"); gui->AddGuiWindow(mItemTrackerWindow); mItemTrackerSettingsWindow = std::make_shared(CVAR_WINDOW("ItemTrackerSettings"), "Item Tracker Settings"); @@ -213,6 +216,7 @@ namespace SohGui { mItemTrackerWindow = nullptr; mItemTrackerSettingsWindow = nullptr; mEntranceTrackerWindow = nullptr; + mEntranceTrackerSettingsWindow = nullptr; mCheckTrackerWindow = nullptr; mCheckTrackerSettingsWindow = nullptr; mGameplayStatsWindow = nullptr; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 28e43c483..587e2d0c1 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -38,6 +38,10 @@ #include "Enhancements/randomizer/randomizer_settings_window.h" #include "Enhancements/resolution-editor/ResolutionEditor.h" +// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but +// they don't work how I expect them to so I added that because it looked good when I eyeballed it +#define FA_ICON_BUTTON_FRAME_PADDING_X(icon) (((optionsButtonSize.x - ImGui::CalcTextSize(icon).x) / 2) + 2.0f) + extern bool ToggleAltAssetsAtEndOfFrame; extern bool isBetaQuestEnabled; @@ -1963,6 +1967,7 @@ extern std::shared_ptr mRandomizerSettingsWindow; extern std::shared_ptr mItemTrackerWindow; extern std::shared_ptr mItemTrackerSettingsWindow; extern std::shared_ptr mEntranceTrackerWindow; +extern std::shared_ptr mEntranceTrackerSettingsWindow; extern std::shared_ptr mCheckTrackerWindow; extern std::shared_ptr mCheckTrackerSettingsWindow; extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); @@ -1981,11 +1986,19 @@ void DrawRandomizerMenu() { ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + #ifdef __WIIU__ static ImVec2 buttonSize(200.0f * 2.0f, 0.0f); + static ImVec2 buttonWithOptionsSize(170.0f * 2.0f, 0.0f); + static ImVec2 optionsButtonSize(25.0f * 2.0f, 0.0f); + static float separationToOptionsButton = 5.0f * 2.0f; #else static ImVec2 buttonSize(200.0f, 0.0f); + static ImVec2 buttonWithOptionsSize(170.0f, 0.0f); + static ImVec2 optionsButtonSize(25.0f, 0.0f); + static float separationToOptionsButton = 5.0f; #endif + if (mRandomizerSettingsWindow) { if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger(CVAR_WINDOW("RandomizerSettings"), 0)).c_str(), buttonSize)) { mRandomizerSettingsWindow->ToggleVisibility(); @@ -1993,36 +2006,64 @@ void DrawRandomizerMenu() { } UIWidgets::Spacer(0); + if (mItemTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger(CVAR_WINDOW("ItemTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Item Tracker", CVarGetInteger(CVAR_WINDOW("ItemTracker"), 0)).c_str(), buttonWithOptionsSize)) { mItemTrackerWindow->ToggleVisibility(); } } - UIWidgets::Spacer(0); + ImGui::SameLine(0, 0); + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + separationToOptionsButton, cursor.y)); + if (mItemTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVarGetInteger(CVAR_WINDOW("ItemTrackerSettings"), 0)).c_str(), buttonSize)) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(FA_ICON_BUTTON_FRAME_PADDING_X(ICON_FA_COG), 6.0f)); + if (ImGui::Button(ICON_FA_COG "##ItemTrackerSettings", optionsButtonSize)) { mItemTrackerSettingsWindow->ToggleVisibility(); } + ImGui::PopStyleVar(); } + UIWidgets::Spacer(0); if (mEntranceTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger(CVAR_WINDOW("EntranceTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Entrance Tracker", CVarGetInteger(CVAR_WINDOW("EntranceTracker"), 0)).c_str(), buttonWithOptionsSize)) { mEntranceTrackerWindow->ToggleVisibility(); } } + + ImGui::SameLine(0, 0); + cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + separationToOptionsButton, cursor.y)); + + if (mEntranceTrackerSettingsWindow) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(FA_ICON_BUTTON_FRAME_PADDING_X(ICON_FA_COG), 6.0f)); + if (ImGui::Button(ICON_FA_COG "##EntranceTrackerSettings", optionsButtonSize)) { + mEntranceTrackerSettingsWindow->ToggleVisibility(); + } + ImGui::PopStyleVar(); + } + UIWidgets::Spacer(0); + if (mCheckTrackerWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger(CVAR_WINDOW("CheckTracker"), 0)).c_str(), buttonSize)) { + if (ImGui::Button(GetWindowButtonText("Check Tracker", CVarGetInteger(CVAR_WINDOW("CheckTracker"), 0)).c_str(), buttonWithOptionsSize)) { mCheckTrackerWindow->ToggleVisibility(); } } - UIWidgets::Spacer(0); + + ImGui::SameLine(0, 0); + cursor = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursor.x + separationToOptionsButton, cursor.y)); + if (mCheckTrackerSettingsWindow) { - if (ImGui::Button(GetWindowButtonText("Check Tracker Settings", CVarGetInteger(CVAR_WINDOW("CheckTrackerSettings"), 0)).c_str(), buttonSize)) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(FA_ICON_BUTTON_FRAME_PADDING_X(ICON_FA_COG), 6.0f)); + if (ImGui::Button(ICON_FA_COG "##CheckTrackerSettings", optionsButtonSize)) { mCheckTrackerSettingsWindow->ToggleVisibility(); } + ImGui::PopStyleVar(); } + ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); From a5c0cede12d3a53cb0f1069a5d4a5c4febe991fa Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:42:56 +0200 Subject: [PATCH 274/300] Rando: Shuffle consumable bags (#3959) * Main implementation * Fix sticks & nuts from shops & checks * Change the models to normal stick & nut Worth noting that before you have the bags, the refills are blue rupees so there will not be model collision * Update hook_handlers.cpp --- .../randomizer/3drando/item_pool.cpp | 7 ++++ .../Enhancements/randomizer/hook_handlers.cpp | 19 +++++++++++ soh/soh/Enhancements/randomizer/item.cpp | 8 +++++ soh/soh/Enhancements/randomizer/item_list.cpp | 16 +++++---- soh/soh/Enhancements/randomizer/logic.cpp | 6 ++-- soh/soh/Enhancements/randomizer/logic.h | 2 ++ .../randomizer/option_descriptions.cpp | 6 ++++ .../Enhancements/randomizer/randomizer.cpp | 18 ++++++---- .../Enhancements/randomizer/randomizerTypes.h | 4 +++ soh/soh/Enhancements/randomizer/savefile.cpp | 8 +++-- soh/soh/Enhancements/randomizer/settings.cpp | 8 +++++ soh/src/code/z_parameter.c | 34 +++++++++++++++++++ .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 8 +++++ 13 files changed, 127 insertions(+), 17 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 9c1459cef..caf7c811e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -977,6 +977,13 @@ void GenerateItemPool() { AddItemToMainPool(RG_PROGRESSIVE_WALLET); } + if (ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG)) { + AddItemToMainPool(RG_PROGRESSIVE_STICK_UPGRADE); + } + + if (ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG)) { + AddItemToMainPool(RG_PROGRESSIVE_NUT_UPGRADE); + } if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 303b8af42..2f314fc76 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1443,6 +1443,25 @@ void RandomizerOnActorInitHandler(void* actorRef) { Actor_Kill(actor); } } + + //consumable bags + if ( + actor->id = ACTOR_EN_ITEM00 && + ( + ( + RAND_GET_OPTION(RSK_SHUFFLE_DEKU_STICK_BAG) && + CUR_UPG_VALUE(UPG_STICKS) == 0 && + actor->params == ITEM00_STICK + ) || + ( + RAND_GET_OPTION(RSK_SHUFFLE_DEKU_NUT_BAG) && + CUR_UPG_VALUE(UPG_NUTS) == 0 && + actor->params == ITEM00_NUTS + ) + ) + ) { + Actor_Kill(actor); + } } void RandomizerRegisterHooks() { diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 16396c072..9be5551b8 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -123,6 +123,10 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio case RG_PROGRESSIVE_STICK_UPGRADE: switch (CUR_UPG_VALUE(UPG_STICKS)) { case 0: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { + actual = RG_DEKU_STICK_BAG; + break; + } case 1: actual = RG_DEKU_STICK_CAPACITY_20; break; @@ -137,6 +141,10 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio case RG_PROGRESSIVE_NUT_UPGRADE: switch (CUR_UPG_VALUE(UPG_NUTS)) { case 0: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { + actual = RG_DEKU_NUT_BAG; + break; + } case 1: actual = RG_DEKU_NUT_CAPACITY_30; break; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 2b6c42d34..3bdd2709f 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -64,8 +64,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, &logic->ProgressiveBulletBag,RHT_PROGRESSIVE_SLINGSHOT, true); itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Brieftasche" }, ITEMTYPE_ITEM, 0x85, true, &logic->ProgressiveWallet, RHT_PROGRESSIVE_WALLET, true); itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Skala" }, ITEMTYPE_ITEM, 0x86, true, &logic->ProgressiveScale, RHT_PROGRESSIVE_SCALE, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, false, &logic->noVariable, RHT_PROGRESSIVE_NUT_UPGRADE, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, false, &logic->noVariable, RHT_PROGRESSIVE_STICK_UPGRADE, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, true, &logic->ProgressiveNutBag, RHT_PROGRESSIVE_NUT_UPGRADE, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, &logic->ProgressiveStickBag, RHT_PROGRESSIVE_STICK_UPGRADE, true); itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Kriechgrube" }, ITEMTYPE_ITEM, 0x89, true, &logic->Bombchus, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true); itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_PROGRESSIVE_MAGIC_METER, true); itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, &logic->ProgressiveOcarina, RHT_PROGRESSIVE_OCARINA, true); @@ -289,6 +289,10 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveWallet, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, &logic->ProgressiveStickBag, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + + itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, &logic->ProgressiveNutBag, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, &logic->noVariable, RHT_NONE); itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, &logic->noVariable, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) @@ -314,10 +318,10 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, &logic->ProgressiveWallet, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Reiche Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, &logic->ProgressiveWallet, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Bourse de Magnat", "Reiche Geldbörse" },/*FIXME: still says tycoon in french & german*/ ITEMTYPE_ITEM, RG_CHILD_WALLET, true, &logic->ProgressiveWallet, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, false, &logic->noVariable, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, false, &logic->noVariable, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20,false, &logic->noVariable, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30,false, &logic->noVariable, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, &logic->ProgressiveNutBag, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, &logic->ProgressiveNutBag, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20,true, &logic->ProgressiveStickBag, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30,true, &logic->ProgressiveStickBag, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, &logic->TriforcePieces, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 56ed191c0..b1fa969d0 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -297,8 +297,8 @@ namespace Rando { //refills Bombs = BombBag; - Nuts = DekuNutDrop || Nuts; - Sticks = DekuStickDrop || Sticks; + Nuts = (ProgressiveNutBag != 0 && DekuNutDrop) || Nuts; + Sticks = (ProgressiveStickBag != 0 && DekuStickDrop) || Sticks; Bugs = HasBottle && BugsAccess; BlueFire = (HasBottle && BlueFireAccess) || (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && CanUse(RG_ICE_ARROWS)); Fish = HasBottle && FishAccess; @@ -626,6 +626,8 @@ namespace Rando { OcarinaCDownButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; //Progressive Items + ProgressiveStickBag = ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Is(true) ? 0 : 1; + ProgressiveNutBag = ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Is(true) ? 0 : 1; ProgressiveBulletBag = 0; ProgressiveBombBag = 0; ProgressiveMagic = 0; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 5475d4d92..16213049d 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -140,6 +140,8 @@ class Logic { bool GregInLacsLogic = false; // Progressive Items + uint8_t ProgressiveStickBag = 0; + uint8_t ProgressiveNutBag = 0; uint8_t ProgressiveBulletBag = 0; uint8_t ProgressiveBombBag = 0; uint8_t ProgressiveMagic = 0; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 784d9d1f3..3e91715c4 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -249,6 +249,12 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; + mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG] = "Shuffles the deku stick bag into the item pool.\n" + "\n" + "The deku stick bag is required to hold deku sticks."; + mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG] = "Shuffles the deku nut bag into the item pool.\n" + "\n" + "The deku nut bag is required to hold deku nuts."; mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n" "\n" "0 Items - Vanilla shop items will be shuffled among different shops.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index e75e03ee6..303a6bbfd 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -397,8 +397,16 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe // Inventory Items case RG_PROGRESSIVE_STICK_UPGRADE: return CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DEKU_STICK_1: + case RG_BUY_DEKU_STICK_1: + return CUR_UPG_VALUE(UPG_STICKS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_NUT_UPGRADE: return CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DEKU_NUTS_5: + case RG_DEKU_NUTS_10: + case RG_BUY_DEKU_NUTS_5: + case RG_BUY_DEKU_NUTS_10: + return CUR_UPG_VALUE(UPG_NUTS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_BOMB_BAG: return CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_BOMBS_5: @@ -694,14 +702,8 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_PIECE_OF_HEART: case RG_HEART_CONTAINER: case RG_ICE_TRAP: - case RG_DEKU_NUTS_5: - case RG_DEKU_NUTS_10: - case RG_DEKU_STICK_1: case RG_TREASURE_GAME_HEART: case RG_TREASURE_GAME_GREEN_RUPEE: - case RG_BUY_DEKU_NUTS_5: - case RG_BUY_DEKU_NUTS_10: - case RG_BUY_DEKU_STICK_1: case RG_BUY_HEART: case RG_TRIFORCE_PIECE: default: @@ -2952,7 +2954,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ + const std::array getItemMessages = {{ GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", @@ -3224,6 +3226,8 @@ void Randomizer::CreateCustomMessages() { "Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), GIMESSAGE_UNTRANSLATED(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!"), GIMESSAGE_UNTRANSLATED(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!"), + GIMESSAGE_UNTRANSLATED(RG_DEKU_STICK_BAG, ITEM_STICK, "You found the %rDeku Stick Bag%w!&You can now hold deku sticks!"), + GIMESSAGE_UNTRANSLATED(RG_DEKU_NUT_BAG, ITEM_NUT, "You found the %rDeku Nut Bag%w!&You can now hold deku nuts!"), }}; CreateGetItemMessages(&getItemMessages); CreateRupeeMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 80d62859c..d15d3d4a3 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1980,6 +1980,8 @@ typedef enum { RG_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, RG_FISHING_POLE, + RG_DEKU_STICK_BAG, + RG_DEKU_NUT_BAG, RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, @@ -3711,6 +3713,8 @@ typedef enum { RSK_FISHSANITY_POND_COUNT, RSK_FISHSANITY_AGE_SPLIT, RSK_SHUFFLE_FISHING_POLE, + RSK_SHUFFLE_DEKU_STICK_BAG, + RSK_SHUFFLE_DEKU_NUT_BAG, RSK_MAX } RandomizerSettingKey; diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 4900e4a70..8859e8d43 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -150,8 +150,12 @@ void SetStartingItems() { } if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) { - GiveLinkDekuSticks(10); - GiveLinkDekuNuts(20); + if (!Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { + GiveLinkDekuSticks(10); + } + if (!Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { + GiveLinkDekuNuts(20); + } } if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 883a7c208..745593ef5 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -120,6 +120,8 @@ void Settings::CreateOptions() { mOptions[RSK_SHUFFLE_CHEST_MINIGAME] = Option::U8("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}); mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox); + mOptions[RSK_SHUFFLE_DEKU_STICK_BAG] = Option::Bool("Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_SHUFFLE_DEKU_NUT_BAG] = Option::Bool("Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE); mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]); @@ -662,6 +664,8 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], &mOptions[RSK_SHUFFLE_FISHING_POLE], + &mOptions[RSK_SHUFFLE_DEKU_STICK_BAG], + &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = OptionGroup::SubGroup("Shuffle NPCs & Merchants", { &mOptions[RSK_SHOPSANITY], @@ -889,6 +893,8 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_CHEST_MINIGAME], &mOptions[RSK_SHUFFLE_100_GS_REWARD], &mOptions[RSK_SHUFFLE_BOSS_SOULS], + &mOptions[RSK_SHUFFLE_DEKU_STICK_BAG], + &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = OptionGroup("Shuffle Dungeon Items", { &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], @@ -1117,6 +1123,8 @@ void Settings::CreateOptions() { { "Shuffle Settings:Shuffle Merchants", RSK_SHUFFLE_MERCHANTS }, { "Shuffle Settings:Shuffle 100 GS Reward", RSK_SHUFFLE_100_GS_REWARD }, { "Shuffle Settings:Shuffle Boss Souls", RSK_SHUFFLE_BOSS_SOULS }, + { "Shuffle Settings:Shuffle Deku Stick Bag", RSK_SHUFFLE_DEKU_STICK_BAG }, + { "Shuffle Settings:Shuffle Deku Nut Bag", RSK_SHUFFLE_DEKU_NUT_BAG }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 658e96394..2f39ade8c 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1926,6 +1926,26 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) { * @return u8 */ u8 Item_Give(PlayState* play, u8 item) { + //prevents getting sticks without the bag in case something got missed + if ( + IS_RANDO && + (item == ITEM_STICK || item == ITEM_STICKS_5 || item == ITEM_STICKS_10) && + Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG) && + CUR_UPG_VALUE(UPG_STICKS) == 0 + ) { + return; + } + + //prevents getting nuts without the bag in case something got missed + if ( + IS_RANDO && + (item == ITEM_NUT || item == ITEM_NUTS_5 || item == ITEM_NUTS_10) && + Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG) && + CUR_UPG_VALUE(UPG_NUTS) == 0 + ) { + return; + } + lusprintf(__FILE__, __LINE__, 2, "Item Give - item: %#x", item); static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 }; s16 i; @@ -2776,6 +2796,20 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { return Return_Item_Entry(giEntry, RG_NONE); } + if (item == RG_DEKU_STICK_BAG) { + Inventory_ChangeUpgrade(UPG_STICKS, 1); + INV_CONTENT(ITEM_STICK) = ITEM_STICK; + AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_DEKU_NUT_BAG) { + Inventory_ChangeUpgrade(UPG_NUTS, 1); + INV_CONTENT(ITEM_NUT) = ITEM_NUT; + AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); + return Return_Item_Entry(giEntry, RG_NONE); + } + temp = gSaveContext.inventory.items[slot]; osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp); INV_CONTENT(item) = item; diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 0382735a3..b005cbf3f 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -487,6 +487,10 @@ s32 EnGirlA_CanBuy_Bombs(PlayState* play, EnGirlA* this) { } s32 EnGirlA_CanBuy_DekuNuts(PlayState* play, EnGirlA* this) { + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG) && CUR_CAPACITY(UPG_NUTS) == 0) { + return CANBUY_RESULT_CANT_GET_NOW; + } + if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) { return CANBUY_RESULT_CANT_GET_NOW; } @@ -500,6 +504,10 @@ s32 EnGirlA_CanBuy_DekuNuts(PlayState* play, EnGirlA* this) { } s32 EnGirlA_CanBuy_DekuSticks(PlayState* play, EnGirlA* this) { + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG) && CUR_CAPACITY(UPG_STICKS) == 0) { + return CANBUY_RESULT_CANT_GET_NOW; + } + if ((CUR_CAPACITY(UPG_STICKS) != 0) && (AMMO(ITEM_STICK) >= CUR_CAPACITY(UPG_STICKS))) { return CANBUY_RESULT_CANT_GET_NOW; } From 7595a5a65e86ad6a61d7bd642f5907f624a7d725 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:45:29 +0100 Subject: [PATCH 275/300] fix selection only and make MQ dungeon settings set themselves more smartley (#4232) --- .../randomizer/3drando/random.hpp | 1 + soh/soh/Enhancements/randomizer/dungeon.cpp | 34 ++-- soh/soh/Enhancements/randomizer/dungeon.h | 7 +- .../randomizer/option_descriptions.cpp | 3 +- .../randomizer/randomizer_check_objects.cpp | 10 +- soh/soh/Enhancements/randomizer/settings.cpp | 179 +++++++++++------- 6 files changed, 149 insertions(+), 85 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/random.hpp b/soh/soh/Enhancements/randomizer/3drando/random.hpp index c8ccf0f50..623c396a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/random.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/random.hpp @@ -30,6 +30,7 @@ const auto& RandomElement(const Container& container) { } //Shuffle items within a vector or array +//RANDOTODO There's probably a more efficient way to do what this does. template void Shuffle(std::vector& vector) { for (std::size_t i = 0; i + 1 < vector.size(); i++) diff --git a/soh/soh/Enhancements/randomizer/dungeon.cpp b/soh/soh/Enhancements/randomizer/dungeon.cpp index 8453c938b..0f799b036 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/dungeon.cpp @@ -8,10 +8,12 @@ namespace Rando { DungeonInfo::DungeonInfo(std::string name_, const RandomizerHintTextKey hintKey_, const RandomizerGet map_, const RandomizerGet compass_, const RandomizerGet smallKey_, const RandomizerGet keyRing_, const RandomizerGet bossKey_, RandomizerArea area_, const uint8_t vanillaKeyCount_, const uint8_t mqKeyCount_, + const RandomizerSettingKey mqSetting_, std::vector vanillaLocations_, std::vector mqLocations_, std::vector sharedLocations_, std::vector bossRoomLocations_) : name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_), bossKey(bossKey_), area(area_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_), + mqSetting(mqSetting_), vanillaLocations(std::move(vanillaLocations_)), mqLocations(std::move(mqLocations_)), sharedLocations(std::move(sharedLocations_)), bossRoomLocations(std::move(bossRoomLocations_)) { } @@ -83,6 +85,14 @@ RandomizerGet DungeonInfo::GetBossKey() const { return bossKey; } +RandomizerSettingKey DungeonInfo::GetMQSetting() const { + return mqSetting; +} + +void DungeonInfo::SetDungeonKnown(bool known) { + isDungeonModeKnown = known; +} + void DungeonInfo::PlaceVanillaMap() const { if (map == RG_NONE) { return; @@ -152,7 +162,7 @@ std::vector DungeonInfo::GetEveryLocation() const { Dungeons::Dungeons() { dungeonList[DEKU_TREE] = - DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DEKU_TREE, 0, 0, + DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DEKU_TREE, 0, 0, RSK_MQ_DEKU_TREE, { // Vanilla Locations RC_DEKU_TREE_MAP_CHEST, @@ -188,7 +198,7 @@ Dungeons::Dungeons() { RC_QUEEN_GOHMA, }); dungeonList[DODONGOS_CAVERN] = DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP, - RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DODONGOS_CAVERN, 0, 0, + RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_DODONGOS_CAVERN, 0, 0, RSK_MQ_DODONGOS_CAVERN, { // Vanilla Locations RC_DODONGOS_CAVERN_MAP_CHEST, @@ -232,7 +242,7 @@ Dungeons::Dungeons() { RC_KING_DODONGO, }); dungeonList[JABU_JABUS_BELLY] = DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP, - RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_JABU_JABUS_BELLY, 0, 0, + RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, RA_JABU_JABUS_BELLY, 0, 0, RSK_MQ_JABU_JABU, { // Vanilla Locations RC_JABU_JABUS_BELLY_MAP_CHEST, @@ -271,7 +281,7 @@ Dungeons::Dungeons() { }); dungeonList[FOREST_TEMPLE] = DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS, - RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, RA_FOREST_TEMPLE, 5, 6, + RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, RA_FOREST_TEMPLE, 5, 6, RSK_MQ_FOREST_TEMPLE, { // Vanilla Locations RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, @@ -321,7 +331,7 @@ Dungeons::Dungeons() { }); dungeonList[FIRE_TEMPLE] = DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS, - RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, RA_FIRE_TEMPLE, 8, 5, + RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, RA_FIRE_TEMPLE, 8, 5, RSK_MQ_FIRE_TEMPLE, { // Vanilla Locations RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, @@ -372,7 +382,7 @@ Dungeons::Dungeons() { }); dungeonList[WATER_TEMPLE] = DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS, - RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, RA_WATER_TEMPLE, 6, 2, + RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, RA_WATER_TEMPLE, 6, 2, RSK_MQ_WATER_TEMPLE, { // Vanilla Locations RC_WATER_TEMPLE_MAP_CHEST, @@ -413,7 +423,7 @@ Dungeons::Dungeons() { }); dungeonList[SPIRIT_TEMPLE] = DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS, - RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, RA_SPIRIT_TEMPLE, 5, 7, + RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, RA_SPIRIT_TEMPLE, 5, 7, RSK_MQ_SPIRIT_TEMPLE, { // Vanilla Locations RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, @@ -479,7 +489,7 @@ Dungeons::Dungeons() { }); dungeonList[SHADOW_TEMPLE] = DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS, - RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, RA_SHADOW_TEMPLE, 5, 6, + RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, RA_SHADOW_TEMPLE, 5, 6, RSK_MQ_SHADOW_TEMPLE, { // Vanilla Locations RC_SHADOW_TEMPLE_MAP_CHEST, @@ -541,7 +551,7 @@ Dungeons::Dungeons() { }); dungeonList[BOTTOM_OF_THE_WELL] = DungeonInfo( "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_COMPASS, - RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, RA_BOTTOM_OF_THE_WELL, 3, 2, + RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, RA_BOTTOM_OF_THE_WELL, 3, 2, RSK_MQ_BOTTOM_OF_THE_WELL, { // Vanilla Locations RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, @@ -575,7 +585,7 @@ Dungeons::Dungeons() { }, {}, {}); dungeonList[ICE_CAVERN] = DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS, - RG_NONE, RG_NONE, RG_NONE, RA_ICE_CAVERN, 0, 0, + RG_NONE, RG_NONE, RG_NONE, RA_ICE_CAVERN, 0, 0, RSK_MQ_ICE_CAVERN, { // Vanilla Locations RC_ICE_CAVERN_MAP_CHEST, @@ -603,7 +613,7 @@ Dungeons::Dungeons() { {}); dungeonList[GERUDO_TRAINING_GROUNDS] = DungeonInfo("Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE, - RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, RA_GERUDO_TRAINING_GROUND, 9, 3, + RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, RA_GERUDO_TRAINING_GROUND, 9, 3, RSK_MQ_GTG, { // Vanilla Locations RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, @@ -652,7 +662,7 @@ Dungeons::Dungeons() { {}, {}); dungeonList[GANONS_CASTLE] = DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY, - RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, RA_GANONS_CASTLE, 2, 3, + RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, RA_GANONS_CASTLE, 2, 3, RSK_MQ_GANONS_CASTLE, { // Vanilla Locations RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, diff --git a/soh/soh/Enhancements/randomizer/dungeon.h b/soh/soh/Enhancements/randomizer/dungeon.h index a2338441d..b9176f707 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.h +++ b/soh/soh/Enhancements/randomizer/dungeon.h @@ -12,7 +12,8 @@ class DungeonInfo { public: DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, RandomizerArea area_, - uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, std::vector vanillaLocations_, + uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, RandomizerSettingKey mqSetting_, + std::vector vanillaLocations_, std::vector mqLocations_, std::vector sharedLocations_, std::vector bossRoomLocations_); DungeonInfo(); @@ -34,6 +35,8 @@ class DungeonInfo { RandomizerGet GetMap() const; RandomizerGet GetCompass() const; RandomizerGet GetBossKey() const; + RandomizerSettingKey GetMQSetting() const; + void SetDungeonKnown(bool known); void PlaceVanillaMap() const; void PlaceVanillaCompass() const; void PlaceVanillaBossKey() const; @@ -50,6 +53,8 @@ class DungeonInfo { RandomizerGet smallKey; RandomizerGet keyRing; RandomizerGet bossKey; + RandomizerSettingKey mqSetting; + bool isDungeonModeKnown = true; uint8_t vanillaKeyCount{}; uint8_t mqKeyCount{}; bool masterQuest = false; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 3e91715c4..ad5cd4e09 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -98,7 +98,8 @@ void Settings::CreateOptionDescriptions() { "\n" "Random Number - A Random number and set of dungeons will be their Master Quest varieties.\n" "\n" - "Selection Only - Specify which dungeons are Vanilla or Master Quest."; + "Selection Only - Specify which dungeons are Vanilla, Master Quest or a 50/50 between the two.\n" + "Differs from Random Number in that they are rolled individually, making the exact total a bell curve."; mOptionDescriptions[RSK_MQ_DUNGEON_SET] = "Choose specific Dungeons to be Master Quest or Vanilla.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index d6fc3fefd..ddedd5b53 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -112,12 +112,12 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { (location.GetRandomizerCheck() != RC_UNKNOWN_CHECK) && (!RandomizerCheckObjects::AreaIsDungeon(location.GetArea()) || location.GetQuest() == RCQUEST_BOTH || location.GetQuest() == RCQUEST_MQ && - ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && - (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeonCount"), 12) > 0) || // at least one MQ dungeon - CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || + ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SET_NUMBER && + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) > 0) || // at least one MQ dungeon + CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_RANDOM_NUMBER)) || location.GetQuest() == RCQUEST_VANILLA && - (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || - CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeonCount"), 12) < 12) // at least one vanilla dungeon + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon ) && (location.GetRCType() != RCTYPE_SHOP || CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 745593ef5..80007b564 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1486,7 +1486,7 @@ void Settings::UpdateOptionProperties() { } else { // If any MQ Options are available, show the MQ Dungeon Randomization Combobox mOptions[RSK_MQ_DUNGEON_RANDOM].Unhide(); - switch(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE)) { + switch(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE)) { // If No MQ Dungeons, add a separator after the combobx and hide // the count slider and the toggle for individual dungeon selections. case RO_MQ_DUNGEONS_NONE: @@ -1504,17 +1504,22 @@ void Settings::UpdateOptionProperties() { // else if random number or selection only, remove the separator and only show // the individual dungeon selection toggle. case RO_MQ_DUNGEONS_RANDOM_NUMBER: - case RO_MQ_DUNGEONS_SELECTION: mOptions[RSK_MQ_DUNGEON_RANDOM].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MQ_DUNGEON_COUNT].Hide(); mOptions[RSK_MQ_DUNGEON_SET].Unhide(); break; + case RO_MQ_DUNGEONS_SELECTION: + mOptions[RSK_MQ_DUNGEON_RANDOM].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); + mOptions[RSK_MQ_DUNGEON_COUNT].Hide(); + mOptions[RSK_MQ_DUNGEON_SET].Hide(); + break; default: break; } // Controls whether or not to show the selectors for individual dungeons. - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE && - CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeonsSelection"), RO_GENERIC_OFF) == RO_GENERIC_ON) { + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE && + (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), RO_GENERIC_OFF) == RO_GENERIC_ON || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION)) { // if showing the dungeon selectors, remove the separator after the Set Dungeons checkbox. mOptions[RSK_MQ_DUNGEON_SET].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_MQ_DEKU_TREE].Unhide(); @@ -1546,12 +1551,7 @@ void Settings::UpdateOptionProperties() { mOptions[RSK_MQ_GANONS_CASTLE].Hide(); } } - // Disable interaction with Set Dungeons checkbox if MQ Dungeon Randomization is set to Selection Only. - if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MqDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION) { - mOptions[RSK_MQ_DUNGEON_SET].Disable("This option is force-enabled because Master Quest Dungeons is set to Selection Only", UIWidgets::CheckboxGraphics::Checkmark); - } else { - mOptions[RSK_MQ_DUNGEON_SET].Enable(); - } + // Show mixed entrance pool options if mixed entrance pools are enabled at all. if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF)) { mOptions[RSK_MIXED_ENTRANCE_POOLS].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); @@ -1871,74 +1871,121 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio // RANDOTODO implement chest shuffle with keysanity // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); mOptions[RSK_SHUFFLE_CHEST_MINIGAME].SetSelectedIndex(RO_CHEST_GAME_OFF); + //TODO: RandomizeAllSettings(true) when implementing the ability to randomize the options themselves. std::array dungeons = ctx->GetDungeons()->GetDungeonList(); - std::array dungeonModesKnown{}; - const std::vector dungeonOptions = { - &mOptions[RSK_MQ_DEKU_TREE], - &mOptions[RSK_MQ_DODONGOS_CAVERN], - &mOptions[RSK_MQ_JABU_JABU], - &mOptions[RSK_MQ_FOREST_TEMPLE], - &mOptions[RSK_MQ_FIRE_TEMPLE], - &mOptions[RSK_MQ_WATER_TEMPLE], - &mOptions[RSK_MQ_SPIRIT_TEMPLE], - &mOptions[RSK_MQ_SHADOW_TEMPLE], - &mOptions[RSK_MQ_BOTTOM_OF_THE_WELL], - &mOptions[RSK_MQ_ICE_CAVERN], - &mOptions[RSK_MQ_GTG], - &mOptions[RSK_MQ_GANONS_CASTLE] - }; - auto mqSet = mOptions[RSK_MQ_DUNGEON_COUNT].Value(); - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_SELECTION)) { - mqSet = 0; + + //reset the MQ vars + for (auto dungeon: dungeons) { + dungeon->ClearMQ(); + dungeon->SetDungeonKnown(true); } - std::vector randMQOption = {}; - if (mOptions[RSK_MQ_DUNGEON_SET]) { - uint8_t dungeonCount = 0; - for (size_t i = 0; i < dungeons.size(); i++) { - dungeons[i]->ClearMQ(); - dungeonModesKnown[i] = true; - switch (dungeonOptions[i]->Value()) { - case 1: - dungeons[i]->SetMQ(); - dungeonCount++; + //if it's selection mode, process the selection directly + if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value() == RO_MQ_DUNGEONS_SELECTION){ + mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_ON); + //How many dungeons are set to MQ in selection + uint8_t mqSet = 0; + for (auto dungeon: dungeons) { + switch (mOptions[dungeon->GetMQSetting()].Value()) { + case RO_MQ_SET_MQ: + dungeon->SetMQ(); + mqSet += 1; break; - case 2: - randMQOption.push_back(i); - dungeonModesKnown[i] = false; + case RO_MQ_SET_RANDOM: + //50% per dungeon, rolled seperatly so people can either have a linear distribtuion + //or a bell curve for the number of MQ dungeons per seed. + if (Random(0,2)){ + dungeon->SetMQ(); + mqSet += 1; + } + dungeon->SetDungeonKnown(false); break; default: break; } } - Shuffle(randMQOption); - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_RANDOM_NUMBER)) { - mqSet = dungeonCount + Random(0, static_cast(randMQOption.size()) + 1); - } - for (uint8_t i = 0; dungeonCount < mqSet; i++) { - if (i > randMQOption.size()) { - // This can happen if the amount of MQ Dungeons is specifically - // set to a higher number than the amount of Dungeons specifically set to MQ or Random, - // break out of the loop and just have fewer MQ dungeons than the Set Count. - break; + //override the dungeons set with the ones set by selection, so it's accurate for anything that wants to know MQ dungeon count + mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(mqSet); + //handling set number and random number together + } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value() != RO_MQ_DUNGEONS_NONE){ + // so we don't have to call this repeatedly + uint8_t mqCount = mOptions[RSK_MQ_DUNGEON_COUNT].Value(); + //How many dungeons are set to MQ in selection + uint8_t mqSet = 0; + //the number of random + uint8_t mqToSet = 0; + //store the dungeons to randomly decide between. we use the id instead of a dungeon object to avoid a lot of casting. + std::vector randMQOption = {}; + //if dungeons have been preset, process them + if (mOptions[RSK_MQ_DUNGEON_SET]){ + for (size_t i = 0; i < dungeons.size(); i++) { + switch (mOptions[dungeons[i]->GetMQSetting()].Value()) { + case RO_MQ_SET_MQ: + dungeons[i]->SetMQ(); + mqSet += 1; + break; + case RO_MQ_SET_RANDOM: + randMQOption.push_back(i); + dungeons[i]->SetDungeonKnown(false); + break; + default: + break; + } + } + //otherwise, every dungeon is possible + } else { + //if the count is fixed to 12, we know everything is MQ, so can skip some setps and do not set Known + if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value() == RO_MQ_DUNGEONS_SET_NUMBER && + mqCount == 12) { + randMQOption = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + for (auto dungeon: dungeons) { + mOptions[dungeon->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_MQ); + } + //if it's fixed to zero, set it to None instead. the rest is processed after + } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value() == RO_MQ_DUNGEONS_SET_NUMBER && + mqCount == 0){ + mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + //otherwise, make everything a possibility and unknown + } else { + for (size_t i = 0; i < dungeons.size(); i++) { + randMQOption.push_back(i); + dungeons[i]->SetDungeonKnown(false); + mOptions[dungeons[i]->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_RANDOM); + } } - dungeons[randMQOption[i]]->SetMQ(); - dungeonCount++; } - } else { - Shuffle(dungeons); - for (const auto dungeon : dungeons) { - dungeon->ClearMQ(); + //if there's no random options, we can skip this + if (randMQOption.size() > 0){ + //Figure out how many dungeons to select, rolling the random number if needed + if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_RANDOM_NUMBER)){ + mqToSet = Random(0, static_cast(randMQOption.size()) + 1); + } else if (mqCount > mqSet) { + mqToSet = std::min(mqCount - mqSet, static_cast(randMQOption.size())); + } + //we only need to shuffle if we're not using them all + if (mqToSet <= static_cast(randMQOption.size()) && mqToSet > 0) { + Shuffle(randMQOption); + } + for (uint8_t i = 0; i < mqToSet; i++){ + dungeons[randMQOption[i]]->SetMQ(); + } + } else { + //if there's no random options, check if we can collapse the setting into None or Selection + if (mqSet == 0){ + mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + } else { + mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_SELECTION); + } } - const bool allDungeonModesKnown = mqSet == 0 || mqSet == dungeons.size(); - for (bool & i : dungeonModesKnown) { - i = allDungeonModesKnown; - } - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_RANDOM_NUMBER)) { - mqSet = Random(0, 13); - } - for (uint8_t i = 0; i < mqSet; i++) { - dungeons[i]->SetMQ(); + //reset the value set based on what was actually set + mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(mqToSet + mqSet); + } + //Not an if else as other settings can become None in processing + if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value() == RO_MQ_DUNGEONS_NONE) { + mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(0); + for (auto dungeon: dungeons) { + mOptions[dungeon->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_VANILLA); } } From 8b6c183776bddb511e7cec7a07d0018507ff101d Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:55:05 +0200 Subject: [PATCH 276/300] Rando: Skeleton key (#3997) * Initial Implementation * Add temporary model to the skeleton key --- .../Enhancements/debugger/debugSaveEditor.h | 4 +- soh/soh/Enhancements/mods.cpp | 23 ++- .../randomizer/3drando/item_pool.cpp | 4 + soh/soh/Enhancements/randomizer/draw.cpp | 50 ++++++ soh/soh/Enhancements/randomizer/draw.h | 1 + soh/soh/Enhancements/randomizer/item_list.cpp | 3 + soh/soh/Enhancements/randomizer/logic.cpp | 6 + soh/soh/Enhancements/randomizer/logic.h | 3 + .../randomizer/option_descriptions.cpp | 2 +- .../Enhancements/randomizer/randomizer.cpp | 3 +- .../Enhancements/randomizer/randomizerTypes.h | 3 + .../Enhancements/randomizer/randomizer_inf.h | 4 +- soh/soh/Enhancements/randomizer/settings.cpp | 7 +- soh/src/code/z_parameter.c | 159 +++++++++--------- .../overlays/actors/ovl_En_Door/z_en_door.h | 3 + 15 files changed, 194 insertions(+), 81 deletions(-) diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index e5086f5b8..661cf87be 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -596,11 +596,13 @@ const std::vector flagTables = { { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }, + { RAND_INF_HAS_SKELETON_KEY, "RAND_INF_HAS_SKELETON_KEY" }, + { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, { RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" }, { RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" }, { RAND_INF_KING_ZORA_THAWED, "RAND_INF_KING_ZORA_THAWED" }, - + { RAND_INF_HC_GREAT_FAIRY_REWARD, "RAND_INF_HC_GREAT_FAIRY_REWARD" }, { RAND_INF_DMT_GREAT_FAIRY_REWARD, "RAND_INF_DMT_GREAT_FAIRY_REWARD" }, { RAND_INF_DMC_GREAT_FAIRY_REWARD, "RAND_INF_DMC_GREAT_FAIRY_REWARD" }, diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 2efe6477e..098317bae 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -29,8 +29,10 @@ #include "src/overlays/actors/ovl_En_Tp/z_en_tp.h" #include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h" #include "src/overlays/actors/ovl_En_Xc/z_en_xc.h" -#include "src/overlays//actors/ovl_Fishing/z_fishing.h" +#include "src/overlays/actors/ovl_Fishing/z_fishing.h" #include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" +#include "src/overlays/actors/ovl_En_Door/z_en_door.h" #include "objects/object_link_boy/object_link_boy.h" #include "objects/object_link_child/object_link_child.h" @@ -1712,6 +1714,24 @@ void RegisterRandomizerCompasses() { }); } +void RegisterSkeletonKey() { + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + Actor* actor = static_cast(refActor); + + if (Flags_GetRandomizerInf(RAND_INF_HAS_SKELETON_KEY)) { + if (actor->id == ACTOR_EN_DOOR) { + EnDoor* door = (EnDoor*)actor; + door->lockTimer = 0; + } else if (actor->id == ACTOR_DOOR_SHUTTER) { + DoorShutter* shutterDoor = (DoorShutter*)actor; + if (shutterDoor->doorType == SHUTTER_KEY_LOCKED) { + shutterDoor->unk_16E = 0; + } + } + } + }); +} + void InitMods() { RandomizerRegisterHooks(); TimeSaverRegisterHooks(); @@ -1760,4 +1780,5 @@ void InitMods() { RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); RegisterPauseMenuHooks(); + RegisterSkeletonKey(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index caf7c811e..6d2e44fbf 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -782,6 +782,10 @@ void GenerateItemPool() { ctx->possibleIceTrapModels.push_back(RG_OCARINA_C_RIGHT_BUTTON); } + if (ctx->GetOption(RSK_SKELETON_KEY)) { + AddItemToMainPool(RG_SKELETON_KEY); + } + if (ctx->GetOption(RSK_SHUFFLE_SWIM)) { AddItemToMainPool(RG_PROGRESSIVE_SCALE); } diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index f35567b83..11e4a430b 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -541,5 +541,55 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); +} + +int skeletonKeyHue = 0; + +// Runs every frame to update rainbow hue, taken from CosmeticsEditor.cpp. +Color_RGBA8 GetSkeletonKeyColor() { + float rainbowSpeed = 0.6f; + + float frequency = 2 * M_PI / (360 * rainbowSpeed); + Color_RGBA8 color; + color.r = sin(frequency * skeletonKeyHue + 0) * 127 + 128; + color.g = sin(frequency * skeletonKeyHue + (2 * M_PI / 3)) * 127 + 128; + color.b = sin(frequency * skeletonKeyHue + (4 * M_PI / 3)) * 127 + 128; + color.a = 255; + + skeletonKeyHue++; + if (skeletonKeyHue >= (360 * rainbowSpeed)) skeletonKeyHue = 0; + + return color; +} + +int test = 0; + +extern "C" void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Color_RGBA8 color = GetSkeletonKeyColor(); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + test += 1; + + if (test > 40) { + test -= 80; + } + + Matrix_RotateZ(M_PI / 40 * test, MTXMODE_APPLY); + Matrix_RotateY(M_PI / 40 * test, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_OPA_DISP++, color.r, color.g, color.b, color.a); + gSPGrayscale(POLY_OPA_DISP++, true); + + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL); + + gSPGrayscale(POLY_OPA_DISP++, false); + CLOSE_DISPS(play->state.gfxCtx); } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index ec390c002..d0ba3c747 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -21,6 +21,7 @@ void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry); #define GET_ITEM_MYSTERY \ diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 3bdd2709f..b9bd9be22 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -289,6 +289,9 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveWallet, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &logic->SkeletonKey, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, &logic->ProgressiveStickBag, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, &logic->ProgressiveNutBag, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index b1fa969d0..49f611f0e 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -411,6 +411,9 @@ namespace Rando { } bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched) { + if (SkeletonKey) { + return true; + } switch (dungeon) { case RR_FOREST_TEMPLE: /*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotJump_Boots) >= static_cast(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHoverBoost) >= static_cast(GlitchDifficulty::NOVICE) || @@ -673,6 +676,9 @@ namespace Rando { //Triforce Pieces TriforcePieces = 0; + //Skeleton Key + SkeletonKey = false; + //Boss Souls CanSummonGohma = false; CanSummonKingDodongo = false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 16213049d..799b8402a 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -171,6 +171,9 @@ class Logic { // Triforce Pieces uint8_t TriforcePieces = 0; + // Skeleton Key + bool SkeletonKey = false; + // Boss Keys bool BossKeyForestTemple = false; bool BossKeyFireTemple = false; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index ad5cd4e09..e5b0722f3 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -542,7 +542,6 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_KAK_50_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 50 tokens will tell you the reward"; mOptionDescriptions[RSK_KAK_100_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 100 tokens will tell you the reward"; mOptionDescriptions[RSK_MASK_SHOP_HINT] = "Reading the mask shop sign will tell you rewards from showing masks at the Deku Theatre."; - mOptionDescriptions[RSK_FULL_WALLETS] = "Start with a full wallet. All wallet upgrades come filled with rupees."; mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC] = "Bombchus are properly considered in logic.\n" @@ -557,6 +556,7 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_BLUE_FIRE_ARROWS] = "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress."; + mOptionDescriptions[RSK_SKELETON_KEY] = "Adds a new item called the \"Skeleton Key\", it unlocks every dungeon door locked by a small key."; mOptionDescriptions[RSK_SUNLIGHT_ARROWS] = "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 303a6bbfd..faac02d84 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2954,7 +2954,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ + const std::array getItemMessages = {{ GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", @@ -3226,6 +3226,7 @@ void Randomizer::CreateCustomMessages() { "Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), GIMESSAGE_UNTRANSLATED(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!"), GIMESSAGE_UNTRANSLATED(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!"), + GIMESSAGE_UNTRANSLATED(RG_SKELETON_KEY, ITEM_KEY_SMALL, "You found the %rSkeleton Key%w!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_STICK_BAG, ITEM_STICK, "You found the %rDeku Stick Bag%w!&You can now hold deku sticks!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_NUT_BAG, ITEM_NUT, "You found the %rDeku Nut Bag%w!&You can now hold deku nuts!"), }}; diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index d15d3d4a3..e89059ecd 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1979,6 +1979,7 @@ typedef enum { RG_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, + RG_SKELETON_KEY, RG_FISHING_POLE, RG_DEKU_STICK_BAG, RG_DEKU_NUT_BAG, @@ -3244,6 +3245,7 @@ typedef enum { RHT_OCARINA_C_RIGHT_BUTTON, RHT_BRONZE_SCALE, RHT_FISHING_POLE, + RHT_SKELETON_KEY, RHT_EPONA, RHT_HINT_MYSTERIOUS, RHT_MYSTERIOUS_ITEM, @@ -3713,6 +3715,7 @@ typedef enum { RSK_FISHSANITY_POND_COUNT, RSK_FISHSANITY_AGE_SPLIT, RSK_SHUFFLE_FISHING_POLE, + RSK_SKELETON_KEY, RSK_SHUFFLE_DEKU_STICK_BAG, RSK_SHUFFLE_DEKU_NUT_BAG, RSK_MAX diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index f1ae83121..72168f018 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -257,11 +257,13 @@ typedef enum { RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_5, + RAND_INF_HAS_SKELETON_KEY, + RAND_INF_LINKS_POCKET, RAND_INF_LEARNED_EPONA_SONG, RAND_INF_DARUNIAS_JOY, RAND_INF_KING_ZORA_THAWED, - + RAND_INF_HC_GREAT_FAIRY_REWARD, RAND_INF_DMT_GREAT_FAIRY_REWARD, RAND_INF_DMC_GREAT_FAIRY_REWARD, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 80007b564..28f341631 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -184,6 +184,7 @@ void Settings::CreateOptions() { // TODO: Compasses show rewards/woth, maps show dungeon mode mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); + mOptions[RSK_SKELETON_KEY] = Option::Bool("Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]); mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); // TODO: Remove Double Defense, Progressive Goron Sword @@ -764,7 +765,8 @@ void Settings::CreateOptions() { &mOptions[RSK_BOMBCHUS_IN_LOGIC], &mOptions[RSK_ENABLE_BOMBCHU_DROPS], &mOptions[RSK_BLUE_FIRE_ARROWS], - &mOptions[RSK_SUNLIGHT_ARROWS] + &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_SKELETON_KEY], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE] = OptionGroup::SubGroup("Gameplay", { &mOptionGroups[RSG_TIMESAVERS_IMGUI], @@ -992,6 +994,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DAMAGE_MULTIPLIER], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_SKELETON_KEY], }); mOptionGroups[RSG_ITEM_POOL] = OptionGroup("Item Pool Settings", std::initializer_list({ &mOptions[RSK_ITEM_POOL], @@ -1210,6 +1213,7 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, { "Miscellaneous Settings:Blue Fire Arrows", RSK_BLUE_FIRE_ARROWS }, { "Miscellaneous Settings:Sunlight Arrows", RSK_SUNLIGHT_ARROWS }, + { "Miscellaneous Settings:Skeleton Key", RSK_SKELETON_KEY }, { "Timesaver Settings:Skip Child Zelda", RSK_SKIP_CHILD_ZELDA }, { "Start with Consumables", RSK_STARTING_CONSUMABLES }, { "Full Wallets", RSK_FULL_WALLETS }, @@ -2359,6 +2363,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SKULLS_SUNS_SONG: case RSK_BLUE_FIRE_ARROWS: case RSK_SUNLIGHT_ARROWS: + case RSK_SKELETON_KEY: case RSK_BOMBCHUS_IN_LOGIC: case RSK_TOT_ALTAR_HINT: case RSK_GANONDORF_HINT: diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 2f39ade8c..a03a74c69 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2796,6 +2796,11 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { return Return_Item_Entry(giEntry, RG_NONE); } + if (item == RG_SKELETON_KEY) { + Flags_SetRandomizerInf(RAND_INF_HAS_SKELETON_KEY); + return Return_Item_Entry(giEntry, RG_NONE); + } + if (item == RG_DEKU_STICK_BAG) { Inventory_ChangeUpgrade(UPG_STICKS, 1); INV_CONTENT(ITEM_STICK) = ITEM_STICK; @@ -5370,83 +5375,87 @@ void Interface_Draw(PlayState* play) { } } - switch (play->sceneNum) { - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_GANONS_TOWER: - case SCENE_GERUDO_TRAINING_GROUND: - case SCENE_THIEVES_HIDEOUT: - case SCENE_INSIDE_GANONS_CASTLE: - case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: - case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: - case SCENE_TREASURE_BOX_SHOP: - if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] >= 0) { - s16 X_Margins_SKC; - s16 Y_Margins_SKC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 0) {X_Margins_SKC = Left_HUD_Margin;}; - Y_Margins_SKC = Bottom_HUD_Margin; - } else { - X_Margins_SKC = 0; - Y_Margins_SKC = 0; - } - s16 PosX_SKC_ori = OTRGetRectDimensionFromLeftEdge(26+X_Margins_SKC); - s16 PosY_SKC_ori = 190+Y_Margins_SKC; - s16 PosX_SKC; - s16 PosY_SKC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) != 0) { - PosY_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosY"), 0)+Y_Margins_SKC; - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 1) {//Anchor Left - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Left_HUD_Margin;}; - PosX_SKC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 2) {//Anchor Right - if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Right_HUD_Margin;}; - PosX_SKC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 3) {//Anchor None - PosX_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 4) {//Hidden - PosX_SKC = -9999; + //when having the skeleton key in rando, don't render the small key counter + if (!Flags_GetRandomizerInf(RAND_INF_HAS_SKELETON_KEY)) { + switch (play->sceneNum) { + case SCENE_FOREST_TEMPLE: + case SCENE_FIRE_TEMPLE: + case SCENE_WATER_TEMPLE: + case SCENE_SPIRIT_TEMPLE: + case SCENE_SHADOW_TEMPLE: + case SCENE_BOTTOM_OF_THE_WELL: + case SCENE_ICE_CAVERN: + case SCENE_GANONS_TOWER: + case SCENE_GERUDO_TRAINING_GROUND: + case SCENE_THIEVES_HIDEOUT: + case SCENE_INSIDE_GANONS_CASTLE: + case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: + case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: + case SCENE_TREASURE_BOX_SHOP: + + if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] >= 0) { + s16 X_Margins_SKC; + s16 Y_Margins_SKC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 0) {X_Margins_SKC = Left_HUD_Margin;}; + Y_Margins_SKC = Bottom_HUD_Margin; + } else { + X_Margins_SKC = 0; + Y_Margins_SKC = 0; } - } else { - PosY_SKC = PosY_SKC_ori; - PosX_SKC = PosX_SKC_ori; + s16 PosX_SKC_ori = OTRGetRectDimensionFromLeftEdge(26+X_Margins_SKC); + s16 PosY_SKC_ori = 190+Y_Margins_SKC; + s16 PosX_SKC; + s16 PosY_SKC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) != 0) { + PosY_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosY"), 0)+Y_Margins_SKC; + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 1) {//Anchor Left + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Left_HUD_Margin;}; + PosX_SKC = OTRGetDimensionFromLeftEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 2) {//Anchor Right + if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.UseMargins"), 0) != 0) {X_Margins_SKC = Right_HUD_Margin;}; + PosX_SKC = OTRGetDimensionFromRightEdge(CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0)+X_Margins_SKC); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 3) {//Anchor None + PosX_SKC = CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosX"), 0); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.SmallKey.PosType"), 0) == 4) {//Hidden + PosX_SKC = -9999; + } + } else { + PosY_SKC = PosY_SKC_ori; + PosX_SKC = PosX_SKC_ori; + } + // Small Key Icon + gDPPipeSync(OVERLAY_DISP++); + + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, keyCountColor.r,keyCountColor.g,keyCountColor.b, interfaceCtx->magicAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255); //We reset this here so it match user color :) + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, PosX_SKC, PosY_SKC, 16, 16, + 1 << 10, 1 << 10); + + // Small Key Counter + gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->magicAlpha); + gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, + TEXEL0, 0, PRIMITIVE, 0); + + interfaceCtx->counterDigits[2] = 0; + interfaceCtx->counterDigits[3] = gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]; + + while (interfaceCtx->counterDigits[3] >= 10) { + interfaceCtx->counterDigits[2]++; + interfaceCtx->counterDigits[3] -= 10; + } + + if (interfaceCtx->counterDigits[2] != 0) { + OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)((u8*)digitTextures[interfaceCtx->counterDigits[2]])), 8, 16, PosX_SKC+8, PosY_SKC, 8, 16, 1 << 10, 1 << 10); + } + + OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[3]]), 8, 16, PosX_SKC+16, PosY_SKC, 8, 16, 1 << 10, 1 << 10); } - // Small Key Icon - gDPPipeSync(OVERLAY_DISP++); - - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, keyCountColor.r,keyCountColor.g,keyCountColor.b, interfaceCtx->magicAlpha); - gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255); //We reset this here so it match user color :) - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, PosX_SKC, PosY_SKC, 16, 16, - 1 << 10, 1 << 10); - - // Small Key Counter - gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->magicAlpha); - gDPSetCombineLERP(OVERLAY_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, - TEXEL0, 0, PRIMITIVE, 0); - - interfaceCtx->counterDigits[2] = 0; - interfaceCtx->counterDigits[3] = gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]; - - while (interfaceCtx->counterDigits[3] >= 10) { - interfaceCtx->counterDigits[2]++; - interfaceCtx->counterDigits[3] -= 10; - } - - if (interfaceCtx->counterDigits[2] != 0) { - OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)((u8*)digitTextures[interfaceCtx->counterDigits[2]])), 8, 16, PosX_SKC+8, PosY_SKC, 8, 16, 1 << 10, 1 << 10); - } - - OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[3]]), 8, 16, PosX_SKC+16, PosY_SKC, 8, 16, 1 << 10, 1 << 10); - } - break; - default: - break; + break; + default: + break; + } } // Rupee Counter diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h index 7389ac99a..4e7ef1279 100644 --- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h +++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h @@ -57,6 +57,9 @@ typedef struct EnDoor { /* 0x01D4 */ EnDoorActionFunc actionFunc; } EnDoor; // size = 0x01D8 +#ifdef __cplusplus +extern "C" +#endif void EnDoor_SetupType(EnDoor* enDoor, PlayState* play); #endif From 134aba4aa0e0617a2082cb86db7e1a7eb116c8e0 Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Wed, 17 Jul 2024 14:35:13 -0400 Subject: [PATCH 277/300] Fixes crashes on asan related to audio. (#4049) Found in MM --- soh/soh/mixer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/soh/soh/mixer.c b/soh/soh/mixer.c index 2e80ffb16..ba6a01bc1 100644 --- a/soh/soh/mixer.c +++ b/soh/soh/mixer.c @@ -99,8 +99,14 @@ void aClearBufferImpl(uint16_t addr, int nbytes) { memset(BUF_U8(addr), 0, nbytes); } -void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) { +void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes) { +#if __SANITIZE_ADDRESS__ + for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) { + BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i]; + } +#else memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes)); +#endif } void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) { From 3d73faa9a0c75e13e25f0d8d73994ca6dbe71938 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 17 Jul 2024 12:57:11 -0700 Subject: [PATCH 278/300] Port Graphics Menu lag fix from 2ship. (#4238) * Port Graphics Menu lag fix from 2ship. * tweak --------- Co-authored-by: Adam Bird --- soh/soh/SohMenuBar.cpp | 61 +++++++++++++++++++++++++----------------- soh/soh/SohMenuBar.h | 2 +- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 0917b0c6d..575dcbc1a 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -50,6 +50,13 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) { if (!menuOpen) { strcat(buttonText, " "); } return buttonText; } + +static std::unordered_map windowBackendNames = { + { LUS::WindowBackend::DX11, "DirectX" }, + { LUS::WindowBackend::SDL_OPENGL, "OpenGL"}, + { LUS::WindowBackend::SDL_METAL, "Metal" }, + { LUS::WindowBackend::GX2, "GX2"} +}; static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large" }; @@ -102,6 +109,24 @@ extern "C" SaveContext gSaveContext; namespace SohGui { +std::unordered_map availableWindowBackendsMap; +LUS::WindowBackend configWindowBackend; + +void UpdateWindowBackendObjects() { + LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend(); + int32_t configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); + if (configWindowBackendId != -1 && configWindowBackendId < static_cast(LUS::WindowBackend::BACKEND_COUNT)) { + configWindowBackend = static_cast(configWindowBackendId); + } else { + configWindowBackend = runningWindowBackend; + } + + auto availableWindowBackends = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends(); + for (auto& backend : *availableWindowBackends) { + availableWindowBackendsMap[backend] = windowBackendNames[backend]; + } +} + void DrawMenuBarIcon() { static bool gameIconLoaded = false; if (!gameIconLoaded) { @@ -391,40 +416,24 @@ void DrawSettingsMenu() { UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements."); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); - - static std::unordered_map windowBackendNames = { - { LUS::WindowBackend::DX11, "DirectX" }, - { LUS::WindowBackend::SDL_OPENGL, "OpenGL"}, - { LUS::WindowBackend::SDL_METAL, "Metal" }, - { LUS::WindowBackend::GX2, "GX2"} - }; ImGui::Text("Renderer API (Needs reload)"); - LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend(); - LUS::WindowBackend configWindowBackend; - int configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); - if (configWindowBackendId != -1 && configWindowBackendId < static_cast(LUS::WindowBackend::BACKEND_COUNT)) { - configWindowBackend = static_cast(configWindowBackendId); - } else { - configWindowBackend = runningWindowBackend; - } - if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (availableWindowBackendsMap.size() <= 1) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) { - for (size_t i = 0; i < LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) { - auto backend = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i]; - if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) { - LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend)); - LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", - windowBackendNames[backend]); + if (ImGui::BeginCombo("##RApi", availableWindowBackendsMap[configWindowBackend])) { + for (auto backend : availableWindowBackendsMap) { + if (ImGui::Selectable(backend.second, backend.first == configWindowBackend)) { + LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend.first)); + LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", backend.second); LUS::Context::GetInstance()->GetConfig()->Save(); + UpdateWindowBackendObjects(); } } ImGui::EndCombo(); } - if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (availableWindowBackendsMap.size() <= 1) { UIWidgets::ReEnableComponent(""); } @@ -1610,6 +1619,10 @@ void DrawRandomizerMenu() { } } +void SohMenuBar::InitElement() { + UpdateWindowBackendObjects(); +} + void SohMenuBar::DrawElement() { if (ImGui::BeginMenuBar()) { DrawMenuBarIcon(); diff --git a/soh/soh/SohMenuBar.h b/soh/soh/SohMenuBar.h index ce62344ad..238903f19 100644 --- a/soh/soh/SohMenuBar.h +++ b/soh/soh/SohMenuBar.h @@ -10,7 +10,7 @@ class SohMenuBar : public LUS::GuiMenuBar { using LUS::GuiMenuBar::GuiMenuBar; protected: void DrawElement() override; - void InitElement() override {}; + void InitElement() override; void UpdateElement() override {}; }; } // namespace SohGui \ No newline at end of file From 4df4e61eb30043646d688ad7a68a7f3b08f151b9 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 18 Jul 2024 22:42:48 +0100 Subject: [PATCH 279/300] Fix return of Item_Give for stricter compilers (#4244) * fix return of Item_Give for stricter compilers * change to just item --- soh/src/code/z_parameter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a03a74c69..31b2a6d0b 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1933,7 +1933,7 @@ u8 Item_Give(PlayState* play, u8 item) { Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG) && CUR_UPG_VALUE(UPG_STICKS) == 0 ) { - return; + return item; } //prevents getting nuts without the bag in case something got missed @@ -1943,7 +1943,7 @@ u8 Item_Give(PlayState* play, u8 item) { Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG) && CUR_UPG_VALUE(UPG_NUTS) == 0 ) { - return; + return item; } lusprintf(__FILE__, __LINE__, 2, "Item Give - item: %#x", item); From 081a55ab294290fe860c4ab194da027fc3883684 Mon Sep 17 00:00:00 2001 From: Angelo Bulfone Date: Fri, 19 Jul 2024 21:49:26 -0600 Subject: [PATCH 280/300] Fix accidental assignment expression (#4248) A typo from https://github.com/HarbourMasters/Shipwright/commit/a5c0cede12d3a53cb0f1069a5d4a5c4febe991fa resulted in various bugs due to giving every actor the same id. --- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 2f314fc76..4f94e517a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1446,7 +1446,7 @@ void RandomizerOnActorInitHandler(void* actorRef) { //consumable bags if ( - actor->id = ACTOR_EN_ITEM00 && + actor->id == ACTOR_EN_ITEM00 && ( ( RAND_GET_OPTION(RSK_SHUFFLE_DEKU_STICK_BAG) && From 7bc2259c825597334c1ca02786f8acdc1e6984fb Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 21 Jul 2024 12:29:45 -0700 Subject: [PATCH 281/300] LUS bump and implement alt assets performance changes. (#4240) * LUS bump and implement alt assets performance changes. * LUS ref update. --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 23 +++++++++++++++-------- soh/soh/OTRGlobals.h | 1 + soh/soh/SohGui.cpp | 1 - soh/soh/SohMenuBar.cpp | 8 +------- soh/soh/resource/type/Skeleton.cpp | 7 +++---- soh/src/code/game.c | 2 +- soh/src/code/gfxprint.c | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libultraship b/libultraship index 96c8a8929..275c741d5 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 96c8a8929c18c1bffd7d92a35a589f74cf16fc59 +Subproject commit 275c741d5dd48d78b6a746c0709c75d095e48eeb diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bb45fdba7..136cb2473 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -137,6 +137,8 @@ Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 }; float previousImGuiScale; +bool prevAltAssets = false; + // Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED. typedef struct { Color_RGB8 inner; @@ -297,6 +299,8 @@ OTRGlobals::OTRGlobals() { }; // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) context = LUS::Context::CreateInstance("Ship of Harkinian", appShortName, "shipofharkinian.json", OTRFiles, {}, 3); + prevAltAssets = CVarGetInteger("gAltAssets", 0); + context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets); SPDLOG_INFO("Starting Ship of Harkinian version {}", (char*)gBuildVersion); context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Animation, "Animation", std::make_shared()); @@ -1235,7 +1239,7 @@ extern "C" void Graph_StartFrame() { } #endif case KbScancode::LUS_KB_TAB: { - ToggleAltAssetsAtEndOfFrame = true; + CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); break; } } @@ -1315,11 +1319,10 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { } } - if (ToggleAltAssetsAtEndOfFrame) { - ToggleAltAssetsAtEndOfFrame = false; - - // Actually update the CVar now before runing the alt asset update listeners - CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); + bool curAltAssets = CVarGetInteger("gAltAssets", 0); + if (prevAltAssets != curAltAssets) { + prevAltAssets = curAltAssets; + LUS::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); gfx_texture_cache_clear(); LUS::SkeletonPatcher::UpdateSkeletons(); GameInteractor::Instance->ExecuteHooks(); @@ -1495,10 +1498,14 @@ extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) { return ExtensionCache.contains(path); } +extern "C" bool ResourceMgr_IsAltAssetsEnabled() { + return LUS::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled(); +} + // Unloads a resource if an alternate version exists when alt assets are enabled // The resource is only removed from the internal cache to prevent it from used in the next resource lookup extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { - if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileAltExists((char*) resName)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists((char*) resName)) { ResourceMgr_UnloadResource((char*) resName); } } @@ -1868,7 +1875,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel pathStr = pathStr.substr(sOtr.length()); } - bool isAlt = CVarGetInteger("gAltAssets", 0); + bool isAlt = ResourceMgr_IsAltAssetsEnabled(); if (isAlt) { pathStr = LUS::IResource::gAltAssetPrefix + pathStr; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index a93df7efb..639ba2c34 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -120,6 +120,7 @@ void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); uint64_t GetPerfCounter(); +bool ResourceMgr_IsAltAssetsEnabled(); struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime); void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime); void ResourceMgr_ClearSkeletons(); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 90f6e59e5..6dda944b5 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -38,7 +38,6 @@ #include "Enhancements/game-interactor/GameInteractor.h" #include "Enhancements/cosmetics/authenticGfxPatches.h" -bool ToggleAltAssetsAtEndOfFrame = false; bool isBetaQuestEnabled = false; extern "C" { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 575dcbc1a..ee9a2708d 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -28,7 +28,6 @@ #include "Enhancements/randomizer/randomizer_item_tracker.h" #include "Enhancements/randomizer/randomizer_settings_window.h" -extern bool ToggleAltAssetsAtEndOfFrame; extern bool isBetaQuestEnabled; extern "C" PlayState* gPlayState; @@ -916,12 +915,7 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Graphics")) { if (ImGui::BeginMenu("Mods")) { - if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false)) { - // The checkbox will flip the alt asset CVar, but we instead want it to change at the end of the game frame - // We toggle it back while setting the flag to update the CVar later - CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0)); - ToggleAltAssetsAtEndOfFrame = true; - } + UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false); UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not."); UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", "gDisableBombBillboarding", true, false); UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects."); diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 13798d3c5..d83f8b91e 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -65,12 +65,11 @@ void SkeletonPatcher::ClearSkeletons() } void SkeletonPatcher::UpdateSkeletons() { - bool isHD = CVarGetInteger("gAltAssets", 0); + auto resourceMgr = LUS::Context::GetInstance()->GetResourceManager(); + bool isHD = resourceMgr->IsAltAssetsEnabled(); for (auto skel : skeletons) { Skeleton* newSkel = - (Skeleton*)LUS::Context::GetInstance()->GetResourceManager() - ->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) - .get(); + (Skeleton*)resourceMgr->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true).get(); if (newSkel != nullptr) { skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment; diff --git a/soh/src/code/game.c b/soh/src/code/game.c index b46aa4ebd..46c212b7a 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -467,7 +467,7 @@ void GameState_Destroy(GameState* gameState) { // Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system. ResourceMgr_ClearSkeletons(); - if (CVarGetInteger("gAltAssets", 0)) { + if (ResourceMgr_IsAltAssetsEnabled()) { ResourceUnloadDirectory("alt/*"); gfx_texture_cache_clear(); } diff --git a/soh/src/code/gfxprint.c b/soh/src/code/gfxprint.c index 8a0dbead4..cb33ec566 100644 --- a/soh/src/code/gfxprint.c +++ b/soh/src/code/gfxprint.c @@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt; // https://github.com/HarbourMasters/Shipwright/issues/2762 typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t; font_texture_t GfxPrint_TextureToUse() { - if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { // If we have alt assets enabled, and we have alt prefixed font texture, use that return otrAlt; } else if (ResourceMgr_FileExists(rGfxPrintFontData)) { From 7a00658be94d7ed9841c3377d166fde2364d88b9 Mon Sep 17 00:00:00 2001 From: Archez Date: Sun, 21 Jul 2024 15:30:18 -0400 Subject: [PATCH 282/300] Fix disable lod breaking certain effects (#4245) --- soh/src/code/z_fcurve_data_skelanime.c | 4 ---- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index b75c34a61..c75450be2 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -131,10 +131,6 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv Matrix_TranslateRotateZYX(&pos, &rot); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); - if (CVarGetInteger("gDisableLOD", 0)) { - lod = 0; - } - if (lod == 0) { s32 pad1; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 965389c40..f4a072c40 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11339,10 +11339,6 @@ void Player_Draw(Actor* thisx, PlayState* play2) { lod = 1; } - if (CVarGetInteger("gDisableLOD", 0)) { - lod = 0; - } - func_80093C80(play); Gfx_SetupDL_25Xlu(play->state.gfxCtx); From 3bcd93428e4d39982ae6c921126c0e10b4b7e46e Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:54:14 +0200 Subject: [PATCH 283/300] Rando: Infinite upgrades (Rando V3) (#3942) * Infinite Upgrades * Add "Condensed Progressive" * VB & fix build * Update settings.cpp --- .../cosmetics/CosmeticsEditor.cpp | 1 + .../Enhancements/debugger/debugSaveEditor.h | 9 ++ .../game-interactor/GameInteractor.h | 22 ++++ soh/soh/Enhancements/mods.cpp | 41 ++++++ .../3drando/hint_list/hint_list_item.cpp | 48 +++++++ .../randomizer/3drando/item_pool.cpp | 10 ++ .../Enhancements/randomizer/hook_handlers.cpp | 18 +++ soh/soh/Enhancements/randomizer/item.cpp | 105 +++++++++++++-- soh/soh/Enhancements/randomizer/item_list.cpp | 9 ++ .../randomizer/option_descriptions.cpp | 5 + .../Enhancements/randomizer/randomizer.cpp | 115 ++++++++++++++--- .../Enhancements/randomizer/randomizerTypes.h | 24 ++++ .../Enhancements/randomizer/randomizer_inf.h | 9 ++ soh/soh/Enhancements/randomizer/settings.cpp | 5 + soh/src/code/z_parameter.c | 121 ++++++++++++++---- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 7 + 16 files changed, 499 insertions(+), 50 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 4badd8279..f4f344b49 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -220,6 +220,7 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 0, 200, 255), false, true, true), COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 661cf87be..4199b7172 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -596,6 +596,15 @@ const std::vector flagTables = { { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }, + { RAND_INF_HAS_INFINITE_QUIVER, "RAND_INF_HAS_INFINITE_QUIVER" }, + { RAND_INF_HAS_INFINITE_BOMB_BAG, "RAND_INF_HAS_INFINITE_BOMB_BAG" }, + { RAND_INF_HAS_INFINITE_BULLET_BAG, "RAND_INF_HAS_INFINITE_BULLET_BAG" }, + { RAND_INF_HAS_INFINITE_STICK_UPGRADE, "RAND_INF_HAS_INFINITE_STICK_UPGRADE" }, + { RAND_INF_HAS_INFINITE_NUT_UPGRADE, "RAND_INF_HAS_INFINITE_NUT_UPGRADE" }, + { RAND_INF_HAS_INFINITE_MAGIC_METER, "RAND_INF_HAS_INFINITE_MAGIC_METER" }, + { RAND_INF_HAS_INFINITE_BOMBCHUS, "RAND_INF_HAS_INFINITE_BOMBCHUS" }, + { RAND_INF_HAS_INFINITE_MONEY, "RAND_INF_HAS_INFINITE_MONEY" }, + { RAND_INF_HAS_SKELETON_KEY, "RAND_INF_HAS_SKELETON_KEY" }, { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 57f1d1e5c..2323e7222 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -220,6 +220,28 @@ typedef enum { VB_GERUDOS_BE_FRIENDLY, // Vanilla condition: switch VB_GTG_GATE_BE_OPEN, + // Opt: *s16 (item id) + /* Vanilla condition: + In one case: + ``` + true + ``` + In the other case: + ``` + (i == ITEM_STICK) || + (i == ITEM_NUT) || + (i == ITEM_BOMB) || + (i == ITEM_BOW) || + ( + (i >= ITEM_BOW_ARROW_FIRE) && + (i <= ITEM_BOW_ARROW_LIGHT) + ) || + (i == ITEM_SLINGSHOT) || + (i == ITEM_BOMBCHU) || + (i == ITEM_BEAN) + ``` + */ + VB_DRAW_AMMO_COUNT, /*** Play Cutscenes ***/ diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 098317bae..2571b7d96 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1694,6 +1694,46 @@ void RegisterFishsanity() { }); } +void RegisterInfiniteUpgrades() { + GameInteractor::Instance->RegisterGameHook([]() { + if (!IS_RANDO) { + return; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) { + AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) { + AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) { + AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) { + AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) { + AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + gSaveContext.magic = gSaveContext.magicCapacity; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) { + AMMO(ITEM_BOMBCHU) = 50; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) { + gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); + } + }); +} + extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void PatchCompasses() { @@ -1774,6 +1814,7 @@ void InitMods() { RegisterNoSwim(); RegisterNoWallet(); RegisterFishsanity(); + RegisterInfiniteUpgrades(); RegisterRandomizerCompasses(); NameTag_RegisterHooks(); RegisterFloorSwitchesHook(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index e99b6fd71..d6e2c2f9a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2058,6 +2058,54 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a fish-puller", /*german*/"", /*french*/"(canne à pêche)")}); // /*spanish*/(caña de pescar) + hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BOMB_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BULLET_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_STICK_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_NUT_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_MAGIC_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BOMBCHU_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_WALLET_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"", /*french*/"Epona"), // /*spanish*/a Epona { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 6d2e44fbf..514e81ce4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -845,6 +845,16 @@ void GenerateItemPool() { ctx->possibleIceTrapModels.push_back(RG_FISHING_POLE); } + if (ctx->GetOption(RSK_INFINITE_UPGRADES).Is(RO_INF_UPGRADES_PROGRESSIVE)) { + AddItemToMainPool(RG_PROGRESSIVE_BOMB_BAG); + AddItemToMainPool(RG_PROGRESSIVE_BOW); + AddItemToMainPool(RG_PROGRESSIVE_NUT_UPGRADE); + AddItemToMainPool(RG_PROGRESSIVE_SLINGSHOT); + AddItemToMainPool(RG_PROGRESSIVE_STICK_UPGRADE); + AddItemToMainPool(RG_PROGRESSIVE_MAGIC_METER); + AddItemToMainPool(RG_PROGRESSIVE_WALLET); + } + if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) { AddItemToMainPool(RG_MAGIC_BEAN_PACK); if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 4f94e517a..d5737d33d 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1113,6 +1113,24 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } + case VB_DRAW_AMMO_COUNT: { + s16 item = *static_cast(optionalArg); + // don't draw ammo count if you have the infinite upgrade + if ( + (item == ITEM_NUT && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) || + (item == ITEM_STICK && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) || + (item == ITEM_BOMB && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) || + ( + (item == ITEM_BOW || item == ITEM_BOW_ARROW_FIRE || item == ITEM_BOW_ARROW_ICE || item == ITEM_BOW_ARROW_LIGHT) && + Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER) + ) || + (item == ITEM_SLINGSHOT && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) || + (item == ITEM_BOMBCHU && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) + ) { + *should = false; + } + break; + } case VB_TRADE_TIMER_ODD_MUSHROOM: case VB_TRADE_TIMER_EYEDROPS: case VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 9be5551b8..2ffedbfeb 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -119,6 +119,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio RandomizerGet actual = RG_NONE; const bool tycoonWallet = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + const u8 infiniteUpgrades = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES); switch (randomizerGet) { case RG_PROGRESSIVE_STICK_UPGRADE: switch (CUR_UPG_VALUE(UPG_STICKS)) { @@ -128,12 +129,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio break; } case 1: - actual = RG_DEKU_STICK_CAPACITY_20; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_STICK_UPGRADE_INF; + } else { + actual = RG_DEKU_STICK_CAPACITY_20; + } break; case 2: - case 3: actual = RG_DEKU_STICK_CAPACITY_30; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_STICK_UPGRADE_INF; + } else { + actual = RG_DEKU_STICK_CAPACITY_30; + } + break; default: break; } @@ -146,12 +158,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio break; } case 1: - actual = RG_DEKU_NUT_CAPACITY_30; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_NUT_UPGRADE_INF; + } else { + actual = RG_DEKU_NUT_CAPACITY_30; + } break; case 2: - case 3: actual = RG_DEKU_NUT_CAPACITY_40; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_NUT_UPGRADE_INF; + } else { + actual = RG_DEKU_NUT_CAPACITY_40; + } + break; default: break; } @@ -162,12 +185,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_BOMB_BAG; break; case 1: - actual = RG_BIG_BOMB_BAG; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_BOMB_BAG_INF; + } else { + actual = RG_BIG_BOMB_BAG; + } break; case 2: - case 3: actual = RG_BIGGEST_BOMB_BAG; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_BOMB_BAG_INF; + } else { + actual = RG_BIGGEST_BOMB_BAG; + } + break; default: break; } @@ -178,12 +212,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_FAIRY_BOW; break; case 1: - actual = RG_BIG_QUIVER; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_QUIVER_INF; + } else { + actual = RG_BIG_QUIVER; + } break; case 2: - case 3: actual = RG_BIGGEST_QUIVER; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_QUIVER_INF; + } else { + actual = RG_BIGGEST_QUIVER; + } + break; default: break; } @@ -194,12 +239,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_FAIRY_SLINGSHOT; break; case 1: - actual = RG_BIG_BULLET_BAG; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_BULLET_BAG_INF; + } else { + actual = RG_BIG_BULLET_BAG; + } break; case 2: - case 3: actual = RG_BIGGEST_BULLET_BAG; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_BULLET_BAG_INF; + } else { + actual = RG_BIGGEST_BULLET_BAG; + } + break; default: break; } @@ -259,9 +315,16 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_GIANT_WALLET; break; case 2: - case 3: actual = tycoonWallet ? RG_TYCOON_WALLET : RG_GIANT_WALLET; break; + case 3: + case 4: + if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_WALLET_INF; + } else { + actual = tycoonWallet ? RG_TYCOON_WALLET : RG_GIANT_WALLET; + } + break; default: break; } @@ -289,9 +352,16 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_MAGIC_SINGLE; break; case 1: - case 2: actual = RG_MAGIC_DOUBLE; break; + case 2: + case 3: + if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_MAGIC_INF; + } else { + actual = RG_MAGIC_DOUBLE; + } + break; default: break; } @@ -299,6 +369,17 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio case RG_PROGRESSIVE_GORONSWORD: // todo progressive? actual = RG_BIGGORON_SWORD; break; + case RG_PROGRESSIVE_BOMBCHUS: + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + actual = RG_BOMBCHU_20; + } else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_BOMBCHU_INF; + } else if (AMMO(ITEM_BOMBCHU) < 5) { + actual = RG_BOMBCHU_10; + } else { + actual = RG_BOMBCHU_5; + } + break; default: actual = RG_NONE; break; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index b9bd9be22..7c86fcfd3 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -289,6 +289,15 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveWallet, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, &logic->ProgressiveBow, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, &logic->ProgressiveBombBag, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, &logic->ProgressiveBulletBag, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, &logic->noVariable, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, &logic->noVariable, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_MAGIC_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, &logic->ProgressiveMagic, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, &logic->Bombchus, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, &logic->ProgressiveWallet, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &logic->SkeletonKey, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index e5b0722f3..6b5ebc893 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -250,6 +250,11 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; + mOptionDescriptions[RSK_INFINITE_UPGRADES] = "Adds upgrades that hold infinite quanities of items (bombs, arrows, etc.)\n" + "\n" + "Progressive - The infinite upgrades are obtained after getting the last normal capacity upgrade\n" + "\n" + "Condensed Progressive - The infinite upgrades are obtained as the first capacity upgrade (doesn't apply to the infinite wallet or to infinite magic)"; mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG] = "Shuffles the deku stick bag into the item pool.\n" "\n" "The deku stick bag is required to hold deku sticks."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index faac02d84..b2c047e63 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -360,6 +360,13 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe // This is needed since Plentiful item pool also adds a third progressive wallet // but we should *not* get Tycoon's Wallet in that mode. bool tycoonWallet = GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + + // Same thing with the infinite upgrades, if we're not shuffling them + // and we're using the Plentiful item pool, we should prevent the infinite + // upgrades from being gotten + u8 infiniteUpgrades = GetRandoSettingValue(RSK_INFINITE_UPGRADES); + + u8 numWallets = 2 + (u8)tycoonWallet + (infiniteUpgrades != RO_INF_UPGRADES_OFF ? 1 : 0); switch (randoGet) { case RG_NONE: case RG_TRIFORCE: @@ -396,19 +403,25 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe // Inventory Items case RG_PROGRESSIVE_STICK_UPGRADE: - return CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_STICK_1: case RG_BUY_DEKU_STICK_1: return CUR_UPG_VALUE(UPG_STICKS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_NUT_UPGRADE: - return CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_NUTS_5: case RG_DEKU_NUTS_10: case RG_BUY_DEKU_NUTS_5: case RG_BUY_DEKU_NUTS_10: return CUR_UPG_VALUE(UPG_NUTS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_BOMB_BAG: - return CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_BOMBS_5: case RG_BOMBS_10: case RG_BOMBS_20: @@ -419,7 +432,9 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_BUY_BOMBS_30: return CUR_UPG_VALUE(UPG_BOMB_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_BOW: - return CUR_UPG_VALUE(UPG_QUIVER) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_QUIVER) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_ARROWS_5: case RG_ARROWS_10: case RG_ARROWS_30: @@ -428,7 +443,9 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_BUY_ARROWS_50: return CUR_UPG_VALUE(UPG_QUIVER) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_SLINGSHOT: - return CUR_UPG_VALUE(UPG_BULLET_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_BULLET_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_SEEDS_30: case RG_BUY_DEKU_SEEDS_30: return CUR_UPG_VALUE(UPG_BULLET_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; @@ -550,13 +567,15 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_PROGRESSIVE_STRENGTH: return CUR_UPG_VALUE(UPG_STRENGTH) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_WALLET: - return CUR_UPG_VALUE(UPG_WALLET) < (tycoonWallet ? 3 : 2) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return CUR_UPG_VALUE(UPG_WALLET) < numWallets ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_SCALE: return CUR_UPG_VALUE(UPG_SCALE) < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_MAGIC_METER: case RG_MAGIC_SINGLE: case RG_MAGIC_DOUBLE: - return gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_FISHING_POLE: return !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; @@ -716,6 +735,11 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem // This is needed since Plentiful item pool also adds a third progressive wallet // but we should *not* get Tycoon's Wallet in that mode. bool tycoonWallet = GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + + // Same thing with the infinite upgrades, if we're not shuffling them + //and we're using the Plentiful item pool, we should prevent the infinite + //upgrades from being gotten + u8 infiniteUpgrades = GetRandoSettingValue(RSK_INFINITE_UPGRADES); switch (randoGet) { case RG_NONE: return ogItemId; @@ -760,8 +784,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_STICK_UPGRADE_20; case 2: - case 3: return GI_STICK_UPGRADE_30; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_STICK_UPGRADE_INF : GI_STICK_UPGRADE_30; } case RG_PROGRESSIVE_NUT_UPGRADE: switch (CUR_UPG_VALUE(UPG_NUTS)) { @@ -769,8 +795,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_NUT_UPGRADE_30; case 2: - case 3: return GI_NUT_UPGRADE_40; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_NUT_UPGRADE_INF : GI_NUT_UPGRADE_40; } case RG_PROGRESSIVE_BOMB_BAG: switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { @@ -779,8 +807,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_BOMB_BAG_30; case 2: - case 3: return GI_BOMB_BAG_40; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_BOMB_BAG_INF : GI_BOMB_BAG_40; } case RG_BOMBS_5: case RG_BUY_BOMBS_525: @@ -801,8 +831,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_QUIVER_40; case 2: - case 3: return GI_QUIVER_50; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_QUIVER_INF : GI_QUIVER_50; } case RG_ARROWS_5: case RG_BUY_ARROWS_10: @@ -820,8 +852,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_BULLET_BAG_40; case 2: - case 3: return GI_BULLET_BAG_50; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_BULLET_BAG_INF : GI_BULLET_BAG_50; } case RG_DEKU_SEEDS_30: case RG_BUY_DEKU_SEEDS_30: @@ -843,6 +877,16 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case RG_BOMBCHU_20: case RG_BUY_BOMBCHU_20: return GI_BOMBCHUS_20; + case RG_PROGRESSIVE_BOMBCHUS: + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + return (GetItemID)RG_PROGRESSIVE_BOMBCHUS; + } else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + return (GetItemID)RG_BOMBCHU_INF; + } else if (AMMO(ITEM_BOMBCHU) < 5) { + return GI_BOMBCHUS_10; + } else { + return GI_BOMBCHUS_5; + } case RG_PROGRESSIVE_HOOKSHOT: switch (INV_CONTENT(ITEM_HOOKSHOT)) { case ITEM_NONE: @@ -959,8 +1003,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_WALLET_GIANT; case 2: + return tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_WALLET_INF : GI_WALLET_GIANT; case 3: - return tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : GI_WALLET_GIANT; + case 4: + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_WALLET_INF : tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : GI_WALLET_GIANT; } case RG_PROGRESSIVE_SCALE: if (!Flags_GetRandomizerInf(RAND_INF_CAN_SWIM)) { @@ -978,8 +1024,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 0: return (GetItemID)RG_MAGIC_SINGLE; case 1: - case 2: return (GetItemID)RG_MAGIC_DOUBLE; + case 2: + case 3: + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_MAGIC_INF : (GetItemID)RG_MAGIC_DOUBLE; } case RG_RECOVERY_HEART: @@ -1077,11 +1125,37 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_GOLD_SKULLTULA_TOKEN: case RG_PROGRESSIVE_HOOKSHOT: case RG_PROGRESSIVE_STRENGTH: + return true; case RG_PROGRESSIVE_BOMB_BAG: + if (CUR_UPG_VALUE(UPG_BOMB_BAG) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_BOW: + if (CUR_UPG_VALUE(UPG_QUIVER) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_SLINGSHOT: + if (CUR_UPG_VALUE(UPG_BULLET_BAG) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_NUT_UPGRADE: + if (CUR_UPG_VALUE(UPG_NUTS) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_STICK_UPGRADE: + if (CUR_UPG_VALUE(UPG_STICKS) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_OCARINA: case RG_PROGRESSIVE_GORONSWORD: case RG_EMPTY_BOTTLE: @@ -1103,6 +1177,9 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BOMBCHU_10: case RG_BOMBCHU_20: case RG_BOMBCHU_DROP: + return true; + case RG_PROGRESSIVE_BOMBCHUS: + return INV_CONTENT(ITEM_BOMBCHU) != ITEM_NONE && !GetRandoSettingValue(RSK_INFINITE_UPGRADES); case RG_ARROWS_5: case RG_ARROWS_10: case RG_ARROWS_30: @@ -2954,7 +3031,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ + const std::array getItemMessages = {{ GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", @@ -3226,6 +3303,14 @@ void Randomizer::CreateCustomMessages() { "Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), GIMESSAGE_UNTRANSLATED(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!"), GIMESSAGE_UNTRANSLATED(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!"), + GIMESSAGE_UNTRANSLATED(RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40, "You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!"), + GIMESSAGE_UNTRANSLATED(RG_QUIVER_INF, ITEM_QUIVER_50, "You got an %rInfinite Quiver%w!&Now you have %yinfinite arrows%w!"), + GIMESSAGE_UNTRANSLATED(RG_BULLET_BAG_INF, ITEM_BULLET_BAG_50, "You got an %rInfinite Bullet Bag%w!&Now you have %yinfinite&slingshot seeds%w!"), + GIMESSAGE_UNTRANSLATED(RG_STICK_UPGRADE_INF, ITEM_STICK, "You now have %yinfinite%w %rDeku Sticks%w!"), + GIMESSAGE_UNTRANSLATED(RG_NUT_UPGRADE_INF, ITEM_NUT, "You now have %yinfinite%w %rDeku Nuts%w!"), + GIMESSAGE_UNTRANSLATED(RG_MAGIC_INF, ITEM_MAGIC_LARGE, "You now have %yinfinite%w %rMagic%w!"), + GIMESSAGE_UNTRANSLATED(RG_BOMBCHU_INF, ITEM_BOMBCHU, "You now have %yinfinite%w %rBombchus%w!"), + GIMESSAGE_UNTRANSLATED(RG_WALLET_INF, ITEM_WALLET_GIANT, "You now have %yinfinite%w %rmoney%w!"), GIMESSAGE_UNTRANSLATED(RG_SKELETON_KEY, ITEM_KEY_SMALL, "You found the %rSkeleton Key%w!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_STICK_BAG, ITEM_STICK, "You found the %rDeku Stick Bag%w!&You can now hold deku sticks!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_NUT_BAG, ITEM_NUT, "You found the %rDeku Nut Bag%w!&You can now hold deku nuts!"), diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index e89059ecd..b423b5235 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1987,6 +1987,14 @@ typedef enum { RG_TYCOON_WALLET, RG_BRONZE_SCALE, RG_CHILD_WALLET, + RG_QUIVER_INF, + RG_BOMB_BAG_INF, + RG_BULLET_BAG_INF, + RG_STICK_UPGRADE_INF, + RG_NUT_UPGRADE_INF, + RG_MAGIC_INF, + RG_BOMBCHU_INF, + RG_WALLET_INF, RG_FAIRY_OCARINA, RG_OCARINA_OF_TIME, RG_BOMB_BAG, @@ -3201,6 +3209,14 @@ typedef enum { RHT_BUY_RED_POTION_40, RHT_BUY_RED_POTION_50, RHT_TRIFORCE, + RHT_QUIVER_INF, + RHT_BOMB_BAG_INF, + RHT_BULLET_BAG_INF, + RHT_STICK_UPGRADE_INF, + RHT_NUT_UPGRADE_INF, + RHT_MAGIC_INF, + RHT_BOMBCHU_INF, + RHT_WALLET_INF, RHT_HINT, RHT_TYCOON_WALLET, RHT_CHILD_WALLET, @@ -3715,6 +3731,7 @@ typedef enum { RSK_FISHSANITY_POND_COUNT, RSK_FISHSANITY_AGE_SPLIT, RSK_SHUFFLE_FISHING_POLE, + RSK_INFINITE_UPGRADES, RSK_SKELETON_KEY, RSK_SHUFFLE_DEKU_STICK_BAG, RSK_SHUFFLE_DEKU_NUT_BAG, @@ -3856,6 +3873,13 @@ typedef enum { RO_FISHSANITY_BOTH } RandoOptionsFishsanity; +//Infinite Upgrades settings (off, progressive, condensed progressive) +typedef enum { + RO_INF_UPGRADES_OFF, + RO_INF_UPGRADES_PROGRESSIVE, + RO_INF_UPGRADES_CONDENSED_PROGRESSIVE, +} RandoOptionInfiniteUpgrades; + //Any Dungeon Item (start with, vanilla, own dungeon, any dungeon, //overworld, anywhere) typedef enum { diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 72168f018..8a9e8be1f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -257,6 +257,15 @@ typedef enum { RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_5, + RAND_INF_HAS_INFINITE_QUIVER, + RAND_INF_HAS_INFINITE_BOMB_BAG, + RAND_INF_HAS_INFINITE_BULLET_BAG, + RAND_INF_HAS_INFINITE_STICK_UPGRADE, + RAND_INF_HAS_INFINITE_NUT_UPGRADE, + RAND_INF_HAS_INFINITE_MAGIC_METER, + RAND_INF_HAS_INFINITE_BOMBCHUS, + RAND_INF_HAS_INFINITE_MONEY, + RAND_INF_HAS_SKELETON_KEY, RAND_INF_LINKS_POCKET, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 28f341631..f3077cf3e 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -184,6 +184,7 @@ void Settings::CreateOptions() { // TODO: Compasses show rewards/woth, maps show dungeon mode mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); + mOptions[RSK_INFINITE_UPGRADES] = Option::U8("Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]); mOptions[RSK_SKELETON_KEY] = Option::Bool("Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]); mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); @@ -766,6 +767,7 @@ void Settings::CreateOptions() { &mOptions[RSK_ENABLE_BOMBCHU_DROPS], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE] = OptionGroup::SubGroup("Gameplay", { @@ -994,6 +996,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DAMAGE_MULTIPLIER], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], }); mOptionGroups[RSG_ITEM_POOL] = OptionGroup("Item Pool Settings", std::initializer_list({ @@ -1213,6 +1216,7 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, { "Miscellaneous Settings:Blue Fire Arrows", RSK_BLUE_FIRE_ARROWS }, { "Miscellaneous Settings:Sunlight Arrows", RSK_SUNLIGHT_ARROWS }, + { "Miscellaneous Settings:Infinite Upgrades", RSK_INFINITE_UPGRADES }, { "Miscellaneous Settings:Skeleton Key", RSK_SKELETON_KEY }, { "Timesaver Settings:Skip Child Zelda", RSK_SKIP_CHILD_ZELDA }, { "Start with Consumables", RSK_STARTING_CONSUMABLES }, @@ -2363,6 +2367,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SKULLS_SUNS_SONG: case RSK_BLUE_FIRE_ARROWS: case RSK_SUNLIGHT_ARROWS: + case RSK_INFINITE_UPGRADES: case RSK_SKELETON_KEY: case RSK_BOMBCHUS_IN_LOGIC: case RSK_TOT_ALTAR_HINT: diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 31b2a6d0b..0cfde00b7 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2768,6 +2768,8 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; AMMO(ITEM_BOMBCHU) = 20; + } else if (Randomizer_GetSettingValue(RSK_INFINITE_UPGRADES)) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS); } else { AMMO(ITEM_BOMBCHU) += AMMO(ITEM_BOMBCHU) < 5 ? 10 : 5; if (AMMO(ITEM_BOMBCHU) > 50) { @@ -2796,6 +2798,46 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { return Return_Item_Entry(giEntry, RG_NONE); } + if (item == RG_QUIVER_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BOMB_BAG_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BULLET_BAG_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_STICK_UPGRADE_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_NUT_UPGRADE_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_MAGIC_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BOMBCHU_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_WALLET_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY); + return Return_Item_Entry(giEntry, RG_NONE); + } + if (item == RG_SKELETON_KEY) { Flags_SetRandomizerInf(RAND_INF_HAS_SKELETON_KEY); return Return_Item_Entry(giEntry, RG_NONE); @@ -3578,21 +3620,23 @@ void Interface_UpdateMagicBar(PlayState* play) { break; case MAGIC_STATE_CONSUME: - gSaveContext.magic -= 2; - if (gSaveContext.magic <= 0) { - gSaveContext.magic = 0; - gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { - sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); - } else { - sMagicBorder = sMagicBorder_ori; - } - } else if (gSaveContext.magic == gSaveContext.magicTarget) { - gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { - sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); - } else { - sMagicBorder = sMagicBorder_ori; + if (!Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + gSaveContext.magic -= 2; + if (gSaveContext.magic <= 0) { + gSaveContext.magic = 0; + gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } else { + sMagicBorder = sMagicBorder_ori; + } + } else if (gSaveContext.magic == gSaveContext.magicTarget) { + gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } else { + sMagicBorder = sMagicBorder_ori; + } } } case MAGIC_STATE_METER_FLASH_1: @@ -3756,6 +3800,7 @@ void Interface_DrawMagicBar(PlayState* play) { s16 magicBarY; Color_RGB8 magicbar_yellow = {250,250,0}; //Magic bar being used Color_RGB8 magicbar_green = {R_MAGIC_FILL_COLOR(0),R_MAGIC_FILL_COLOR(1),R_MAGIC_FILL_COLOR(2)}; //Magic bar fill + Color_RGB8 magicbar_blue = {0,0,200};//Infinite magic bar if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicActive.Changed"), 0)) { magicbar_yellow = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicActive.Value"), magicbar_yellow); @@ -3763,6 +3808,9 @@ void Interface_DrawMagicBar(PlayState* play) { if (CVarGetInteger(CVAR_COSMETIC("Consumable.Magic.Changed"), 0)) { magicbar_green = CVarGetColor24(CVAR_COSMETIC("Consumable.Magic.Value"), magicbar_green); } + if (CVarGetInteger("gCosmetics.Consumable_MagicInfinite.Changed", 0)) { + magicbar_blue = CVarGetColor24("gCosmetics.Consumable_MagicInfinite.Value", magicbar_blue); + } OPEN_DISPS(play->state.gfxCtx); @@ -3870,14 +3918,26 @@ void Interface_DrawMagicBar(PlayState* play) { // Fill the rest of the bar with the normal magic color gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + // Blue magic + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_blue.r, magicbar_blue.g, magicbar_blue.b, interfaceCtx->magicAlpha); + } else { + // Green magic (default) + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + } gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2, (rMagicFillX + gSaveContext.magicTarget) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } else { // Fill the whole bar with the normal magic color - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + // Blue magic + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_blue.r, magicbar_blue.g, magicbar_blue.b, interfaceCtx->magicAlpha); + } else { + // Green magic (default) + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + } gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicMeterFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -5021,10 +5081,25 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { i = gSaveContext.equips.buttonItems[button]; - if ((i == ITEM_STICK) || (i == ITEM_NUT) || (i == ITEM_BOMB) || (i == ITEM_BOW) || - ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_SLINGSHOT) || (i == ITEM_BOMBCHU) || - (i == ITEM_BEAN)) { - + if ( + GameInteractor_Should( + VB_DRAW_AMMO_COUNT, + ( + (i == ITEM_STICK) || + (i == ITEM_NUT) || + (i == ITEM_BOMB) || + (i == ITEM_BOW) || + ( + (i >= ITEM_BOW_ARROW_FIRE) && + (i <= ITEM_BOW_ARROW_LIGHT) + ) || + (i == ITEM_SLINGSHOT) || + (i == ITEM_BOMBCHU) || + (i == ITEM_BEAN) + ), + &i + ) + ) { if ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) { i = ITEM_BOW; } @@ -5297,8 +5372,8 @@ void Interface_Draw(PlayState* play) { if (fullUi) { s16 PosX_RC; s16 PosY_RC; - //when not having a wallet in rando, don't calculate the ruppe icon - if (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { + //when not having a wallet (or infinite money) in rando, don't calculate the ruppe icon + if (!IS_RANDO || (Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) && !Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY))) { // Rupee Icon if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { switch (CUR_UPG_VALUE(UPG_WALLET)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 83b734156..d34ce4d8a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -6,6 +6,9 @@ #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + u8 gAmmoItems[] = { ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, ITEM_BOMBCHU, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_BEAN, ITEM_NONE, @@ -37,6 +40,10 @@ s8 ItemInSlotUsesAmmo(s16 slot) { } void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item, int slot) { + if (!GameInteractor_Should(VB_DRAW_AMMO_COUNT, true, &item)) { + return; + } + s16 ammo; s16 i; From c68cecec71803e5fe8102aa06bdff61161cc1236 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:56:44 +0200 Subject: [PATCH 284/300] Rando: Shuffle Hyrule Loach (Rando V3) (#3805) * Shuffle Hyrule Loach * Remove rando specific loach text override * Remove duplicated enhancement from fishsanity * Re-run Build * Re-run Build * Changed to be an option within fishsanity * Rename cvar and fix check tracker * Fix build * Re-run build * Re-re-run build * Update z_fishing.c * Fix AllHyruleLoaches * Fix static data * Fix hint spacing * Restrict loach hint to "Shuffle only Hyrule Loach" * Update settings.cpp * Address review --- .../custom-message/CustomMessageTypes.h | 8 ++ .../Enhancements/debugger/debugSaveEditor.h | 2 + .../randomizer/3drando/hint_list.cpp | 3 + .../randomizer/3drando/item_pool.cpp | 6 ++ .../location_access/locacc_hyrule_field.cpp | 73 ++++++++++--------- .../Enhancements/randomizer/location_list.cpp | 2 + .../randomizer/option_descriptions.cpp | 3 + .../Enhancements/randomizer/randomizer.cpp | 2 +- .../Enhancements/randomizer/randomizerTypes.h | 7 +- .../randomizer/randomizer_check_objects.cpp | 2 + .../randomizer/randomizer_check_tracker.cpp | 5 ++ .../Enhancements/randomizer/randomizer_inf.h | 2 + soh/soh/Enhancements/randomizer/settings.cpp | 21 +++++- .../Enhancements/randomizer/static_data.cpp | 2 + soh/soh/OTRGlobals.cpp | 16 +++- soh/soh/SohMenuBar.cpp | 3 +- .../overlays/actors/ovl_Fishing/z_fishing.c | 55 +++++++------- 17 files changed, 144 insertions(+), 68 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 6d25d9f8a..93681ebe9 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -138,7 +138,15 @@ typedef enum { TEXT_BEAN_SALESMAN_SOLD_OUT = 0x406B, TEXT_BEAN_SALESMAN_WANT_TO_PLANT = 0x406C, TEXT_FISHING_POND_START = 0x407B, + TEXT_FISHING_TALK_ABOUT_SOMETHING = 0x4088, + TEXT_FISHING_TRY_ANOTHER_LURE = 0x408D, + TEXT_FISHING_SECRETS = 0x408E, + TEXT_FISHING_GOOD_FISHERMAN = 0x408F, TEXT_FISHING_POND_START_MET = 0x4093, + TEXT_FISHING_DIFFERENT_POND = 0x4094, + TEXT_FISHING_SCRATCHING = 0x4095, + TEXT_FISHING_CLOUDY = 0x4096, + TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE = 0x40AF, TEXT_DAMPES_DIARY = 0x5003, TEXT_GRANNYS_SHOP = 0x500C, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK = 0x5036, diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 4199b7172..c3e01b657 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -510,6 +510,8 @@ const std::vector flagTables = { { RAND_INF_HAS_OCARINA_C_LEFT, "RAND_INF_HAS_OCARINA_C_LEFT"}, { RAND_INF_HAS_OCARINA_C_RIGHT, "RAND_INF_HAS_OCARINA_C_RIGHT"}, + { RAND_INF_CAUGHT_LOACH, "RAND_INF_CAUGHT_LOACH" }, + { RAND_INF_CAN_SWIM, "RAND_INF_CAN_SWIM" }, { RAND_INF_HAS_WALLET, "RAND_INF_HAS_WALLET" }, diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 3d0ae5940..ca60835e6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2752,6 +2752,9 @@ void StaticData::HintTable_Init() { /*french*/ "As-tu récemment ressenti une vague de #puissance magique#? Un mystérieux hibou m'a dit qu'elle provenait du #[[1]]#. Tu devrais aller y jeter un coup d'oeil, @!\x0B", {QM_GREEN, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); + hintTextTable[RHT_LOACH_HINT] = HintText(CustomMessage("What?^You wanna know about the&%rHyrule Loach%w?^It's a big fish, but it's so rare that I'll give my %g[[1]]%w to anyone who catches it. Seriously!", + {QM_RED})); + hintTextTable[RHT_FISHING_POLE_HINT] = HintText(CustomMessage("^If I remember correctly, I lost it somewhere in #[[1]]#...&Let me know if you find it!", {QM_RED})); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 514e81ce4..fd78f1843 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -836,6 +836,12 @@ void GenerateItemPool() { } else { PlaceVanillaOverworldFish(); } + + if (fsMode.Is(RO_FISHSANITY_HYRULE_LOACH)) { + AddItemToMainPool(RG_PURPLE_RUPEE); + } else { + ctx->PlaceItemInLocation(RC_LH_HYRULE_LOACH, RG_PURPLE_RUPEE, false, true); + } } else { PlaceVanillaOverworldFish(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp index d5d966308..860b90e8b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp @@ -167,42 +167,43 @@ void AreaTable_Init_HyruleField() { // TODO: should some of these helpers be done via events instead? areaTable[RR_LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", RA_NONE, DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_LH_CHILD_FISHING, logic->CanFish && logic->IsChild), - LOCATION(RC_LH_CHILD_FISH_1, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_2, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_3, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_4, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_5, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_6, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_7, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_8, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_9, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_10, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_11, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_12, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_13, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_14, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_FISH_15, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_LOACH_1, logic->CanGetChildFish), - LOCATION(RC_LH_CHILD_LOACH_2, logic->CanGetChildFish), - LOCATION(RC_LH_ADULT_FISHING, logic->CanFish && logic->IsAdult), - LOCATION(RC_LH_ADULT_FISH_1, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_2, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_3, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_4, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_5, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_6, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_7, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_8, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_9, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_10, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_11, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_12, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_13, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_14, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_FISH_15, logic->CanGetAdultFish), - LOCATION(RC_LH_ADULT_LOACH, logic->CanGetAdultFish), - LOCATION(RC_FISHING_POLE_HINT,true), + LOCATION(RC_LH_CHILD_FISHING, logic->CanFish && logic->IsChild), + LOCATION(RC_LH_CHILD_FISH_1, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_2, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_3, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_4, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_5, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_6, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_7, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_8, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_9, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_10, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_11, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_12, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_13, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_14, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_FISH_15, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_LOACH_1, logic->CanGetChildFish), + LOCATION(RC_LH_CHILD_LOACH_2, logic->CanGetChildFish), + LOCATION(RC_LH_ADULT_FISHING, logic->CanFish && logic->IsAdult), + LOCATION(RC_LH_ADULT_FISH_1, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_2, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_3, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_4, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_5, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_6, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_7, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_8, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_9, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_10, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_11, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_12, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_13, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_14, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_FISH_15, logic->CanGetAdultFish), + LOCATION(RC_LH_ADULT_LOACH, logic->CanGetAdultFish), + LOCATION(RC_LH_HYRULE_LOACH, logic->CanFish), + LOCATION(RC_FISHING_POLE_HINT, true), }, { //Exits Entrance(RR_LH_FISHING_ISLAND, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 987565352..ad09e683d 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -157,6 +157,7 @@ std::vector Rando::StaticData::overworldLocations = { // Lake Hylia RC_LH_CHILD_FISHING, RC_LH_ADULT_FISHING, + RC_LH_HYRULE_LOACH, RC_LH_LAB_DIVE, RC_LH_TRADE_FROG, RC_LH_UNDERWATER_ITEM, @@ -643,6 +644,7 @@ void Rando::StaticData::InitLocationTable() { // // Lake Hylia locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_HYRULE_LOACH] = Location::Base(RC_LH_HYRULE_LOACH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x00, "Hyrule Loach Reward", RHT_LH_HYRULE_LOACH, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CAUGHT_LOACH), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 6b5ebc893..36c270642 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -279,6 +279,7 @@ void Settings::CreateOptionDescriptions() { "Affordable prices per tier: starter = 10, adult = 105, giant = 205, tycoon = 505\n\n" "Use this to enable wallet tier locking, but make shop items not as expensive as they could be."; mOptionDescriptions[RSK_FISHSANITY] = "Off - Fish will not be shuffled. No changes will be made to fishing behavior.\n\n" + "Shuffle only Hyrule Loach - Allows you to earn an item by catching the hyrule loach at the fishing pond and giving it to the owner.\n\n" "Shuffle Fishing Pond - The fishing pond's fish will be shuffled. Catching a fish in the fishing pond will grant a reward.\n\n" "Shuffle Overworld Fish - Fish in generic grottos and Zora's Domain will be shuffled. Catching a fish in a bottle will give a reward.\n\n" "Shuffle Both - Both overworld fish and fish in the fishing pond will be shuffled."; @@ -526,6 +527,8 @@ void Settings::CreateOptionDescriptions() { "Reading the diary of Dampé the gravekeeper as adult will tell you the location of one of the Hookshots."; mOptionDescriptions[RSK_GREG_HINT] = "Talking to the chest game owner after buying a key will tell you the location of Greg the Green Rupee."; + mOptionDescriptions[RSK_LOACH_HINT] = + "Talking to the fishing pond owner and asking to talk about something will tell you what's the reward for the Hyrule Loach."; mOptionDescriptions[RSK_SARIA_HINT] = "Talking to Saria either in person or through Saria's Song will tell you the " "location of a progressive magic meter."; mOptionDescriptions[RSK_FISHING_POLE_HINT] = "Talking to the fishing pond owner without the fishing pole will tell you its location."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b2c047e63..01b3f49c9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -86,7 +86,7 @@ static const char* englishRupeeNames[171] = { "Frog Coins", "Gald", "Gekz", "Gems", "Geo", "Gil", "Glimmer", "Glitches", "Gold", "Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Gummybears", "Hell", - "Hylian Loaches", "Ice Traps", "ISK", "Jiggies", "KF7 Ammo", + "Hyrule Loaches", "Ice Traps", "ISK", "Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", "Leaves ", "Lemmings", "Lien", "Lira", "Lumber", "Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", "Meat Stacks", "Medaparts", diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index b423b5235..1b772367d 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -945,6 +945,7 @@ typedef enum { RC_LH_CHILD_LOACH_1, RC_LH_CHILD_LOACH_2, RC_LH_ADULT_FISHING, + RC_LH_HYRULE_LOACH, RC_LH_ADULT_FISH_1, RC_LH_ADULT_FISH_2, RC_LH_ADULT_FISH_3, @@ -2076,6 +2077,7 @@ typedef enum { RH_ALTAR_CHILD, RH_ALTAR_ADULT, RH_SARIA_HINT, + RH_LOACH_HINT, RH_FISHING_POLE, RH_MINUET_WARP_LOC, RH_BOLERO_WARP_LOC, @@ -3448,6 +3450,7 @@ typedef enum { RHT_GREG_HINT, RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT, + RHT_LOACH_HINT, RHT_FISHING_POLE_HINT, // Static Entrance Hints RHT_WARP_SONG, @@ -3625,6 +3628,7 @@ typedef enum { RSK_SHEIK_LA_HINT, RSK_DAMPES_DIARY_HINT, RSK_GREG_HINT, + RSK_LOACH_HINT, RSK_SARIA_HINT, RSK_FROGS_HINT, RSK_OOT_HINT, @@ -3865,9 +3869,10 @@ typedef enum { RO_BOSS_SOULS_ON_PLUS_GANON, } RandoOptionBossSouls; -//Fishsanity settings (off, pond only, grottos only, both) +//Fishsanity settings (off, loach only, pond only, grottos only, both) typedef enum { RO_FISHSANITY_OFF, + RO_FISHSANITY_HYRULE_LOACH, RO_FISHSANITY_POND, RO_FISHSANITY_OVERWORLD, RO_FISHSANITY_BOTH diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index ddedd5b53..3b5eed450 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -161,6 +161,8 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), RO_GENERIC_NO)) && (location.GetRandomizerCheck() != RC_KF_KOKIRI_SWORD_CHEST || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), RO_GENERIC_NO)) && + (location.GetRandomizerCheck() != RC_LH_HYRULE_LOACH || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_GENERIC_NO) == RO_FISHSANITY_HYRULE_LOACH) && (location.GetRandomizerCheck() != RC_ZR_MAGIC_BEAN_SALESMAN || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), RO_GENERIC_NO)) && (location.GetRandomizerCheck() != RC_HC_MALON_EGG || diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 76c293950..de46a4496 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -65,6 +65,7 @@ bool showCows; bool showAdultTrade; bool showKokiriSword; bool showMasterSword; +bool showHyruleLoach; bool showWeirdEgg; bool showGerudoCard; bool showFrogSongRupees; @@ -1167,6 +1168,9 @@ void LoadSettings() { showMasterSword = IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MASTER_SWORD) == RO_GENERIC_YES : true; + showHyruleLoach = IS_RANDO ? + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY) == RO_FISHSANITY_HYRULE_LOACH + : false; showWeirdEgg = IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_WEIRD_EGG) == RO_GENERIC_YES : true; @@ -1287,6 +1291,7 @@ bool IsCheckShuffled(RandomizerCheck rc) { ) && (rc != RC_KF_KOKIRI_SWORD_CHEST || showKokiriSword) && (rc != RC_TOT_MASTER_SWORD || showMasterSword) && + (rc != RC_LH_HYRULE_LOACH || showHyruleLoach) && (rc != RC_ZR_MAGIC_BEAN_SALESMAN || showBeans) && (rc != RC_HC_MALON_EGG || showWeirdEgg) && (loc->GetRCType() != RCTYPE_FROG_SONG || showFrogSongRupees) && diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8a9e8be1f..8d3e96239 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -202,6 +202,8 @@ typedef enum { RAND_INF_HAS_OCARINA_C_LEFT, RAND_INF_HAS_OCARINA_C_RIGHT, + RAND_INF_CAUGHT_LOACH, + RAND_INF_CAN_SWIM, RAND_INF_HAS_WALLET, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index f3077cf3e..f3f860800 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -122,7 +122,7 @@ void Settings::CreateOptions() { mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox); mOptions[RSK_SHUFFLE_DEKU_STICK_BAG] = Option::Bool("Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); mOptions[RSK_SHUFFLE_DEKU_NUT_BAG] = Option::Bool("Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF); - mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); + mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF); mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE); mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]); mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); @@ -163,6 +163,7 @@ void Settings::CreateOptions() { mOptions[RSK_SHEIK_LA_HINT] = Option::Bool("Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SheikLAHint"), mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE); mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", CVAR_RANDOMIZER_SETTING("DampeHint"), mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE); mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE); + mOptions[RSK_LOACH_HINT] = Option::Bool("Hyrule Loach Hint", CVAR_RANDOMIZER_SETTING("LoachHint"), mOptionDescriptions[RSK_LOACH_HINT], IMFLAG_NONE); mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE); mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE); mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE); @@ -738,6 +739,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHEIK_LA_HINT], &mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT], + &mOptions[RSK_LOACH_HINT], &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], &mOptions[RSK_OOT_HINT], @@ -974,6 +976,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHEIK_LA_HINT], &mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT], + &mOptions[RSK_LOACH_HINT], &mOptions[RSK_SARIA_HINT], &mOptions[RSK_FROGS_HINT], &mOptions[RSK_OOT_HINT], @@ -1198,6 +1201,7 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Sheik Light Arrow Hint", RSK_SHEIK_LA_HINT }, { "Miscellaneous Settings:Dampe's Diary Hint", RSK_DAMPES_DIARY_HINT }, { "Miscellaneous Settings:Greg the Rupee Hint", RSK_GREG_HINT }, + { "Miscellaneous Settings:Hyrule Loach Hint", RSK_LOACH_HINT }, { "Miscellaneous Settings:Saria's Hint", RSK_SARIA_HINT }, { "Miscellaneous Settings:Frog Ocarina Game Hint", RSK_FROGS_HINT }, { "Miscellaneous Settings:Ocarina of Time Hint", RSK_OOT_HINT }, @@ -1763,16 +1767,22 @@ void Settings::UpdateOptionProperties() { if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), RO_GENERIC_OFF)) { mOptions[RSK_MALON_HINT].Enable(); - } else { + } else { mOptions[RSK_MALON_HINT].Disable("Malon's hint points to a cow, so requires cows to be shuffled."); } if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), RO_GENERIC_OFF)) { mOptions[RSK_KAK_100_SKULLS_HINT].Enable(); - } else { + } else { mOptions[RSK_KAK_100_SKULLS_HINT].Disable("There is no point to hinting 100 skulls if it is not shuffled"); } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_OFF) == RO_FISHSANITY_HYRULE_LOACH) { + mOptions[RSK_LOACH_HINT].Enable(); + } else { + mOptions[RSK_LOACH_HINT].Disable("Loach hint is only avaliable with \"Fishsanity\" set to \"Shuffle only Hyrule Loach\"\nas that's the only setting where you present the loach to the fishing pond owner"); + } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 7) == 0) { mOptions[RSK_CHICKENS_HINT].Disable("Anju will just give you the item instead with 0 chickens"); } else { @@ -2125,6 +2135,10 @@ void Settings::FinalizeSettings(const std::set& excludedLocatio mOptions[RSK_KAK_100_SKULLS_HINT].SetSelectedIndex(RO_GENERIC_OFF); } + if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) { + mOptions[RSK_LOACH_HINT].SetSelectedIndex(RO_FISHSANITY_OFF); + } + if (mOptions[RSK_CUCCO_COUNT].Is(0)) { mOptions[RSK_CHICKENS_HINT].SetSelectedIndex(RO_GENERIC_OFF); } @@ -2375,6 +2389,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SHEIK_LA_HINT: case RSK_DAMPES_DIARY_HINT: case RSK_GREG_HINT: + case RSK_LOACH_HINT: case RSK_SARIA_HINT: case RSK_FROGS_HINT: case RSK_OOT_HINT: diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index f413a86e0..5a091552b 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -71,6 +71,7 @@ std::unordered_map StaticData::hintNames = { {RH_ALTAR_CHILD, CustomMessage("ToT Altar as Child")}, {RH_ALTAR_ADULT, CustomMessage("ToT Altar as Adult")}, {RH_SARIA_HINT, CustomMessage("Saria's Magic Hint")}, + {RH_LOACH_HINT, CustomMessage("Loach Hint")}, {RH_FISHING_POLE, CustomMessage("Fishing Pole Hint")}, {RH_MINUET_WARP_LOC, CustomMessage("Minuet of Forest Destination")}, {RH_BOLERO_WARP_LOC, CustomMessage("Bolero of Fire Destination")}, @@ -199,6 +200,7 @@ std::unordered_map StaticData::staticHintInfoMap {RH_DAMPES_DIARY, StaticHintInfo(HINT_TYPE_AREA, {RHT_DAMPE_DIARY}, RSK_DAMPES_DIARY_HINT, true, {}, {RG_PROGRESSIVE_HOOKSHOT}, {RC_DAMPE_HINT})}, {RH_GREG_RUPEE, StaticHintInfo(HINT_TYPE_AREA, {RHT_GREG_HINT}, RSK_GREG_HINT, true, {}, {RG_GREG_RUPEE}, {RC_GREG_HINT})}, {RH_SARIA_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT}, RSK_SARIA_HINT, true, {}, {RG_PROGRESSIVE_MAGIC_METER}, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, true)}, + {RH_LOACH_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_LOACH_HINT}, RSK_LOACH_HINT, true, {RC_LH_HYRULE_LOACH})}, {RH_FISHING_POLE, StaticHintInfo(HINT_TYPE_AREA, {RHT_FISHING_POLE_HINT}, RSK_FISHING_POLE_HINT, true, {}, {RG_FISHING_POLE}, {RC_FISHING_POLE_HINT}, true)}, {RH_MEDIGORON, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_MEDIGORON_HINT}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_GC_MEDIGORON})}, {RH_GRANNY, StaticHintInfo(HINT_TYPE_MERCHANT, {RHT_GRANNY_HINT}, RSK_SHUFFLE_MERCHANTS, (uint8_t)RO_SHUFFLE_MERCHANTS_ON_HINT, {RC_KAK_GRANNYS_SHOP})}, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 18da01c2c..43f3e2f00 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2707,7 +2707,21 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { else if (textId == TEXT_FROGS_UNDERWATER && ctx->GetOption(RSK_FROGS_HINT)) { messageEntry = ctx->GetHint(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT), TEXTBOX_TYPE_BLUE; } - else if ((textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET) && + else if ( + Randomizer_GetSettingValue(RSK_LOACH_HINT) && + ( + textId == TEXT_FISHING_CLOUDY || + textId == TEXT_FISHING_TRY_ANOTHER_LURE || + textId == TEXT_FISHING_SECRETS || + textId == TEXT_FISHING_GOOD_FISHERMAN || + textId == TEXT_FISHING_DIFFERENT_POND || + textId == TEXT_FISHING_SCRATCHING || + textId == TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE + ) + ) { + messageEntry = ctx->GetHint(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if ((textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET) && ctx->GetOption(RSK_SHUFFLE_FISHING_POLE) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { messageEntry = OTRGlobals::Instance->gRandomizer->GetFishingPondOwnerMessage(textId); } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 587e2d0c1..8adeaa429 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -924,7 +924,6 @@ void DrawEnhancementsMenu() { } UIWidgets::Spacer(0); - if (ImGui::BeginMenu("Fishing")) { UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeFishing")); UIWidgets::Tooltip("Turn on/off changes to the fishing behavior"); @@ -944,6 +943,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child"); UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6, 13, "", 13, true, true, false, disabled, disabledTooltip); UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); + UIWidgets::PaddedEnhancementCheckbox("All fish are Hyrule Loaches", CVAR_ENHANCEMENT("AllHyruleLoaches"), true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Every fish in the fishing pond will always be a Hyrule Loach"); ImGui::EndMenu(); } UIWidgets::Spacer(0); diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index a0ead103c..b3be105dd 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -17,6 +17,7 @@ #define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface #define IS_FISHSANITY (IS_RANDO && Randomizer_GetPondFishShuffled()) #define FISHID(params) (Randomizer_IdentifyFish(play->sceneNum, params)) +bool getShouldSpawnLoaches(); void Fishing_Init(Actor* thisx, PlayState* play); void Fishing_Destroy(Actor* thisx, PlayState* play); @@ -26,8 +27,6 @@ void Fishing_DrawFish(Actor* thisx, PlayState* play); void Fishing_DrawOwner(Actor* thisx, PlayState* play); void Fishing_Reset(void); -bool getShouldSpawnLoaches(); - typedef struct { /* 0x00 */ u8 isLoach; /* 0x02 */ Vec3s pos; @@ -436,6 +435,10 @@ static Vec3f sStreamSoundProjectedPos; static s16 sFishOnHandParams; static Color_RGBA16 fsPulseColor = { 30, 240, 200 }; +u8 AllHyruleLoaches() { + return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0); +} + void Fishing_SetColliderElement(s32 index, ColliderJntSph* collider, Vec3f* pos, f32 scale) { collider->elements[index].dim.worldSphere.center.x = pos->x; collider->elements[index].dim.worldSphere.center.y = pos->y; @@ -1001,7 +1004,7 @@ void Fishing_Init(Actor* thisx, PlayState* play2) { sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i, true); } } else { - if ((thisx->params < (EN_FISH_PARAM + 15)) || (thisx->params == EN_FISH_AQUARIUM)) { + if ((thisx->params < (EN_FISH_PARAM + 15) && !AllHyruleLoaches()) || (thisx->params == EN_FISH_AQUARIUM)) { SkelAnime_InitFlex(play, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, NULL, NULL, 0); Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f); } else { @@ -2847,7 +2850,7 @@ void Fishing_FishLeapSfx(Fishing* this, u8 outOfWater) { s16 sfxId; u8 length; - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { length = this->fishLength; } else { length = 2.0f * this->fishLength; @@ -2992,7 +2995,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { this->actor.uncullZoneForward = 700.0f; this->actor.uncullZoneScale = 50.0f; - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { playerSpeedMod = (player->actor.speedXZ * 0.15f) + 0.25f; } else { playerSpeedMod = (player->actor.speedXZ * 0.3f) + 0.25f; @@ -3054,7 +3057,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { Math_ApproachS(&this->fishLimbDRotZDelta, 0, 5, 0x1F4); - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { Actor_SetScale(&this->actor, this->fishLength * 15.0f * 0.00001f); this->fishLimbRotPhase += this->fishLimbRotPhaseStep; @@ -3223,7 +3226,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { break; case 1: - if (this->isLoach == 1) { + if (this->isLoach == 1 || AllHyruleLoaches()) { this->fishState = -1; this->unk_1A4 = 20000; this->unk_1A2 = 20000; @@ -3376,7 +3379,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { if (sLureEquipped == FS_LURE_SINKING) { this->fishTargetPos.y = sLurePos.y; - } else if (this->isLoach == 0) { + } else if (this->isLoach == 0 && !AllHyruleLoaches()) { this->fishTargetPos.y = sLurePos.y - 15.0f; } else { this->fishTargetPos.y = sLurePos.y - 5.0f; @@ -3451,8 +3454,8 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { } if (getGuaranteeBite() == 1 || ((this->timerArray[0] == 1) || (Rand_ZeroOne() < chance)) && - ((Rand_ZeroOne() < (this->perception * multiplier)) || ((this->isLoach + 1) == KREG(69)))) { - if (this->isLoach == 0) { + ((Rand_ZeroOne() < (this->perception * multiplier)) || (((this->isLoach || AllHyruleLoaches()) + 1) == KREG(69)))) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { this->fishState = 3; this->unk_190 = 1.2f; this->unk_194 = 5000.0f; @@ -3673,7 +3676,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_ENEMY | 0x800); sFishingMusicDelay = 0; - if (this->isLoach == 1) { + if (this->isLoach == 1 || AllHyruleLoaches()) { rumbleStrength = (this->fishLength * 3.0f) + 120.0f; } else { rumbleStrength = (2.0f * this->fishLength) + 120.0f; @@ -3776,7 +3779,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { Math_ApproachF(&this->actor.speedXZ, 5.0f, 1.0f, 0.5f); } - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { sRodReelingSpeed = 1.0f - (this->fishLength * 0.00899f); } else { sRodReelingSpeed = 1.0f - (this->fishLength * 0.00899f * 1.4f); @@ -3792,7 +3795,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { this->unk_190 = 1.0f; this->unk_194 = 4500.0f; - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { sRodReelingSpeed = 1.3f - (this->fishLength * 0.00899f); } else { sRodReelingSpeed = 1.3f - (this->fishLength * 0.00899f * 1.4f); @@ -3946,7 +3949,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_HEART_GET | 0x900); sFishingCaughtTextDelay = 40; - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { sFishLengthToWeigh = this->fishLength; if (sFishLengthToWeigh >= 75) { @@ -3993,13 +3996,13 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { if (play->msgCtx.choiceIndex == 0) { if (sFishOnHandLength == 0.0f) { sFishOnHandLength = this->fishLength; - sFishOnHandIsLoach = this->isLoach; + sFishOnHandIsLoach = (this->isLoach || AllHyruleLoaches()); sLureCaughtWith = sLureEquipped; if (IS_FISHSANITY) { sFishOnHandParams = this->fishsanityParams; } Actor_Kill(&this->actor); - } else if (getShouldConfirmKeep() && (this->isLoach == 0) && (sFishOnHandIsLoach == 0) && + } else if (getShouldConfirmKeep() && (this->isLoach == 0 && !AllHyruleLoaches()) && (sFishOnHandIsLoach == 0) && ((s16)this->fishLength < (s16)sFishOnHandLength)) { this->keepState = 1; this->timerArray[0] = 0x3C; @@ -4061,7 +4064,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) { this->unk_194 = 2000.0f; SkelAnime_Free(&this->skelAnime, play); - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { SkelAnime_InitFlex(play, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, 0, 0, 0); Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f); } else { @@ -4397,7 +4400,7 @@ void Fishing_DrawFish(Actor* thisx, PlayState* play) { Matrix_RotateZ(((this->unk_164 + this->actor.shape.rot.z) / 32768.0f) * M_PI, MTXMODE_APPLY); Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); - if (this->isLoach == 0) { + if (this->isLoach == 0 && !AllHyruleLoaches()) { Matrix_RotateY((this->fishLimb23RotYDelta * (M_PI / 32768)) - (M_PI / 2), MTXMODE_APPLY); Matrix_Translate(0.0f, 0.0f, this->fishLimb23RotYDelta * 10.0f * 0.01f, MTXMODE_APPLY); @@ -4998,7 +5001,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { if (sFishOnHandLength == 0.0f) { this->actor.textId = 0x408C; this->stateAndTimer = 20; - } else if (sFishOnHandIsLoach == 0 && !IS_RANDO) { + } else if (sFishOnHandIsLoach == 0) { sFishLengthToWeigh = sFishOnHandLength; if ((s16)sFishingRecordLength < (s16)sFishOnHandLength) { if (sLureCaughtWith == FS_LURE_SINKING) { @@ -5011,14 +5014,10 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { this->actor.textId = 0x408B; this->stateAndTimer = 20; } - } else if (!IS_RANDO) { + } else { this->actor.textId = 0x409B; this->stateAndTimer = 11; } - else { - this->actor.textId = 0x4086; - this->stateAndTimer = 11; - } Message_ContinueTextbox(play, this->actor.textId); break; case 1: @@ -5154,7 +5153,13 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { } } } else { - getItemId = GI_RUPEE_PURPLE; + if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_CAUGHT_LOACH)) { + Flags_SetRandomizerInf(RAND_INF_CAUGHT_LOACH); + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_HYRULE_LOACH, GI_RUPEE_PURPLE); + getItemId = getItemEntry.getItemId; + } else { + getItemId = GI_RUPEE_PURPLE; + } sFishOnHandLength = 0.0f; // doesn't record loach } From e66dada09dee7ff039bf1a82969441eedd5c5f2e Mon Sep 17 00:00:00 2001 From: Archez Date: Tue, 23 Jul 2024 21:31:01 -0400 Subject: [PATCH 285/300] Fix grotto handling with the skip intro timesaver (#4252) --- .../TimeSavers/SkipCutscene/SkipIntro.cpp | 56 ++++++++++--------- .../randomizer/randomizer_entrance.c | 4 ++ .../randomizer/randomizer_entrance.h | 1 + .../randomizer/randomizer_grotto.c | 43 +++++++++++++- .../randomizer/randomizer_grotto.h | 3 +- 5 files changed, 78 insertions(+), 29 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp index 2402f841c..dda8b7a6e 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp @@ -3,11 +3,11 @@ #include "soh/OTRGlobals.h" extern "C" { - #include "z64save.h" - #include "functions.h" - #include "soh/Enhancements/randomizer/randomizer_grotto.h" - extern PlayState* gPlayState; - extern SaveContext gSaveContext; +#include "z64save.h" +#include "functions.h" +#include "soh/Enhancements/randomizer/randomizer_entrance.h" +extern PlayState* gPlayState; +extern SaveContext gSaveContext; } void SkipIntro_Register() { @@ -15,31 +15,33 @@ void SkipIntro_Register() { // If we're playing rando and if starting age is adult and/or overworld spawns are shuffled we need to skip // the cutscene regardless of the enhancement being on. bool adultStart = gSaveContext.linkAge == LINK_AGE_ADULT; - bool shuffleOverworldSpawns = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true); - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || (IS_RANDO && (adultStart || shuffleOverworldSpawns))) { - // Calculate spawn location. Start with vanilla, Link's house. - int32_t spawnEntrance = ENTR_LINKS_HOUSE_0; - // If we're not in rando, we can skip all of the below. - if (IS_RANDO) { - // If starting age is shuffled, use vanilla adult spawn/prelude warp. + bool shuffleOverworldSpawns = + OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true); + if ((CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || + (IS_RANDO && (adultStart || shuffleOverworldSpawns)) && gSaveContext.cutsceneIndex == 0xFFF1)) { + // Calculate spawn location. Start with vanilla, Link's house. + int32_t spawnEntrance = ENTR_LINKS_HOUSE_0; + // If we're not in rando, we can skip all of the below. + if (IS_RANDO) { + // If starting age is shuffled, use vanilla adult spawn/prelude warp. + if (adultStart) { + spawnEntrance = ENTR_TEMPLE_OF_TIME_7; + } + // If we're shuffling overworld spawns we'll need to get the Entrance Override + if (shuffleOverworldSpawns) { + // If we're shuffling overworld spawns the adult spawn is ENTR_HYRULE_FIELD_10 instead of + // ENTR_TEMPLE_OF_TIME_7, so that spawn and Prelude don't share an entrance. if (adultStart) { - spawnEntrance = ENTR_TEMPLE_OF_TIME_7; - } - // If we're shuffling overworld spawns we'll need to get the Entrance Override - if (shuffleOverworldSpawns) { - // If we're shuffling overworld spawns the adult spawn is ENTR_HYRULE_FIELD_10 instead of - // ENTR_TEMPLE_OF_TIME_7, so that spawn and Prelude don't share an entrance. - if (adultStart){ - spawnEntrance = ENTR_HYRULE_FIELD_10; - } - spawnEntrance = Grotto_OverrideSpecialEntrance(Entrance_GetOverride(spawnEntrance)); + spawnEntrance = ENTR_HYRULE_FIELD_10; } + spawnEntrance = Entrance_PeekNextIndexOverride(spawnEntrance); } - // Skip the intro cutscene for whatever the spawnEntrance is calculated to be. - if (gSaveContext.entranceIndex == spawnEntrance) { - gSaveContext.cutsceneIndex = 0; - *should = false; - } + } + // Skip the intro cutscene for whatever the spawnEntrance is calculated to be. + if (gSaveContext.entranceIndex == spawnEntrance) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } } }); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 24bf8c03a..d52b09836 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -260,6 +260,10 @@ s16 Entrance_GetOverride(s16 index) { return entranceOverrideTable[index]; } +s16 Entrance_PeekNextIndexOverride(int16_t nextEntranceIndex) { + return Grotto_GetEntranceValueHandlingGrottoRando(Entrance_GetOverride(nextEntranceIndex)); +} + s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) { // When entering Spirit Temple, clear temp flags so they don't carry over to the randomized dungeon if (nextEntranceIndex == ENTR_SPIRIT_TEMPLE_0 && Entrance_GetOverride(nextEntranceIndex) != nextEntranceIndex && diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.h b/soh/soh/Enhancements/randomizer/randomizer_entrance.h index 8d8d3a678..cc22b31f3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.h +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.h @@ -81,6 +81,7 @@ void Entrance_ResetEntranceTable(void); uint8_t Entrance_EntranceIsNull(EntranceOverride* entranceOverride); int16_t Entrance_GetOverride(int16_t index); int16_t Entrance_OverrideNextIndex(int16_t nextEntranceIndex); +int16_t Entrance_PeekNextIndexOverride(int16_t nextEntranceIndex); int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex); uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn); void Entrance_SetGameOverEntrance(void); diff --git a/soh/soh/Enhancements/randomizer/randomizer_grotto.c b/soh/soh/Enhancements/randomizer/randomizer_grotto.c index b552dd2cd..6c92221b9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_grotto.c +++ b/soh/soh/Enhancements/randomizer/randomizer_grotto.c @@ -128,8 +128,49 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM } } +// Get the next entrance value while handling conversion of grotto rando IDs to real entrance values. +// This method doesn't change player respawn data, so only use this if you are querying an entrance index. +s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) { + // Don't change anything unless grotto shuffle has been enabled + if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) { + return nextEntranceIndex; + } + + // If Link hits a grotto exit, load the entrance index from the grotto exit list + // based on the current grotto ID + if (nextEntranceIndex == ENTR_RETURN_GROTTO) { + nextEntranceIndex = grottoExitList[grottoId]; + } + + // Get the new grotto id from the next entrance + grottoId = nextEntranceIndex & 0x00FF; + + // Grotto Returns + if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START + NUM_GROTTOS) { + GrottoReturnInfo grotto = grottoReturnTable[grottoId]; + + // When the nextEntranceIndex is determined by a dynamic exit, + // or set by Entrance_OverrideBlueWarp to mark a blue warp entrance, + // we have to set the respawn information and nextEntranceIndex manually + if (gPlayState != NULL && gPlayState->nextEntranceIndex != ENTR_LOAD_OPENING) { + nextEntranceIndex = grotto.entranceIndex; + } else if (gPlayState == NULL) { // Handle spawn position when loading from a save file + nextEntranceIndex = grotto.entranceIndex; + // Otherwise return 0x7FFF (ENTR_RETURN_GROTTO) and let the game handle it + } else { + nextEntranceIndex = ENTR_RETURN_GROTTO; + } + // Grotto Loads + } else if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_LOAD_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START) { + GrottoLoadInfo grotto = grottoLoadTable[grottoId]; + nextEntranceIndex = grotto.entranceIndex; + } + + return nextEntranceIndex; +} + // Translates and overrides the passed in entrance index if it corresponds to a -// special grotto entrance (grotto load or returnpoint) +// special grotto entrance (grotto load or returnpoint) and updates player respawn data correctly. s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) { // Don't change anything unless grotto shuffle has been enabled diff --git a/soh/soh/Enhancements/randomizer/randomizer_grotto.h b/soh/soh/Enhancements/randomizer/randomizer_grotto.h index c516d32bf..938c4c6d6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_grotto.h +++ b/soh/soh/Enhancements/randomizer/randomizer_grotto.h @@ -24,7 +24,8 @@ typedef struct { void Grotto_InitExitAndLoadLists(void); void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex); void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex); -s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex); +s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex); +s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex); void Grotto_ForceGrottoReturnOnSpecialEntrance(void); void Grotto_ForceGrottoReturn(void); void Grotto_ForceRegularVoidOut(void); From b81a3dd099f8207e1add57aa323ede3d4ad13575 Mon Sep 17 00:00:00 2001 From: Archez Date: Thu, 25 Jul 2024 21:09:45 -0400 Subject: [PATCH 286/300] Another round of fixes for skip intro and grotto rando (#4253) --- .../Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp | 3 ++- soh/soh/Enhancements/randomizer/randomizer_grotto.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp index dda8b7a6e..aca290f79 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/SkipIntro.cpp @@ -18,7 +18,8 @@ void SkipIntro_Register() { bool shuffleOverworldSpawns = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true); if ((CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || - (IS_RANDO && (adultStart || shuffleOverworldSpawns)) && gSaveContext.cutsceneIndex == 0xFFF1)) { + (IS_RANDO && (adultStart || shuffleOverworldSpawns))) && + gSaveContext.cutsceneIndex == 0xFFF1) { // Calculate spawn location. Start with vanilla, Link's house. int32_t spawnEntrance = ENTR_LINKS_HOUSE_0; // If we're not in rando, we can skip all of the below. diff --git a/soh/soh/Enhancements/randomizer/randomizer_grotto.c b/soh/soh/Enhancements/randomizer/randomizer_grotto.c index 6c92221b9..ef532f670 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_grotto.c +++ b/soh/soh/Enhancements/randomizer/randomizer_grotto.c @@ -142,12 +142,12 @@ s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) { nextEntranceIndex = grottoExitList[grottoId]; } - // Get the new grotto id from the next entrance - grottoId = nextEntranceIndex & 0x00FF; + // Get the new grotto id from the next entrance, temp value to override modifying the static one + s8 tempGrottoId = nextEntranceIndex & 0x00FF; // Grotto Returns if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START + NUM_GROTTOS) { - GrottoReturnInfo grotto = grottoReturnTable[grottoId]; + GrottoReturnInfo grotto = grottoReturnTable[tempGrottoId]; // When the nextEntranceIndex is determined by a dynamic exit, // or set by Entrance_OverrideBlueWarp to mark a blue warp entrance, @@ -162,7 +162,7 @@ s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) { } // Grotto Loads } else if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_LOAD_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START) { - GrottoLoadInfo grotto = grottoLoadTable[grottoId]; + GrottoLoadInfo grotto = grottoLoadTable[tempGrottoId]; nextEntranceIndex = grotto.entranceIndex; } From 06b20a05dd179b8d3fa4897fe855e8c8e0138323 Mon Sep 17 00:00:00 2001 From: Nick Michael Date: Mon, 29 Jul 2024 17:22:57 +0100 Subject: [PATCH 287/300] Fix Lake Hylia Water Level for Vanilla with Cutscene Skips (#4257) * Fix Lake Hylia Water Level * Move logic to SkipBlueWarp handlers --- .../TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp index 564ca2d8f..ec53c7ed0 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp @@ -46,12 +46,16 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, void isBlueWarp = 1; // Fire Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { + // Normally set in the blue warp cutscene + Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; isBlueWarp = 1; // Water Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { // Normally set in the blue warp cutscene gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; + Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; isBlueWarp = 1; From cab0871fe7b97dd27563be95fb315c00a7fdb11d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Mon, 29 Jul 2024 21:48:49 -0400 Subject: [PATCH 288/300] Fix Zora's Sapphire crash (#4254) --- soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 5984e7eee..9ba6a8437 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -2092,7 +2092,7 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { RandomizerCheck rc = RC_MAX; RandomizerGet rg = RG_NONE; - switch (this->actor.params) { + switch (this->actor.params & 0x00FF) { case DEMO_EFFECT_JEWEL_KOKIRI: rc = RC_QUEEN_GOHMA; rg = RG_KOKIRI_EMERALD; From aeb85c81aa824e2b88b519f465dd9e1988691cf3 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Thu, 1 Aug 2024 21:24:24 -0700 Subject: [PATCH 289/300] Item SaveContext Logic (#4237) * Port initial framework up to latest dev-rando. Includes about 15 items using the SCL structure for tracking. * Most other item variables ported to SaveContext in UpdateHelpers. * Removed individual Context retrievals in favor of single local variable in Logic to reference. * start of some diagnostics. caught some reverse logic with ApplyItemEffect. * more diagnostics * Resolve major logic issue with SetInventory flow in ApplyItemEffect. Other small logic issues in ApplyItemEffect. * Added a bit of logging. Add Double Defense to item effects. * revert hint gen bypass * item_list *actually* divorced from logicVar pointers. Several missed options for ApplyItemEffect, HasItem, and UpdateHelpers added in. Changed HasItem to a switch block for more performance. Seeds generate within 10-20 seconds in release mode. Further optimization is assumed possible. * Some formatting * Bit more formatting. * Couple review changes. * Incorporate progressive upgrades and skeleton key into SCL. Bit of cleanup. * Change `inLogic` to static array. * Fix bug in `BottleCount()` preventing Jabu Jabu from ever being in logic. * Fix bomb bag HasItem check. * Fix Gerudo Fortress and Ganon's Castle SmallKeys checks. * Change all logic use of `bool remove` to be `bool state` and work on the affirmative assumption. * Forgot the `Set(x)` uses in `Logic::Reset()`. * Fix fishing pole effect application. * fishing pole tweak * Add `RG_BOMB_BAG`, `RG_NUTS` and `RG_STICKS` to `HasItem()`. Fix silver and gold gauntlet checks in `HasItem()`. Change Nuts and Sticks helpers to use non-progressive RGs in `UpdateHelpers()`. * Change mSaveContext to simple pointer. Set `mSaveContext` to `&gSaveContext` when loading a save file. Modify `Item::GetGIEntry()` to use rando context's SaveContext pointer instead of the gSaveContext macros. Utilize `Item::GetGIEntry()` to get real RG of infinite upgrades and set rando infs accordingly, skipping upgrade level incrementing (which was causing overflow of wallets for some reason). * Rename all remaining references of LogicVar to variants of LogicVal. * Change final references to song LogicVars to CanUse calls, and remove them. * Separate equip and rand inf flag maps. Add Zelda's Letter and Weird Egg rand infs to map. Consolidate `HasItem` rand inf lookups using rand inf map and equips using equip flag map. Maps are static, so can be referenced with `Context::` instead of ctx pointer. --- soh/include/variables.h | 1 + soh/include/z64item.h | 15 + .../Enhancements/randomizer/3drando/fill.cpp | 16 +- .../randomizer/3drando/location_access.cpp | 2 +- .../location_access/locacc_spirit_temple.cpp | 6 +- soh/soh/Enhancements/randomizer/context.cpp | 778 +++++++++++++++++- soh/soh/Enhancements/randomizer/context.h | 32 + soh/soh/Enhancements/randomizer/item.cpp | 108 +-- soh/soh/Enhancements/randomizer/item.h | 21 +- soh/soh/Enhancements/randomizer/item_list.cpp | 500 +++++------ soh/soh/Enhancements/randomizer/logic.cpp | 571 +++++++++---- soh/soh/Enhancements/randomizer/logic.h | 30 +- .../Enhancements/randomizer/randomizerTypes.h | 151 ++++ .../Enhancements/randomizer/randomizer_inf.h | 11 + soh/soh/SaveManager.cpp | 3 +- 15 files changed, 1713 insertions(+), 532 deletions(-) diff --git a/soh/include/variables.h b/soh/include/variables.h index 2c226f2c6..0f50e2249 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -94,6 +94,7 @@ extern "C" extern u16 gEquipMasks[4]; extern u16 gEquipNegMasks[4]; extern u32 gUpgradeMasks[8]; + extern u32 gUpgradeNegMasks[8]; extern u8 gEquipShifts[4]; extern u8 gUpgradeShifts[8]; extern u16 gUpgradeCapacities[8][4]; diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 92ce499ba..ceba11d09 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -311,6 +311,21 @@ typedef enum { /* 0xFF */ ITEM_NONE = 0xFF } ItemID; +typedef enum { + EQUIP_FLAG_SWORD_KOKIRI = 1 << 0, + EQUIP_FLAG_SWORD_MASTER = 1 << 1, + EQUIP_FLAG_SWORD_BGS = 1 << 2, + EQUIP_FLAG_SHIELD_DEKU = 1 << 4, + EQUIP_FLAG_SHIELD_HYLIAN = 1 << 5, + EQUIP_FLAG_SHIELD_MIRROR = 1 << 6, + EQUIP_FLAG_TUNIC_KOKIRI = 1 << 8, + EQUIP_FLAG_TUNIC_GORON = 1 << 9, + EQUIP_FLAG_TUNIC_ZORA = 1 << 10, + EQUIP_FLAG_BOOTS_KOKIRI = 1 << 12, + EQUIP_FLAG_BOOTS_IRON = 1 << 13, + EQUIP_FLAG_BOOTS_HOVER = 1 << 14, +} EquipmentFlag; + #define ITEM_TRADE_CHILD ITEM_WEIRD_EGG #define ITEM_TRADE_ADULT ITEM_POCKET_EGG diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index d25d04aa0..de5ddbdb3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -245,7 +245,7 @@ std::vector GetAccessibleLocations(const std::vector> buyIgnores; + std::vector buyIgnores; //Variables for search std::vector newItemLocations; @@ -365,9 +365,9 @@ std::vector GetAccessibleLocations(const std::vectorGetPlacedItem().GetLogicVar()) || type != ITEMTYPE_SHOP) { + if ((type == ITEMTYPE_SHOP && Rando::StaticData::GetItemTable()[ignore].GetLogicVal() != location->GetPlacedItem().GetLogicVal()) || type != ITEMTYPE_SHOP) { newItemLocations.push_back(location); } } @@ -408,7 +408,7 @@ std::vector GetAccessibleLocations(const std::vectorGetPlacedItem().GetLogicVar(); + auto buyItem = location->GetPlacedItem().GetLogicVal(); //Buy item not in list to ignore, add it to list and write to playthrough if (std::find(buyIgnores.begin(), buyIgnores.end(), buyItem) == buyIgnores.end()) { exclude = false; @@ -1003,7 +1003,9 @@ void ClearProgress() { int Fill() { auto ctx = Rando::Context::GetInstance(); int retries = 0; + SPDLOG_INFO("Starting seed generation..."); while(retries < 5) { + SPDLOG_INFO("Attempt {}...", retries + 1); placementFailure = false; //showItemProgress = false; ctx->playthroughLocations.clear(); @@ -1036,8 +1038,10 @@ int Fill() { //Place shop items first, since a buy shield is needed to place a dungeon reward on Gohma due to access NonShopItems = {}; if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) { + SPDLOG_INFO("Placing Vanilla Shop Items..."); PlaceVanillaShopItems(); //Place vanilla shop items in vanilla location } else { + SPDLOG_INFO("Shuffling Shop Items"); int total_replaced = 0; if (ctx->GetOption(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_ZERO_ITEMS)) { //Shopsanity 1-4, random //Initialize NonShopItems @@ -1080,6 +1084,7 @@ int Fill() { } //Place dungeon rewards + SPDLOG_INFO("Shuffling and Placing Dungeon Items..."); RandomizeDungeonRewards(); //Place dungeon items restricted to their Own Dungeon @@ -1111,15 +1116,18 @@ int Fill() { //Then place dungeon items that are assigned to restrictive location pools RandomizeDungeonItems(); + SPDLOG_INFO("Dungeon Items Done"); //Then place Link's Pocket Item if it has to be an advancement item RandomizeLinksPocket(); + SPDLOG_INFO("Shuffling Advancement Items"); //Then place the rest of the advancement items std::vector remainingAdvancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); }); AssumedFill(remainingAdvancementItems, ctx->allLocations, true); //Fast fill for the rest of the pool + SPDLOG_INFO("Shuffling Remaining Items"); std::vector remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); FastFill(remainingPool, GetAllEmptyLocations(), false); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index ddda3dbab..b181a3cdb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -162,7 +162,7 @@ Rando::Entrance* Area::GetExit(RandomizerRegion exitToReturn) { } bool Area::CanPlantBeanCheck() const { - return (logic->MagicBean || logic->MagicBeanPack) && BothAgesCheck(); + return Rando::Context::GetInstance()->GetAmmo(ITEM_BEAN) > 0 && BothAgesCheck(); } bool Area::AllAccountedFor() const { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index 7feb1b064..92716469e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -207,10 +207,12 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, true), - LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG) + && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Hammer), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, true), - LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->Ocarina && logic->SongOfTime && logic->EponasSong && logic->SunsSong && logic->SongOfStorms && logic->ZeldasLullaby), + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->Hammer && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG) + && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY)), }, {}); areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 35c856d60..a325e5e84 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -9,13 +9,12 @@ #include "settings.h" #include "rando_hash.h" #include "fishsanity.h" +#include "macros.h" #include "3drando/hints.hpp" #include #include -#include "luslog.h" - namespace Rando { std::weak_ptr Context::mContext; @@ -49,6 +48,7 @@ std::shared_ptr Context::CreateInstance() { if (mContext.expired()) { auto instance = std::make_shared(); mContext = instance; + GetInstance()->GetLogic()->SetContext(GetInstance()); return instance; } return GetInstance(); @@ -395,6 +395,500 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) { CreateStaticHints(); } +std::map Context::RandoGetToEquipFlag = { + { RG_KOKIRI_SWORD, EQUIP_FLAG_SWORD_KOKIRI }, + { RG_MASTER_SWORD, EQUIP_FLAG_SWORD_MASTER }, + { RG_BIGGORON_SWORD, EQUIP_FLAG_SWORD_BGS }, + { RG_DEKU_SHIELD, EQUIP_FLAG_SHIELD_DEKU }, + { RG_HYLIAN_SHIELD, EQUIP_FLAG_SHIELD_HYLIAN }, + { RG_MIRROR_SHIELD, EQUIP_FLAG_SHIELD_MIRROR }, + { RG_GORON_TUNIC, EQUIP_FLAG_TUNIC_GORON }, + { RG_ZORA_TUNIC, EQUIP_FLAG_TUNIC_ZORA }, + { RG_BUY_DEKU_SHIELD, EQUIP_FLAG_SHIELD_DEKU }, + { RG_BUY_HYLIAN_SHIELD, EQUIP_FLAG_SHIELD_HYLIAN }, + { RG_BUY_GORON_TUNIC, EQUIP_FLAG_TUNIC_GORON }, + { RG_BUY_ZORA_TUNIC, EQUIP_FLAG_TUNIC_ZORA }, + { RG_IRON_BOOTS, EQUIP_FLAG_BOOTS_IRON }, + { RG_HOVER_BOOTS, EQUIP_FLAG_BOOTS_HOVER } +}; + +std::map Context::RandoGetToRandInf = { + { RG_ZELDAS_LETTER, RAND_INF_ZELDAS_LETTER }, + { RG_WEIRD_EGG, RAND_INF_WEIRD_EGG }, + { RG_GOHMA_SOUL, RAND_INF_GOHMA_SOUL }, + { RG_KING_DODONGO_SOUL, RAND_INF_KING_DODONGO_SOUL }, + { RG_BARINADE_SOUL, RAND_INF_BARINADE_SOUL }, + { RG_PHANTOM_GANON_SOUL, RAND_INF_PHANTOM_GANON_SOUL }, + { RG_VOLVAGIA_SOUL, RAND_INF_VOLVAGIA_SOUL }, + { RG_MORPHA_SOUL, RAND_INF_MORPHA_SOUL }, + { RG_BONGO_BONGO_SOUL, RAND_INF_BONGO_BONGO_SOUL }, + { RG_TWINROVA_SOUL, RAND_INF_TWINROVA_SOUL }, + { RG_GANON_SOUL, RAND_INF_GANON_SOUL }, + { RG_OCARINA_A_BUTTON, RAND_INF_HAS_OCARINA_A }, + { RG_OCARINA_C_UP_BUTTON, RAND_INF_HAS_OCARINA_C_UP }, + { RG_OCARINA_C_DOWN_BUTTON, RAND_INF_HAS_OCARINA_C_DOWN }, + { RG_OCARINA_C_LEFT_BUTTON, RAND_INF_HAS_OCARINA_C_LEFT }, + { RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT }, + { RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY }, + { RG_GREG_RUPEE, RAND_INF_GREG_FOUND }, + { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND } +}; + +std::map Context::RandoGetToDungeonScene = { + { RG_FOREST_TEMPLE_SMALL_KEY, SCENE_FOREST_TEMPLE }, + { RG_FIRE_TEMPLE_SMALL_KEY, SCENE_FIRE_TEMPLE }, + { RG_WATER_TEMPLE_SMALL_KEY, SCENE_WATER_TEMPLE }, + { RG_SPIRIT_TEMPLE_SMALL_KEY, SCENE_SPIRIT_TEMPLE }, + { RG_SHADOW_TEMPLE_SMALL_KEY, SCENE_SHADOW_TEMPLE }, + { RG_BOTTOM_OF_THE_WELL_SMALL_KEY, SCENE_BOTTOM_OF_THE_WELL }, + { RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, SCENE_GERUDO_TRAINING_GROUND }, + { RG_GERUDO_FORTRESS_SMALL_KEY, SCENE_THIEVES_HIDEOUT }, + { RG_GANONS_CASTLE_SMALL_KEY, SCENE_INSIDE_GANONS_CASTLE }, + { RG_FOREST_TEMPLE_KEY_RING, SCENE_FOREST_TEMPLE }, + { RG_FIRE_TEMPLE_KEY_RING, SCENE_FIRE_TEMPLE }, + { RG_WATER_TEMPLE_KEY_RING, SCENE_WATER_TEMPLE }, + { RG_SPIRIT_TEMPLE_KEY_RING, SCENE_SPIRIT_TEMPLE }, + { RG_SHADOW_TEMPLE_KEY_RING, SCENE_SHADOW_TEMPLE }, + { RG_BOTTOM_OF_THE_WELL_KEY_RING, SCENE_BOTTOM_OF_THE_WELL }, + { RG_GERUDO_TRAINING_GROUNDS_KEY_RING, SCENE_GERUDO_TRAINING_GROUND }, + { RG_GERUDO_FORTRESS_KEY_RING, SCENE_THIEVES_HIDEOUT }, + { RG_GANONS_CASTLE_KEY_RING, SCENE_INSIDE_GANONS_CASTLE }, + { RG_FOREST_TEMPLE_BOSS_KEY, SCENE_FOREST_TEMPLE }, + { RG_FIRE_TEMPLE_BOSS_KEY, SCENE_FIRE_TEMPLE }, + { RG_WATER_TEMPLE_BOSS_KEY, SCENE_WATER_TEMPLE }, + { RG_SPIRIT_TEMPLE_BOSS_KEY, SCENE_SPIRIT_TEMPLE }, + { RG_SHADOW_TEMPLE_BOSS_KEY, SCENE_SHADOW_TEMPLE }, + { RG_GANONS_CASTLE_BOSS_KEY, SCENE_INSIDE_GANONS_CASTLE }, + { RG_DEKU_TREE_MAP, SCENE_DEKU_TREE }, + { RG_DODONGOS_CAVERN_MAP, SCENE_DODONGOS_CAVERN }, + { RG_JABU_JABUS_BELLY_MAP, SCENE_JABU_JABU }, + { RG_FOREST_TEMPLE_MAP, SCENE_FOREST_TEMPLE }, + { RG_FIRE_TEMPLE_MAP, SCENE_FIRE_TEMPLE }, + { RG_WATER_TEMPLE_MAP, SCENE_WATER_TEMPLE }, + { RG_SPIRIT_TEMPLE_MAP, SCENE_SPIRIT_TEMPLE }, + { RG_SHADOW_TEMPLE_MAP, SCENE_SHADOW_TEMPLE }, + { RG_BOTTOM_OF_THE_WELL_MAP, SCENE_BOTTOM_OF_THE_WELL }, + { RG_ICE_CAVERN_MAP, SCENE_ICE_CAVERN }, + { RG_DEKU_TREE_COMPASS, SCENE_DEKU_TREE }, + { RG_DODONGOS_CAVERN_COMPASS, SCENE_DODONGOS_CAVERN }, + { RG_JABU_JABUS_BELLY_COMPASS, SCENE_JABU_JABU }, + { RG_FOREST_TEMPLE_COMPASS, SCENE_FOREST_TEMPLE }, + { RG_FIRE_TEMPLE_COMPASS, SCENE_FIRE_TEMPLE }, + { RG_WATER_TEMPLE_COMPASS, SCENE_WATER_TEMPLE }, + { RG_SPIRIT_TEMPLE_COMPASS, SCENE_SPIRIT_TEMPLE }, + { RG_SHADOW_TEMPLE_COMPASS, SCENE_SHADOW_TEMPLE }, + { RG_BOTTOM_OF_THE_WELL_COMPASS, SCENE_BOTTOM_OF_THE_WELL }, + { RG_ICE_CAVERN_COMPASS, SCENE_ICE_CAVERN }, + { RG_TREASURE_GAME_SMALL_KEY, SCENE_TREASURE_BOX_SHOP } +}; + +std::map Context::RandoGetToQuestItem = { + { RG_FOREST_MEDALLION, QUEST_MEDALLION_FOREST }, + { RG_FIRE_MEDALLION, QUEST_MEDALLION_FIRE }, + { RG_WATER_MEDALLION, QUEST_MEDALLION_WATER }, + { RG_SPIRIT_MEDALLION, QUEST_MEDALLION_SPIRIT }, + { RG_SHADOW_MEDALLION, QUEST_MEDALLION_SHADOW }, + { RG_LIGHT_MEDALLION, QUEST_MEDALLION_LIGHT }, + { RG_MINUET_OF_FOREST, QUEST_SONG_MINUET }, + { RG_BOLERO_OF_FIRE, QUEST_SONG_BOLERO }, + { RG_SERENADE_OF_WATER, QUEST_SONG_SERENADE }, + { RG_REQUIEM_OF_SPIRIT, QUEST_SONG_REQUIEM }, + { RG_NOCTURNE_OF_SHADOW, QUEST_SONG_NOCTURNE }, + { RG_PRELUDE_OF_LIGHT, QUEST_SONG_PRELUDE }, + { RG_ZELDAS_LULLABY, QUEST_SONG_LULLABY }, + { RG_EPONAS_SONG, QUEST_SONG_EPONA }, + { RG_SARIAS_SONG, QUEST_SONG_SARIA }, + { RG_SUNS_SONG, QUEST_SONG_SUN }, + { RG_SONG_OF_TIME, QUEST_SONG_TIME }, + { RG_SONG_OF_STORMS, QUEST_SONG_STORMS }, + { RG_KOKIRI_EMERALD, QUEST_KOKIRI_EMERALD }, + { RG_GORON_RUBY, QUEST_GORON_RUBY }, + { RG_ZORA_SAPPHIRE, QUEST_ZORA_SAPPHIRE }, + { RG_STONE_OF_AGONY, QUEST_STONE_OF_AGONY }, + { RG_GERUDO_MEMBERSHIP_CARD, QUEST_GERUDO_CARD }, +}; + +uint32_t HookshotLookup[3] = { ITEM_NONE, ITEM_HOOKSHOT, ITEM_LONGSHOT }; +uint32_t OcarinaLookup[3] = { ITEM_NONE, ITEM_OCARINA_FAIRY, ITEM_OCARINA_TIME }; + +void Context::ApplyItemEffect(Item& item, bool state) { + auto randoGet = item.GetRandomizerGet(); + if (item.GetGIEntry()->objectId == OBJECT_GI_STICK) { + SetInventory(ITEM_STICK, (!state ? ITEM_NONE : ITEM_STICK)); + } + if (item.GetGIEntry()->objectId == OBJECT_GI_NUTS) { + SetInventory(ITEM_NUT, (!state ? ITEM_NONE : ITEM_NUT)); + } + switch (item.GetItemType()) { + case ITEMTYPE_ITEM: + { + switch (randoGet) { + case RG_STONE_OF_AGONY: + case RG_GERUDO_MEMBERSHIP_CARD: + SetQuestItem(RandoGetToQuestItem.at(randoGet), state); + break; + case RG_WEIRD_EGG: + SetRandoInf(RAND_INF_WEIRD_EGG, state); + break; + case RG_ZELDAS_LETTER: + SetRandoInf(RAND_INF_ZELDAS_LETTER, state); + break; + case RG_DOUBLE_DEFENSE: + mSaveContext->isDoubleDefenseAcquired = state; + break; + case RG_POCKET_EGG: + case RG_COJIRO: + case RG_ODD_MUSHROOM: + case RG_ODD_POTION: + case RG_POACHERS_SAW: + case RG_BROKEN_SWORD: + case RG_PRESCRIPTION: + case RG_EYEBALL_FROG: + case RG_EYEDROPS: + case RG_CLAIM_CHECK: + SetAdultTrade(item.GetGIEntry()->itemId, state); + break; + case RG_PROGRESSIVE_HOOKSHOT: + { + uint8_t i; + for (i = 0; i < 3; i++) { + if (CurrentInventory(ITEM_HOOKSHOT) == HookshotLookup[i]) { + break; + } + } + auto newItem = i + (!state ? -1 : 1); + if (newItem < 0) { + newItem = 0; + } + else if (newItem > 2) { + newItem = 2; + } + SetInventory(ITEM_HOOKSHOT, HookshotLookup[newItem]); + } break; + case RG_PROGRESSIVE_STRENGTH: + { + auto currentLevel = CurrentUpgrade(UPG_STRENGTH); + auto newLevel = currentLevel + (!state ? -1 : 1); + SetUpgrade(UPG_STRENGTH, newLevel); + } break; + case RG_PROGRESSIVE_BOMB_BAG: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_BOMB_BAG_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_BOMB_BAG, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_BOMB_BAG); + auto newLevel = currentLevel + (!state ? -1 : 1); + if (currentLevel == 0 && state || currentLevel == 1 && !state) { + SetInventory(ITEM_BOMB, (!state ? ITEM_NONE : ITEM_BOMB)); + } + SetUpgrade(UPG_BOMB_BAG, newLevel); + } break; + case RG_PROGRESSIVE_BOW: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_QUIVER_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_QUIVER, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_QUIVER); + auto newLevel = currentLevel + (!state ? -1 : 1); + if (currentLevel == 0 && state || currentLevel == 1 && !state) { + SetInventory(ITEM_BOW, (!state ? ITEM_NONE : ITEM_BOW)); + } + SetUpgrade(UPG_QUIVER, newLevel); + } break; + case RG_PROGRESSIVE_SLINGSHOT: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_BULLET_BAG_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_BULLET_BAG, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_BULLET_BAG); + auto newLevel = currentLevel + (!state ? -1 : 1); + if (currentLevel == 0 && state || currentLevel == 1 && !state) { + SetInventory(ITEM_SLINGSHOT, (!state ? ITEM_NONE : ITEM_SLINGSHOT)); + } + SetUpgrade(UPG_BULLET_BAG, newLevel); + } break; + case RG_PROGRESSIVE_WALLET: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_WALLET_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_MONEY, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_WALLET); + if (!CheckRandoInf(RAND_INF_HAS_WALLET) && state) { + SetRandoInf(RAND_INF_HAS_WALLET, true); + } + else if (currentLevel == 0 && !state) { + SetRandoInf(RAND_INF_HAS_WALLET, false); + } + else { + auto newLevel = currentLevel + (!state ? -1 : 1); + SetUpgrade(UPG_WALLET, newLevel); + } + } break; + case RG_PROGRESSIVE_SCALE: + { + auto currentLevel = CurrentUpgrade(UPG_SCALE); + if (!CheckRandoInf(RAND_INF_CAN_SWIM) && state) { + SetRandoInf(RAND_INF_CAN_SWIM, true); + } + else if (currentLevel == 0 && !state) { + SetRandoInf(RAND_INF_CAN_SWIM, false); + } + else { + auto newLevel = currentLevel + (!state ? -1 : 1); + SetUpgrade(UPG_SCALE, newLevel); + } + } break; + case RG_PROGRESSIVE_NUT_UPGRADE: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_NUT_UPGRADE_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_NUTS); + auto newLevel = currentLevel + (!state ? -1 : 1); + if (currentLevel == 0 && state || currentLevel == 1 && !state) { + SetInventory(ITEM_NUT, (!state ? ITEM_NONE : ITEM_NUT)); + } + SetUpgrade(UPG_NUTS, newLevel); + } break; + case RG_PROGRESSIVE_STICK_UPGRADE: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_STICK_UPGRADE_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE, true); + break; + } + auto currentLevel = CurrentUpgrade(UPG_STICKS); + auto newLevel = currentLevel + (!state ? -1 : 1); + if (currentLevel == 0 && state || currentLevel == 1 && !state) { + SetInventory(ITEM_STICK, (!state ? ITEM_NONE : ITEM_STICK)); + } + SetUpgrade(UPG_STICKS, newLevel); + } break; + case RG_PROGRESSIVE_BOMBCHUS: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_BOMBCHU_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_BOMBCHUS, true); + break; + } + SetInventory(ITEM_BOMBCHU, (!state ? ITEM_NONE : ITEM_BOMBCHU)); + } break; + case RG_PROGRESSIVE_MAGIC_METER: + { + auto realGI = item.GetGIEntry(); + if (realGI->itemId == RG_MAGIC_INF && realGI->modIndex == MOD_RANDOMIZER) { + SetRandoInf(RAND_INF_HAS_INFINITE_MAGIC_METER, true); + break; + } + mSaveContext->magicLevel += (!state ? -1 : 1); + } break; + case RG_PROGRESSIVE_OCARINA: + { + uint8_t i; + for (i = 0; i < 3; i++) { + if (CurrentInventory(ITEM_OCARINA_FAIRY) == OcarinaLookup[i]) { + break; + } + } + i += (!state ? -1 : 1); + if (i < 0) { + i = 0; + } + else if (i > 2) { + i = 2; + } + SetInventory(ITEM_OCARINA_FAIRY, OcarinaLookup[i]); + } break; + case RG_HEART_CONTAINER: + mSaveContext->healthCapacity += (!state ? -16 : 16); + break; + case RG_PIECE_OF_HEART: + mSaveContext->healthCapacity += (!state ? -4 : 4); + break; + case RG_BOOMERANG: + case RG_LENS_OF_TRUTH: + case RG_MEGATON_HAMMER: + case RG_DINS_FIRE: + case RG_FARORES_WIND: + case RG_NAYRUS_LOVE: + case RG_FIRE_ARROWS: + case RG_ICE_ARROWS: + case RG_LIGHT_ARROWS: + SetInventory(item.GetGIEntry()->itemId, (!state ? ITEM_NONE : item.GetGIEntry()->itemId)); + break; + case RG_MAGIC_BEAN: + case RG_MAGIC_BEAN_PACK: + { + auto change = (item.GetRandomizerGet() == RG_MAGIC_BEAN ? 1 : 10); + auto current = GetAmmo(ITEM_BEAN); + SetAmmo(ITEM_BEAN, current + (!state ? -change : change)); + } break; + case RG_EMPTY_BOTTLE: + case RG_BOTTLE_WITH_MILK: + case RG_BOTTLE_WITH_RED_POTION: + case RG_BOTTLE_WITH_GREEN_POTION: + case RG_BOTTLE_WITH_BLUE_POTION: + case RG_BOTTLE_WITH_FAIRY: + case RG_BOTTLE_WITH_FISH: + case RG_BOTTLE_WITH_BLUE_FIRE: + case RG_BOTTLE_WITH_BUGS: + case RG_BOTTLE_WITH_POE: + case RG_BOTTLE_WITH_BIG_POE: + { + uint8_t slot = SLOT_BOTTLE_1; + while (slot != SLOT_BOTTLE_4) { + if (mSaveContext->inventory.items[slot] == ITEM_NONE) { + break; + } + slot++; + } + mSaveContext->inventory.items[slot] = item.GetGIEntry()->itemId; + } break; + case RG_RUTOS_LETTER: + SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER, state); + break; + case RG_GOHMA_SOUL: + case RG_KING_DODONGO_SOUL: + case RG_BARINADE_SOUL: + case RG_PHANTOM_GANON_SOUL: + case RG_VOLVAGIA_SOUL: + case RG_MORPHA_SOUL: + case RG_BONGO_BONGO_SOUL: + case RG_TWINROVA_SOUL: + case RG_GANON_SOUL: + case RG_OCARINA_A_BUTTON: + case RG_OCARINA_C_UP_BUTTON: + case RG_OCARINA_C_DOWN_BUTTON: + case RG_OCARINA_C_LEFT_BUTTON: + case RG_OCARINA_C_RIGHT_BUTTON: + case RG_GREG_RUPEE: + case RG_FISHING_POLE: + SetRandoInf(RandoGetToRandInf.at(randoGet), state); + break; + case RG_TRIFORCE_PIECE: + mSaveContext->triforcePiecesCollected += (!state ? -1 : 1); + break; + case RG_BOMBCHU_5: + case RG_BOMBCHU_10: + case RG_BOMBCHU_20: + case RG_BOMBCHU_DROP: + SetInventory(ITEM_BOMBCHU, (!state ? ITEM_NONE : ITEM_BOMBCHU)); + break; + } + } + break; + case ITEMTYPE_EQUIP: + { + RandomizerGet itemRG = item.GetRandomizerGet(); + if (itemRG == RG_GIANTS_KNIFE) { + return; + } + uint32_t equipId = RandoGetToEquipFlag.find(itemRG)->second; + if (!state) { + mSaveContext->inventory.equipment &= ~equipId; + if (equipId == EQUIP_FLAG_SWORD_BGS) { + mSaveContext->bgsFlag = false; + } + } + else { + mSaveContext->inventory.equipment |= equipId; + if (equipId == EQUIP_FLAG_SWORD_BGS) { + mSaveContext->bgsFlag = true; + } + } + } + break; + case ITEMTYPE_DUNGEONREWARD: + case ITEMTYPE_SONG: + SetQuestItem(RandoGetToQuestItem.find(item.GetRandomizerGet())->second, state); + break; + case ITEMTYPE_MAP: + SetDungeonItem(DUNGEON_MAP, RandoGetToDungeonScene.find(item.GetRandomizerGet())->second, state); + break; + case ITEMTYPE_COMPASS: + SetDungeonItem(DUNGEON_COMPASS, RandoGetToDungeonScene.find(item.GetRandomizerGet())->second, state); + break; + case ITEMTYPE_BOSSKEY: + SetDungeonItem(DUNGEON_KEY_BOSS, RandoGetToDungeonScene.find(item.GetRandomizerGet())->second, state); + break; + case ITEMTYPE_FORTRESS_SMALLKEY: + case ITEMTYPE_SMALLKEY: + { + auto randoGet = item.GetRandomizerGet(); + auto keyring = randoGet >= RG_FOREST_TEMPLE_KEY_RING && randoGet <= RG_GANONS_CASTLE_KEY_RING; + auto dungeonIndex = RandoGetToDungeonScene.find(randoGet)->second; + auto count = GetSmallKeyCount(dungeonIndex); + if (!state) { + if (keyring) { + count = 0; + } + else { + count -= 1; + } + } + else { + if (keyring) { + count = 10; + } + else { + count += 1; + } + } + SetSmallKeyCount(dungeonIndex, count); + } break; + case ITEMTYPE_TOKEN: + mSaveContext->inventory.gsTokens += (!state ? -1 : 1); + break; + case ITEMTYPE_EVENT: + break; + case ITEMTYPE_DROP: + case ITEMTYPE_REFILL: + case ITEMTYPE_SHOP: + { + RandomizerGet itemRG = item.GetRandomizerGet(); + if (itemRG == RG_BUY_HYLIAN_SHIELD || itemRG == RG_BUY_DEKU_SHIELD || itemRG == RG_BUY_GORON_TUNIC || itemRG == RG_BUY_ZORA_TUNIC) { + uint32_t equipId = RandoGetToEquipFlag.find(itemRG)->second; + if (!state) { + mSaveContext->inventory.equipment &= ~equipId; + } + else { + mSaveContext->inventory.equipment |= equipId; + } + } + switch (itemRG) { + case RG_DEKU_NUTS_5: + case RG_DEKU_NUTS_10: + case RG_BUY_DEKU_NUTS_5: + case RG_BUY_DEKU_NUTS_10: + SetInventory(ITEM_NUT, (!state ? ITEM_NONE : ITEM_NUT)); + break; + case RG_DEKU_STICK_1: + case RG_BUY_DEKU_STICK_1: + case RG_STICKS: + SetInventory(ITEM_STICK, (!state ? ITEM_NONE : ITEM_STICK)); + break; + case RG_BOMBCHU_5: + case RG_BOMBCHU_10: + case RG_BOMBCHU_20: + case RG_BOMBCHU_DROP: + SetInventory(ITEM_BOMBCHU, (!state ? ITEM_NONE : ITEM_BOMBCHU)); + break; + } + } break; + } + mLogic->UpdateHelpers(); +} + std::shared_ptr Context::GetSettings() { return mSettings; } @@ -422,7 +916,170 @@ std::shared_ptr Context::GetLogic() { return mLogic; } +SaveContext* Context::GetSaveContext() { + if (mSaveContext == nullptr) { + NewSaveContext(); + } + return mSaveContext; +} + +void Context::SetSaveContext(SaveContext* context) { + mSaveContext = context; +} + +void Context::InitSaveContext() { + mSaveContext->totalDays = 0; + mSaveContext->bgsDayCount = 0; + + mSaveContext->deaths = 0; + for (int i = 0; i < ARRAY_COUNT(mSaveContext->playerName); i++) { + mSaveContext->playerName[i] = 0x3E; + } + mSaveContext->n64ddFlag = 0; + mSaveContext->healthCapacity = 0x30; + mSaveContext->health = 0x30; + mSaveContext->magicLevel = 0; + mSaveContext->magic = 0x30; + mSaveContext->rupees = 0; + mSaveContext->swordHealth = 0; + mSaveContext->naviTimer = 0; + mSaveContext->isMagicAcquired = 0; + mSaveContext->isDoubleMagicAcquired = 0; + mSaveContext->isDoubleDefenseAcquired = 0; + mSaveContext->bgsFlag = 0; + mSaveContext->ocarinaGameRoundNum = 0; + for (int button = 0; button < ARRAY_COUNT(mSaveContext->childEquips.buttonItems); button++) { + mSaveContext->childEquips.buttonItems[button] = ITEM_NONE; + } + for (int button = 0; button < ARRAY_COUNT(mSaveContext->childEquips.cButtonSlots); button++) { + mSaveContext->childEquips.cButtonSlots[button] = SLOT_NONE; + } + mSaveContext->childEquips.equipment = 0; + for (int button = 0; button < ARRAY_COUNT(mSaveContext->adultEquips.buttonItems); button++) { + mSaveContext->adultEquips.buttonItems[button] = ITEM_NONE; + } + for (int button = 0; button < ARRAY_COUNT(mSaveContext->adultEquips.cButtonSlots); button++) { + mSaveContext->adultEquips.cButtonSlots[button] = SLOT_NONE; + } + mSaveContext->adultEquips.equipment = 0; + mSaveContext->unk_54 = 0; + mSaveContext->savedSceneNum = SCENE_LINKS_HOUSE; + + // Equipment + for (int button = 0; button < ARRAY_COUNT(mSaveContext->equips.buttonItems); button++) { + mSaveContext->equips.buttonItems[button] = ITEM_NONE; + } + for (int button = 0; button < ARRAY_COUNT(mSaveContext->equips.cButtonSlots); button++) { + mSaveContext->equips.cButtonSlots[button] = SLOT_NONE; + } + mSaveContext->equips.equipment = 0; + + // Inventory + for (int item = 0; item < ARRAY_COUNT(mSaveContext->inventory.items); item++) { + mSaveContext->inventory.items[item] = ITEM_NONE; + } + for (int ammo = 0; ammo < ARRAY_COUNT(mSaveContext->inventory.ammo); ammo++) { + mSaveContext->inventory.ammo[ammo] = 0; + } + mSaveContext->inventory.equipment = 0; + mSaveContext->inventory.upgrades = 0; + mSaveContext->inventory.questItems = 0; + for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonItems); dungeon++) { + mSaveContext->inventory.dungeonItems[dungeon] = 0; + } + for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonKeys); dungeon++) { + mSaveContext->inventory.dungeonKeys[dungeon] = 0x0; + } + mSaveContext->inventory.defenseHearts = 0; + mSaveContext->inventory.gsTokens = 0; + for (int scene = 0; scene < ARRAY_COUNT(mSaveContext->sceneFlags); scene++) { + mSaveContext->sceneFlags[scene].chest = 0; + mSaveContext->sceneFlags[scene].swch = 0; + mSaveContext->sceneFlags[scene].clear = 0; + mSaveContext->sceneFlags[scene].collect = 0; + mSaveContext->sceneFlags[scene].unk = 0; + mSaveContext->sceneFlags[scene].rooms = 0; + mSaveContext->sceneFlags[scene].floors = 0; + } + mSaveContext->fw.pos.x = 0; + mSaveContext->fw.pos.y = 0; + mSaveContext->fw.pos.z = 0; + mSaveContext->fw.yaw = 0; + mSaveContext->fw.playerParams = 0; + mSaveContext->fw.entranceIndex = 0; + mSaveContext->fw.roomIndex = 0; + mSaveContext->fw.set = 0; + mSaveContext->fw.tempSwchFlags = 0; + mSaveContext->fw.tempCollectFlags = 0; + for (int flag = 0; flag < ARRAY_COUNT(mSaveContext->gsFlags); flag++) { + mSaveContext->gsFlags[flag] = 0; + } + for (int highscore = 0; highscore < ARRAY_COUNT(mSaveContext->highScores); highscore++) { + mSaveContext->highScores[highscore] = 0; + } + for (int flag = 0; flag < ARRAY_COUNT(mSaveContext->eventChkInf); flag++) { + mSaveContext->eventChkInf[flag] = 0; + } + for (int flag = 0; flag < ARRAY_COUNT(mSaveContext->itemGetInf); flag++) { + mSaveContext->itemGetInf[flag] = 0; + } + for (int flag = 0; flag < ARRAY_COUNT(mSaveContext->infTable); flag++) { + mSaveContext->infTable[flag] = 0; + } + mSaveContext->worldMapAreaData = 0; + mSaveContext->scarecrowLongSongSet = 0; + for (int i = 0; i < ARRAY_COUNT(mSaveContext->scarecrowLongSong); i++) { + mSaveContext->scarecrowLongSong[i].noteIdx = 0; + mSaveContext->scarecrowLongSong[i].unk_01 = 0; + mSaveContext->scarecrowLongSong[i].unk_02 = 0; + mSaveContext->scarecrowLongSong[i].volume = 0; + mSaveContext->scarecrowLongSong[i].vibrato = 0; + mSaveContext->scarecrowLongSong[i].tone = 0; + mSaveContext->scarecrowLongSong[i].semitone = 0; + } + mSaveContext->scarecrowSpawnSongSet = 0; + for (int i = 0; i < ARRAY_COUNT(mSaveContext->scarecrowSpawnSong); i++) { + mSaveContext->scarecrowSpawnSong[i].noteIdx = 0; + mSaveContext->scarecrowSpawnSong[i].unk_01 = 0; + mSaveContext->scarecrowSpawnSong[i].unk_02 = 0; + mSaveContext->scarecrowSpawnSong[i].volume = 0; + mSaveContext->scarecrowSpawnSong[i].vibrato = 0; + mSaveContext->scarecrowSpawnSong[i].tone = 0; + mSaveContext->scarecrowSpawnSong[i].semitone = 0; + } + + mSaveContext->horseData.scene = SCENE_HYRULE_FIELD; + mSaveContext->horseData.pos.x = -1840; + mSaveContext->horseData.pos.y = 72; + mSaveContext->horseData.pos.z = 5497; + mSaveContext->horseData.angle = -0x6AD9; + mSaveContext->magicLevel = 0; + mSaveContext->infTable[29] = 1; + mSaveContext->sceneFlags[5].swch = 0x40000000; + + // SoH specific + mSaveContext->backupFW = mSaveContext->fw; + mSaveContext->pendingSale = ITEM_NONE; + mSaveContext->pendingSaleMod = MOD_NONE; + mSaveContext->isBossRushPaused = 0; + mSaveContext->pendingIceTrapCount = 0; + + // Init with normal quest unless only an MQ rom is provided + mSaveContext->questId = OTRGlobals::Instance->HasOriginal() ? QUEST_NORMAL : QUEST_MASTER; + + //RANDOTODO (ADD ITEMLOCATIONS TO GSAVECONTEXT) +} + +void Context::NewSaveContext() { + if (mSaveContext != nullptr && mSaveContext != &gSaveContext) { + free(mSaveContext); + } + mSaveContext = new SaveContext(); + InitSaveContext(); +} + void Context::ResetLogic() { + NewSaveContext(); mLogic->Reset(); } @@ -449,4 +1106,121 @@ Option& Context::GetOption(const RandomizerSettingKey key) const { TrickOption& Context::GetTrickOption(const RandomizerTrick key) const { return mSettings->GetTrickOption(key); } + +uint8_t Context::InventorySlot(uint32_t item) { + return gItemSlots[item]; +} + +uint32_t Context::CurrentUpgrade(uint32_t upgrade) { + return (mSaveContext->inventory.upgrades & gUpgradeMasks[upgrade]) >> gUpgradeShifts[upgrade]; +} + +uint32_t Context::CurrentInventory(uint32_t item) { + return mSaveContext->inventory.items[InventorySlot(item)]; +} + +void Context::SetUpgrade(uint32_t upgrade, uint8_t level) { + mSaveContext->inventory.upgrades &= gUpgradeNegMasks[upgrade]; + mSaveContext->inventory.upgrades |= level << gUpgradeShifts[upgrade]; +} + +bool Context::CheckInventory(uint32_t item, bool exact) { + auto current = mSaveContext->inventory.items[InventorySlot(item)]; + return exact ? (current == item) : (current != ITEM_NONE); +} + +void Context::SetInventory(uint32_t itemSlot, uint32_t item) { + mSaveContext->inventory.items[InventorySlot(itemSlot)] = item; +} + +bool Context::CheckEquipment(uint32_t equipFlag) { + return (equipFlag & mSaveContext->inventory.equipment); +} + +bool Context::CheckQuestItem(uint32_t item) { + return ((1 << item) & mSaveContext->inventory.questItems); +} + +bool Context::HasAdultTrade(uint32_t itemID) { + int tradeIndex = itemID - ITEM_POCKET_EGG; + return mSaveContext->adultTradeItems & (1 << tradeIndex); +} + +void Context::SetAdultTrade(uint32_t itemID, bool state) { + int tradeIndex = itemID - ITEM_POCKET_EGG; + if (!state) { + mSaveContext->adultTradeItems &= ~(1 << tradeIndex); + } + else { + mSaveContext->adultTradeItems |= (1 << tradeIndex); + } +} + +void Context::SetQuestItem(uint32_t item, bool state) { + if (!state) { + mSaveContext->inventory.questItems &= ~(1 << item); + } + else { + mSaveContext->inventory.questItems |= (1 << item); + } +} + +uint8_t Context::GetSmallKeyCount(uint32_t dungeonIndex) { + return mSaveContext->inventory.dungeonKeys[dungeonIndex]; +} + +void Context::SetSmallKeyCount(uint32_t dungeonIndex, uint8_t count) { + mSaveContext->inventory.dungeonKeys[dungeonIndex] = count; +} + +bool Context::CheckDungeonItem(uint32_t item, uint32_t dungeonIndex) { + return mSaveContext->inventory.dungeonItems[dungeonIndex] & gBitFlags[item]; +} + +void Context::SetDungeonItem(uint32_t item, uint32_t dungeonIndex, bool state) { + if (!state) { + mSaveContext->inventory.dungeonItems[dungeonIndex] &= ~gBitFlags[item]; + } + else { + mSaveContext->inventory.dungeonItems[dungeonIndex] |= gBitFlags[item]; + } +} + +bool Context::CheckRandoInf(uint32_t flag) { + return mSaveContext->randomizerInf[flag >> 4] & (1 << (flag & 0xF)); +} + +void Context::SetRandoInf(uint32_t flag, bool state) { + if (!state) { + mSaveContext->randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF)); + } + else { + mSaveContext->randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); + } +} + +bool Context::CheckEventChkInf(int32_t flag) { + return mSaveContext->eventChkInf[flag >> 4] & (1 << (flag & 0xF)); +} + +void Context::SetEventChkInf(int32_t flag, bool state) { + if (!state) { + mSaveContext->eventChkInf[flag >> 4] &= ~(1 << (flag & 0xF)); + } + else { + mSaveContext->eventChkInf[flag >> 4] |= (1 << (flag & 0xF)); + } +} + +uint8_t Context::GetGSCount() { + return mSaveContext->inventory.gsTokens; +} + +uint8_t Context::GetAmmo(uint32_t item) { + return mSaveContext->inventory.ammo[gItemSlots[item]]; +} + +void Context::SetAmmo(uint32_t item, uint8_t count) { + mSaveContext->inventory.ammo[gItemSlots[item]] = count; +} } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h index 2deb4e365..13147143e 100644 --- a/soh/soh/Enhancements/randomizer/context.h +++ b/soh/soh/Enhancements/randomizer/context.h @@ -52,6 +52,10 @@ class Context { void GenerateLocationPool(); static std::vector GetLocations(const std::vector& locationPool, Category categoryInclude, Category categoryExclude = Category::cNull); + static std::map RandoGetToQuestItem; + static std::map RandoGetToDungeonScene; + static std::map RandoGetToEquipFlag; + static std::map RandoGetToRandInf; void AddExcludedOptions(); void LocationReset(); void ClearItemLocations(); @@ -64,12 +68,17 @@ class Context { void SetSpoilerLoaded(bool spoilerLoaded = true); bool IsPlandoLoaded() const; void SetPlandoLoaded(bool plandoLoaded = true); + void ApplyItemEffect(Item& item, bool state); std::shared_ptr GetSettings(); std::shared_ptr GetEntranceShuffler(); std::shared_ptr GetDungeons(); std::shared_ptr GetFishsanity(); DungeonInfo* GetDungeon(size_t key) const; std::shared_ptr GetLogic(); + SaveContext* GetSaveContext(); + void SetSaveContext(SaveContext* context); + void InitSaveContext(); + void NewSaveContext(); void ResetLogic(); std::shared_ptr GetTrials(); TrialInfo* GetTrial(size_t key) const; @@ -92,6 +101,28 @@ class Context { bool playthroughBeatable = false; bool allLocationsReachable = false; RandomizerArea GetAreaFromString(std::string str); + uint8_t InventorySlot(uint32_t item); + void SetUpgrade(uint32_t upgrade, uint8_t level); + uint32_t CurrentUpgrade(uint32_t upgrade); + uint32_t CurrentInventory(uint32_t item); + bool CheckInventory(uint32_t item, bool exact); + void SetInventory(uint32_t itemSlot, uint32_t item); + bool CheckEquipment(uint32_t item); + bool CheckQuestItem(uint32_t item); + void SetQuestItem(uint32_t item, bool state); + bool HasAdultTrade(uint32_t item); + void SetAdultTrade(uint32_t item, bool state); + uint8_t GetSmallKeyCount(uint32_t dungeonIndex); + void SetSmallKeyCount(uint32_t dungeonIndex, uint8_t count); + bool CheckDungeonItem(uint32_t item, uint32_t dungeonIndex); + void SetDungeonItem(uint32_t item, uint32_t dungeonIndex, bool state); + bool CheckRandoInf(uint32_t flag); + void SetRandoInf(uint32_t flag, bool state); + bool CheckEventChkInf(int32_t flag); + uint8_t GetGSCount(); + void SetEventChkInf(int32_t flag, bool state); + uint8_t GetAmmo(uint32_t item); + void SetAmmo(uint32_t item, uint8_t count); private: static std::weak_ptr mContext; @@ -101,6 +132,7 @@ class Context { std::shared_ptr mEntranceShuffler; std::shared_ptr mDungeons; std::shared_ptr mLogic; + SaveContext* mSaveContext = nullptr; std::shared_ptr mTrials; std::shared_ptr mFishsanity; bool mSeedGenerated = false; diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 2ffedbfeb..5fbab59a8 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -14,74 +14,41 @@ namespace Rando { Item::Item() : randomizerGet(RG_NONE), type(ITEMTYPE_ITEM), getItemId(GI_NONE), advancement(false), hintKey(RHT_NONE), progressive(false), price(0) {} Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, bool* logicVar_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, - const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, - const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, - const bool progressive_, const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, + const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, + const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, + const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { - giEntry = std::make_shared(GetItemEntry{itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast(randomizerGet_), MOD_RANDOMIZER, NULL}); - } else { - giEntry = std::make_shared(GetItemEntry{itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_VANILLA, getItemId_, gid_, true, ITEM_FROM_NPC, category_, itemId_, modIndex_, NULL}); + giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast(randomizerGet_), MOD_RANDOMIZER, NULL }); + } + else { + giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_VANILLA, getItemId_, gid_, true, ITEM_FROM_NPC, category_, itemId_, modIndex_, NULL }); } } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, uint8_t* logicVar_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, - const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, - const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, - const bool progressive_, const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const bool progressive_, + const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) { - if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { - giEntry = std::make_shared(GetItemEntry{itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast(randomizerGet_), modIndex_, NULL}); - } else { - giEntry = std::make_shared(GetItemEntry{itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_VANILLA, getItemId_, gid_, true, ITEM_FROM_NPC, category_, itemId_, modIndex_, NULL}); - } -} - -Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, bool* logicVar_, const RandomizerHintTextKey hintKey_, const bool progressive_, - const uint16_t price_) - : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) { -} - -Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, uint8_t* logicVar_, const RandomizerHintTextKey hintKey_, const bool progressive_, - const uint16_t price_) - : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { } Item::~Item() = default; void Item::ApplyEffect() const { - // If this is a key ring, logically add as many keys as we could need - if (RHT_FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= RHT_GANONS_CASTLE_KEY_RING) { - *std::get(logicVar) += 10; - } else { - if (std::holds_alternative(logicVar)) { - *std::get(logicVar) = true; - } else { - *std::get(logicVar) += 1; - } - } - Rando::Context::GetInstance()->GetLogic()->UpdateHelpers(); + auto ctx = Rando::Context::GetInstance(); + ctx->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true); + ctx->GetLogic()->SetInLogic(logicVal, true); + ctx->GetLogic()->UpdateHelpers(); } void Item::UndoEffect() const { - if (RHT_FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= RHT_GANONS_CASTLE_KEY_RING) { - *std::get(logicVar) -= 10; - } else { - if (std::holds_alternative(logicVar)) { - *std::get(logicVar) = false; - } else { - *std::get(logicVar) -= 1; - } - } - Rando::Context::GetInstance()->GetLogic()->UpdateHelpers(); + auto ctx = Rando::Context::GetInstance(); + ctx->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false); + ctx->GetLogic()->SetInLogic(logicVal, false); + ctx->GetLogic()->UpdateHelpers(); } const Text& Item::GetName() const { @@ -100,8 +67,8 @@ ItemType Item::GetItemType() const { return type; } -std::variant Item::GetLogicVar() const { - return logicVar; +LogicVal Item::GetLogicVal() const { + return logicVal; } RandomizerGet Item::GetRandomizerGet() const { @@ -116,13 +83,14 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio if (giEntry != nullptr) { return giEntry; } + auto ctx = Rando::Context::GetInstance(); RandomizerGet actual = RG_NONE; const bool tycoonWallet = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; const u8 infiniteUpgrades = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES); switch (randomizerGet) { case RG_PROGRESSIVE_STICK_UPGRADE: - switch (CUR_UPG_VALUE(UPG_STICKS)) { + switch (ctx->CurrentUpgrade(UPG_STICKS)) { case 0: if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { actual = RG_DEKU_STICK_BAG; @@ -151,7 +119,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_NUT_UPGRADE: - switch (CUR_UPG_VALUE(UPG_NUTS)) { + switch (ctx->CurrentUpgrade(UPG_NUTS)) { case 0: if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { actual = RG_DEKU_NUT_BAG; @@ -180,7 +148,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_BOMB_BAG: - switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { + switch (ctx->CurrentUpgrade(UPG_BOMB_BAG)) { case 0: actual = RG_BOMB_BAG; break; @@ -207,7 +175,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_BOW: - switch (CUR_UPG_VALUE(UPG_QUIVER)) { + switch (ctx->CurrentUpgrade(UPG_QUIVER)) { case 0: actual = RG_FAIRY_BOW; break; @@ -234,7 +202,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_SLINGSHOT: - switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) { + switch (ctx->CurrentUpgrade(UPG_BULLET_BAG)) { case 0: actual = RG_FAIRY_SLINGSHOT; break; @@ -261,7 +229,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_OCARINA: - switch (INV_CONTENT(ITEM_OCARINA_FAIRY)) { + switch (ctx->CurrentInventory(ITEM_OCARINA_FAIRY)) { case ITEM_NONE: actual = RG_FAIRY_OCARINA; break; @@ -274,7 +242,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_HOOKSHOT: - switch (INV_CONTENT(ITEM_HOOKSHOT)) { + switch (ctx->CurrentInventory(ITEM_HOOKSHOT)) { case ITEM_NONE: actual = RG_HOOKSHOT; break; @@ -287,7 +255,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_STRENGTH: - switch (CUR_UPG_VALUE(UPG_STRENGTH)) { + switch (ctx->CurrentUpgrade(UPG_STRENGTH)) { case 0: actual = RG_GORONS_BRACELET; break; @@ -303,11 +271,11 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_WALLET: - if (!Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { + if (!ctx->CheckRandoInf(RAND_INF_HAS_WALLET)) { actual = RG_CHILD_WALLET; break; } - switch (CUR_UPG_VALUE(UPG_WALLET)) { + switch (ctx->CurrentUpgrade(UPG_WALLET)) { case 0: actual = RG_ADULT_WALLET; break; @@ -330,11 +298,11 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_SCALE: - if (!Flags_GetRandomizerInf(RAND_INF_CAN_SWIM)) { + if (!ctx->CheckRandoInf(RAND_INF_CAN_SWIM)) { actual = RG_BRONZE_SCALE; break; } - switch (CUR_UPG_VALUE(UPG_SCALE)) { + switch (ctx->CurrentUpgrade(UPG_SCALE)) { case 0: actual = RG_SILVER_SCALE; break; @@ -347,7 +315,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_MAGIC_METER: - switch (gSaveContext.magicLevel) { + switch (ctx->GetSaveContext()->magicLevel) { case 0: actual = RG_MAGIC_SINGLE; break; @@ -370,11 +338,11 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_BIGGORON_SWORD; break; case RG_PROGRESSIVE_BOMBCHUS: - if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + if (ctx->CurrentInventory(ITEM_BOMBCHU) == ITEM_NONE) { actual = RG_BOMBCHU_20; } else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { actual = RG_BOMBCHU_INF; - } else if (AMMO(ITEM_BOMBCHU) < 5) { + } else if (ctx->GetAmmo(ITEM_BOMBCHU) < 5) { actual = RG_BOMBCHU_10; } else { actual = RG_BOMBCHU_5; diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index 8986d1146..f0df0f1bf 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -11,6 +11,7 @@ enum ItemType { ITEMTYPE_ITEM, + ITEMTYPE_EQUIP, ITEMTYPE_MAP, ITEMTYPE_COMPASS, ITEMTYPE_BOSSKEY, @@ -30,17 +31,11 @@ class Item { public: Item(); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - bool* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, - uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, - uint16_t modIndex_, bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, + uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, + bool progressive_ = false, uint16_t price_ = 0); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - uint8_t* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, - uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, - bool progressive_ = false, uint16_t price_ = 0); - Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - bool* logicVar_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); - Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - uint8_t* logicVar_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); ~Item(); void ApplyEffect() const; @@ -51,7 +46,7 @@ class Item { bool IsAdvancement() const; int GetItemID() const; ItemType GetItemType() const; - std::variant GetLogicVar() const; + LogicVal GetLogicVal() const; RandomizerGet GetRandomizerGet() const; uint16_t GetPrice() const; std::shared_ptr GetGIEntry() const; @@ -73,11 +68,11 @@ class Item { ItemType type; int16_t getItemId; bool advancement; - std::variant logicVar; + LogicVal logicVal; RandomizerHintTextKey hintKey; bool progressive; uint16_t price; bool playthrough = false; - std::shared_ptr giEntry; + std::shared_ptr giEntry; }; } diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 7c86fcfd3..6e4524939 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -12,331 +12,331 @@ std::unordered_map Rando::StaticData::itemNameToEnum void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); - itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, &logic->noVariable, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); - // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Variable Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index - itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_KOKIRI, true, &logic->KokiriSword, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Espada Master"}, ITEMTYPE_ITEM, 0xE0, true, &logic->MasterSword, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); + // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Value Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index + itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Espada Master"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MASTER_SWORD].SetCustomDrawFunc(Randomizer_DrawMasterSword); - itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Messer des Riesen" }, ITEMTYPE_ITEM, GI_SWORD_KNIFE, true, &logic->noVariable, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BGS, true, &logic->BiggoronSword, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_DEKU, false, &logic->noVariable, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_HYLIAN, false, &logic->noVariable, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegel-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_MIRROR, true, &logic->MirrorShield, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_ITEM, GI_TUNIC_GORON, true, &logic->GoronTunic, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_ITEM, GI_TUNIC_ZORA, true, &logic->ZoraTunic, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_ITEM, GI_BOOTS_IRON, true, &logic->IronBoots, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_ITEM, GI_BOOTS_HOVER, true, &logic->HoverBoots, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, &logic->Boomerang, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, &logic->LensOfTruth, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, &logic->Hammer, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein der Qualen" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &logic->ShardOfAgony, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, &logic->DinsFire, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, &logic->FaroresWind, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, &logic->NayrusLove, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, &logic->FireArrows, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, &logic->IceArrows, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, &logic->LightArrows, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo Karte" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, &logic->GerudoToken, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, &logic->MagicBean, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, &logic->MagicBeanPack, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, &logic->DoubleDefense, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Messer des Riesen" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegel-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein der Qualen" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo Karte" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DOUBLE_DEFENSE].SetCustomDrawFunc(Randomizer_DrawDoubleDefense); // Trade Quest Items - itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, &logic->WeirdEgg, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, &logic->ZeldasLetter, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Taschenei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, &logic->PocketEgg, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Cojiro" }, ITEMTYPE_ITEM, GI_COJIRO, true, &logic->Cojiro, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Seltsamer Pilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, &logic->OddMushroom, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Seltsamer Trank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, &logic->OddPoultice, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Wilderer-Säge" }, ITEMTYPE_ITEM, GI_SAW, true, &logic->PoachersSaw, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Schwert des gebrochenen Goronen" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, &logic->BrokenSword, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Verschreibung" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, &logic->Prescription, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Augapfel-Frosch" }, ITEMTYPE_ITEM, GI_FROG, true, &logic->EyeballFrog, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Supertropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, &logic->Eyedrops, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Quittung" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, &logic->ClaimCheck, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Taschenei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Cojiro" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Seltsamer Pilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Seltsamer Trank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Wilderer-Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Schwert des gebrochenen Goronen" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Verschreibung" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Augapfel-Frosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Supertropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Quittung" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Skulltula Token - itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, &logic->GoldSkulltulaTokens, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); + itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, &logic->ProgressiveHookshot, RHT_PROGRESSIVE_HOOKSHOT, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, &logic->ProgressiveStrength, RHT_PROGRESSIVE_STRENGTH, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, &logic->ProgressiveBombBag, RHT_PROGRESSIVE_BOMB_BAG, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, &logic->ProgressiveBow, RHT_PROGRESSIVE_BOW, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, &logic->ProgressiveBulletBag,RHT_PROGRESSIVE_SLINGSHOT, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Brieftasche" }, ITEMTYPE_ITEM, 0x85, true, &logic->ProgressiveWallet, RHT_PROGRESSIVE_WALLET, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Skala" }, ITEMTYPE_ITEM, 0x86, true, &logic->ProgressiveScale, RHT_PROGRESSIVE_SCALE, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, true, &logic->ProgressiveNutBag, RHT_PROGRESSIVE_NUT_UPGRADE, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, &logic->ProgressiveStickBag, RHT_PROGRESSIVE_STICK_UPGRADE, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Kriechgrube" }, ITEMTYPE_ITEM, 0x89, true, &logic->Bombchus, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_PROGRESSIVE_MAGIC_METER, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, &logic->ProgressiveOcarina, RHT_PROGRESSIVE_OCARINA, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronenschwert" }, ITEMTYPE_ITEM, 0xD4, true, &logic->ProgressiveGiantKnife,RHT_PROGRESSIVE_GORONSWORD, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Brieftasche" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Skala" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Kriechgrube" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronenschwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true); // Bottles - itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, &logic->Bottles, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, &logic->Bottles, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, &logic->Bottles, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, &logic->Bottles, RHT_BOTTLE_WITH_GREEN_POTION,RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, &logic->Bottles, RHT_BOTTLE_WITH_BLUE_POTION,RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, &logic->Bottles, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, &logic->Bottles, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, &logic->Bottles, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, &logic->Bottles, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, &logic->Bottles, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, &logic->RutosLetter, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER,GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, &logic->BottleWithBigPoe, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER,GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); // Songs - itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, &logic->ZeldasLullaby, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, &logic->EponasSong, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Sarias Lied" }, ITEMTYPE_SONG, 0xC3, true, &logic->SariasSong, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Das Lied der Sonne" }, ITEMTYPE_SONG, 0xC4, true, &logic->SunsSong, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Das Lied der Zeit" }, ITEMTYPE_SONG, 0xC5, true, &logic->SongOfTime, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Lied der Stürme" }, ITEMTYPE_SONG, 0xC6, true, &logic->SongOfStorms, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Wald-Minuett" }, ITEMTYPE_SONG, 0xBB, true, &logic->MinuetOfForest, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, &logic->BoleroOfFire, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, &logic->SerenadeOfWater, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne der Schatten " }, ITEMTYPE_SONG, 0xBF, true, &logic->NocturneOfShadow, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem des Geistes" }, ITEMTYPE_SONG, 0xBE, true, &logic->RequiemOfSpirit, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Präludium des Lichts" }, ITEMTYPE_SONG, 0xC0, true, &logic->PreludeOfLight, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Sarias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Das Lied der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Das Lied der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Lied der Stürme" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Wald-Minuett" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne der Schatten " }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem des Geistes" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Präludium des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, &logic->noVariable, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, &logic->noVariable, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, &logic->noVariable, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, &logic->noVariable, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, &logic->noVariable, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, &logic->noVariable, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, &logic->noVariable, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, &logic->noVariable, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &logic->noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &logic->noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &logic->noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &logic->noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &logic->noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &logic->noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &logic->noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &logic->noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &logic->noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &logic->noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, &logic->BossKeyForestTemple, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Feuertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x96, true, &logic->BossKeyFireTemple, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Feuertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Wassertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x97, true, &logic->BossKeyWaterTemple, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Wassertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Geistertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x98, true, &logic->BossKeySpiritTemple, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Geistertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Schlüssel für den Boss des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, &logic->BossKeyShadowTemple, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Schlüssel für den Boss des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Ganons Schloss-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x9A, true, &logic->BossKeyGanonsCastle, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Ganons Schloss-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Waldtempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xAF, true, &logic->ForestTempleKeys, RHT_FOREST_TEMPLE_SMALL_KEY,RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Waldtempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Feuertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB0, true, &logic->FireTempleKeys, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Feuertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Wassertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB1, true, &logic->WaterTempleKeys, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Wassertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Geisttempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB2, true, &logic->SpiritTempleKeys, RHT_SPIRIT_TEMPLE_SMALL_KEY,RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Geisttempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Schattentempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB3, true, &logic->ShadowTempleKeys, RHT_SHADOW_TEMPLE_SMALL_KEY,RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Schattentempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Boden des Brunnens Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB4, true, &logic->BottomOfTheWellKeys, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY,RG_BOTTOM_OF_THE_WELL_SMALL_KEY,OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Boden des Brunnens Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, Text{ "Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Trainingsgelände Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB5, true, &logic->GerudoTrainingGroundsKeys, RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY,RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY,OBJECT_GI_KEY,GID_KEY_SMALL,TEXT_RANDOMIZER_CUSTOM_ITEM,0x80, CHEST_ANIM_SHORT,ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, Text{ "Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Trainingsgelände Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Gerudo-Festung Kleiner Schlüssel" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, &logic->GerudoFortressKeys, RHT_GERUDO_FORTRESS_SMALL_KEY,RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Gerudo-Festung Kleiner Schlüssel" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Ganons Schloss Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB7, true, &logic->GanonsCastleKeys, RHT_GANONS_CASTLE_SMALL_KEY,RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Ganons Schloss Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, &logic->TreasureGameKeys, RHT_TREASURE_GAME_SMALL_KEY,ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE); + itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Waldtempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD5, true, &logic->ForestTempleKeys, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Waldtempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Feuertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD6, true, &logic->FireTempleKeys, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Feuertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Wassertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD7, true, &logic->WaterTempleKeys, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Wassertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Geisttempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD8, true, &logic->SpiritTempleKeys, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Geisttempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schattentempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD9, true, &logic->ShadowTempleKeys, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schattentempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Boden des Brunnens Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDA, true, &logic->BottomOfTheWellKeys, RHT_BOTTOM_OF_THE_WELL_KEY_RING,RG_BOTTOM_OF_THE_WELL_KEY_RING,OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Boden des Brunnens Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, Text{ "Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Trainingsgelände Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDB, true, &logic->GerudoTrainingGroundsKeys, RHT_GERUDO_TRAINING_GROUNDS_KEY_RING,RG_GERUDO_TRAINING_GROUNDS_KEY_RING,OBJECT_GI_KEY,GID_KEY_SMALL,TEXT_RANDOMIZER_CUSTOM_ITEM,0x80, CHEST_ANIM_SHORT,ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, Text{ "Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Trainingsgelände Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Gerudo Festung Schlüsselanhänger" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, &logic->GerudoFortressKeys, RHT_GERUDO_FORTRESS_KEY_RING,RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Gerudo Festung Schlüsselanhänger" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Ganons Schloss Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDD, true, &logic->GanonsCastleKeys, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Ganons Schloss Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, &logic->KokiriEmerald, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, &logic->GoronRuby, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, &logic->ZoraSapphire, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Wald Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, &logic->ForestMedallion, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST,0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Feuer Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, &logic->FireMedallion, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Wasser Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, &logic->WaterMedallion, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER,0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Geist Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, &logic->SpiritMedallion, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT,0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Schatten Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, &logic->ShadowMedallion, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW,0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Licht Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, &logic->LightMedallion, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT,0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Wald Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST,0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Feuer Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Wasser Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER,0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Geist Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT,0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Schatten Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW,0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Licht Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT,0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Generic Items - itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, &logic->noVariable, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüne Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, &logic->noVariable, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, &logic->Greg, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blaue Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, &logic->noVariable, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Rote Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, &logic->noVariable, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Lila Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, &logic->noVariable, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesige Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, &logic->noVariable, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, &logic->PieceOfHeart, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herz-Container" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2,true, &logic->HeartContainer, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, &logic->noVariable, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, &logic->noVariable, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Pez" }, ITEMTYPE_ITEM, GI_FISH, false, &logic->noVariable, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüne Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blaue Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Rote Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Lila Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesige Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herz-Container" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, LOGIC_NONE, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Pez" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); // Refills - itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, &logic->noVariable, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, &logic->noVariable, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBS_20] = Item(RG_BOMBS_20, Text{ "Bombs (20)", "Bombes (20)", "Bomben (20)" }, ITEMTYPE_REFILL, GI_BOMBS_20, false, &logic->noVariable, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Bombchus (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, &logic->Bombchus5, RHT_BOMBCHU_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Bombchus (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, &logic->Bombchus10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Bombchus (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, &logic->Bombchus20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_DROP] = Item(RG_BOMBCHU_DROP, Text{ "Bombchu Drop", "Drop Missiles", "Bombchus" }, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, &logic->BombchuDrop, RHT_NONE, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, &logic->noVariable, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, &logic->noVariable, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, &logic->noVariable, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, &logic->noVariable, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, &logic->noVariable, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, &logic->noVariable, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stick (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, &logic->noVariable, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Rotes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_RED, false, &logic->noVariable, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Grünes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, &logic->noVariable, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Blaues Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, &logic->noVariable, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, LOGIC_NONE, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, LOGIC_NONE, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_20] = Item(RG_BOMBS_20, Text{ "Bombs (20)", "Bombes (20)", "Bomben (20)" }, ITEMTYPE_REFILL, GI_BOMBS_20, false, LOGIC_NONE, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Bombchus (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, LOGIC_BOMBCHUS_5, RHT_BOMBCHU_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Bombchus (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, LOGIC_BOMBCHUS_10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Bombchus (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, LOGIC_BOMBCHUS_20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_DROP] = Item(RG_BOMBCHU_DROP, Text{ "Bombchu Drop", "Drop Missiles", "Bombchus" }, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, LOGIC_BOMBCHU_DROP, RHT_NONE, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, LOGIC_NONE, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, LOGIC_NONE, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, LOGIC_NONE, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, LOGIC_NONE, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stick (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Rotes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Grünes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Blaues Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); // Treasure Game - itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhen-Minispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, &logic->PieceOfHeart, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüne Rupie (Schatztruhe-Minispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE,false, &logic->noVariable, RHT_TREASURE_GAME_GREEN_RUPEE,ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhen-Minispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüne Rupie (Schatztruhe-Minispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE,ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); // Shop - itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuss kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, &logic->Nuts, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15); - itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, &logic->BuyArrow, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60); - itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, &logic->BuyArrow, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90); - itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, &logic->BuyBomb, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25); - itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuss kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, &logic->Nuts, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stick kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, &logic->Sticks, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, &logic->BuyBomb, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, &logic->FishAccess, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200); - itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &logic->noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, &logic->BuyMagicPotion, RHT_BOTTLE_WITH_GREEN_POTION,ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, &logic->BuyMagicPotion, RHT_BOTTLE_WITH_BLUE_POTION,ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100); - itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylianischer Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, &logic->HylianShield, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80); - itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, &logic->DekuShield, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40); - itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, &logic->GoronTunic, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200); - itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, &logic->ZoraTunic, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300); - itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, &logic->noVariable, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBCHU_10] = Item(RG_BUY_BOMBCHU_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Bomchu kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, &logic->BuyBombchus, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); - itemTable[RG_BUY_BOMBCHU_20] = Item(RG_BUY_BOMBCHU_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Bomchu kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, &logic->BuyBombchus, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); - itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, &logic->BuySeed, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, &logic->noVariable, RHT_NONE, false, 0); - itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, &logic->BlueFireAccess, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); - itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, &logic->BugsAccess, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, &logic->noVariable, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, &logic->FairyAccess, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, &logic->BuyArrow, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20); - itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, &logic->BuyBomb, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80); - itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, &logic->BuyBomb, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120); - itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, &logic->BuyBomb, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35); - itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &logic->noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); - itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &logic->noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuss kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15); + itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60); + itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90); + itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25); + itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuss kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stick kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); + itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200); + itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100); + itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylianischer Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80); + itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40); + itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200); + itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300); + itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); + itemTable[RG_BUY_BOMBCHU_10] = Item(RG_BUY_BOMBCHU_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Bomchu kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); + itemTable[RG_BUY_BOMBCHU_20] = Item(RG_BUY_BOMBCHU_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Bomchu kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); + itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, false, 0); + itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); + itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20); + itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80); + itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120); + itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35); + itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); + itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); // Misc. - itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "", "" }, ITEMTYPE_ITEM, 0xE0, true, &logic->CanSummonGohma, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "", "" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE1, true, &logic->CanSummonKingDodongo,RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_KING_DODONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "", "" }, ITEMTYPE_ITEM, 0xE2, true, &logic->CanSummonBarinade, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "", "" }, ITEMTYPE_ITEM, 0xE2, true, LOGIC_CAN_SUMMON_BARINADE, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BARINADE_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE3, true, &logic->CanSummonPhantomGanon,RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE3, true, LOGIC_CAN_SUMMON_PHANTOMGANON, RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_PHANTOM_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "", "" }, ITEMTYPE_ITEM, 0xE4, true, &logic->CanSummonVolvagia, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "", "" }, ITEMTYPE_ITEM, 0xE4, true, LOGIC_CAN_SUMMON_VOLVAGIA, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_VOLVAGIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "", "" }, ITEMTYPE_ITEM, 0xE5, true, &logic->CanSummonMorpha, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "", "" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MORPHA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE6, true, &logic->CanSummonBongoBongo, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE6, true, LOGIC_CAN_SUMMON_BONGOBONGO, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BONGO_BONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "", "" }, ITEMTYPE_ITEM, 0xE7, true, &logic->CanSummonTwinrova, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "", "" }, ITEMTYPE_ITEM, 0xE7, true, LOGIC_CAN_SUMMON_TWINROVA, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE8, true, &logic->CanSummonGanon, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Caña de Pescar" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, &logic->FishingPole, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Caña de Pescar" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI); - itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Botón A de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &logic->OcarinaAButton, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Botón A de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_A_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Botón C superior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &logic->OcarinaCUpButton, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Botón C superior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_UP_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Botón C inferior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &logic->OcarinaCDownButton, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Botón C inferior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_DOWN_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Botón C izquierdo de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &logic->OcarinaCLeftButton, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Botón C izquierdo de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_LEFT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Botón C derecho de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &logic->OcarinaCRightButton, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Botón C derecho de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveWallet, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, &logic->ProgressiveBow, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, &logic->ProgressiveBombBag, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, &logic->ProgressiveBulletBag, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, &logic->noVariable, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_NUT_UPGRADE_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, &logic->noVariable, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_MAGIC_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, &logic->ProgressiveMagic, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, &logic->Bombchus, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, &logic->ProgressiveWallet, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_MAGIC_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &logic->SkeletonKey, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); - itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, &logic->ProgressiveStickBag, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, &logic->ProgressiveNutBag, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, &logic->noVariable, RHT_NONE); - itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, &logic->noVariable, RHT_NONE); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE); + itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) - itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, &logic->ProgressiveHookshot, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, &logic->ProgressiveHookshot, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, &logic->ProgressiveOcarina, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, &logic->ProgressiveOcarina, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, &logic->ProgressiveBombBag, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, &logic->ProgressiveBombBag, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, &logic->ProgressiveBombBag, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, &logic->ProgressiveBow, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, &logic->ProgressiveBow, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, &logic->ProgressiveBow, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, &logic->ProgressiveBulletBag,RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Großer Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, &logic->ProgressiveBulletBag,RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, &logic->ProgressiveBulletBag,RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, &logic->ProgressiveStrength, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberne Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER,true, &logic->ProgressiveStrength, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER,0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldene Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, &logic->ProgressiveStrength, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Skala" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveScale, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Skala" }, ITEMTYPE_ITEM, GI_SCALE_GOLD, true, &logic->ProgressiveScale, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsene Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, &logic->ProgressiveWallet, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, &logic->ProgressiveWallet, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Reiche Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, &logic->ProgressiveWallet, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Bourse de Magnat", "Reiche Geldbörse" },/*FIXME: still says tycoon in french & german*/ ITEMTYPE_ITEM, RG_CHILD_WALLET, true, &logic->ProgressiveWallet, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, &logic->ProgressiveNutBag, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, &logic->ProgressiveNutBag, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20,true, &logic->ProgressiveStickBag, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30,true, &logic->ProgressiveStickBag, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, &logic->ProgressiveMagic, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, &logic->TriforcePieces, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Großer Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberne Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldene Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Skala" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Skala" }, ITEMTYPE_ITEM, GI_SCALE_GOLD, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsene Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Reiche Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Bourse de Magnat", "Reiche Geldbörse" },/*FIXME: still says tycoon in french & german*/ ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); // Init itemNameToEnum for (auto& item : itemTable) { diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 49f611f0e..3814e12c5 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -8,6 +8,7 @@ #include "dungeon.h" #include "context.h" +#include namespace Rando { bool Logic::IsMagicItem(RandomizerGet item) { @@ -24,52 +25,187 @@ namespace Rando { } bool Logic::HasItem(RandomizerGet itemName) { - return (itemName == RG_DINS_FIRE && DinsFire) || - (itemName == RG_FARORES_WIND && FaroresWind) || - (itemName == RG_NAYRUS_LOVE && NayrusLove) || - (itemName == RG_LENS_OF_TRUTH && LensOfTruth) || - (itemName == RG_FAIRY_BOW && Bow) || - (itemName == RG_MEGATON_HAMMER && Hammer) || - (itemName == RG_IRON_BOOTS && IronBoots) || - (itemName == RG_HOVER_BOOTS && HoverBoots) || - (itemName == RG_HOOKSHOT && Hookshot) || - (itemName == RG_LONGSHOT && Longshot) || - (itemName == RG_SILVER_GAUNTLETS && SilverGauntlets) || - (itemName == RG_GOLDEN_GAUNTLETS && GoldenGauntlets) || - (itemName == RG_GORON_TUNIC && GoronTunic) || - (itemName == RG_ZORA_TUNIC && ZoraTunic) || - (itemName == RG_SCARECROW && Scarecrow) || - (itemName == RG_DISTANT_SCARECROW && DistantScarecrow) || - (itemName == RG_HYLIAN_SHIELD && HylianShield) || - (itemName == RG_MIRROR_SHIELD && MirrorShield) || - (itemName == RG_MASTER_SWORD && MasterSword) || - (itemName == RG_BIGGORON_SWORD && BiggoronSword) || - (itemName == RG_FAIRY_SLINGSHOT && Slingshot) || - (itemName == RG_BOOMERANG && Boomerang) || - (itemName == RG_KOKIRI_SWORD && KokiriSword) || - (itemName == RG_STICKS && Sticks) || - (itemName == RG_DEKU_SHIELD && DekuShield) || - (itemName == RG_FIRE_ARROWS && FireArrows) || - (itemName == RG_ICE_ARROWS && IceArrows) || - (itemName == RG_LIGHT_ARROWS && LightArrows) || - (itemName == RG_OCARINA_A_BUTTON && OcarinaAButton) || - (itemName == RG_OCARINA_C_LEFT_BUTTON && OcarinaCLeftButton) || - (itemName == RG_OCARINA_C_RIGHT_BUTTON && OcarinaCRightButton) || - (itemName == RG_OCARINA_C_DOWN_BUTTON && OcarinaCDownButton) || - (itemName == RG_OCARINA_C_UP_BUTTON && OcarinaCUpButton) || - (itemName == RG_FISHING_POLE && FishingPole) || - (itemName == RG_ZELDAS_LULLABY && ZeldasLullaby) || - (itemName == RG_EPONAS_SONG && EponasSong) || - (itemName == RG_SARIAS_SONG && SariasSong) || - (itemName == RG_SUNS_SONG && SunsSong) || - (itemName == RG_SONG_OF_TIME && SongOfTime) || - (itemName == RG_SONG_OF_STORMS && SongOfStorms) || - (itemName == RG_MINUET_OF_FOREST && MinuetOfForest) || - (itemName == RG_BOLERO_OF_FIRE && BoleroOfFire) || - (itemName == RG_SERENADE_OF_WATER && SerenadeOfWater) || - (itemName == RG_REQUIEM_OF_SPIRIT && RequiemOfSpirit) || - (itemName == RG_NOCTURNE_OF_SHADOW && NocturneOfShadow) || - (itemName == RG_PRELUDE_OF_LIGHT && PreludeOfLight); + switch (itemName) { + case RG_FAIRY_OCARINA: + return ctx->CheckInventory(ITEM_OCARINA_FAIRY, false); + case RG_OCARINA_OF_TIME: + return ctx->CheckInventory(ITEM_OCARINA_TIME, true); + case RG_DINS_FIRE: + return ctx->CheckInventory(ITEM_DINS_FIRE, true); + case RG_FARORES_WIND: + return ctx->CheckInventory(ITEM_FARORES_WIND, true); + case RG_NAYRUS_LOVE: + return ctx->CheckInventory(ITEM_NAYRUS_LOVE, true); + case RG_LENS_OF_TRUTH: + return ctx->CheckInventory(ITEM_LENS, true); + case RG_FAIRY_BOW: + return ctx->CheckInventory(ITEM_BOW, true); + case RG_MEGATON_HAMMER: + return ctx->CheckInventory(ITEM_HAMMER, true); + case RG_HOOKSHOT: + return ctx->CheckInventory(ITEM_HOOKSHOT, false); + case RG_LONGSHOT: + return ctx->CheckInventory(ITEM_LONGSHOT, true); + case RG_PROGRESSIVE_STICK_UPGRADE: + case RG_STICKS: + return ctx->CurrentUpgrade(UPG_STICKS); + case RG_FIRE_ARROWS: + return ctx->CheckInventory(ITEM_ARROW_FIRE, true); + case RG_ICE_ARROWS: + return ctx->CheckInventory(ITEM_ARROW_ICE, true); + case RG_LIGHT_ARROWS: + return ctx->CheckInventory(ITEM_ARROW_LIGHT, true); + case RG_PROGRESSIVE_BOMBCHUS: + return ctx->CheckInventory(ITEM_BOMBCHU, true); + case RG_FAIRY_SLINGSHOT: + return ctx->CheckInventory(ITEM_SLINGSHOT, true); + case RG_BOOMERANG: + return ctx->CheckInventory(ITEM_BOOMERANG, true); + case RG_PROGRESSIVE_NUT_UPGRADE: + case RG_NUTS: + return ctx->CurrentUpgrade(UPG_NUTS); + case RG_SCARECROW: + return Scarecrow; + case RG_DISTANT_SCARECROW: + return DistantScarecrow; + case RG_KOKIRI_SWORD: + case RG_DEKU_SHIELD: + case RG_GORON_TUNIC: + case RG_ZORA_TUNIC: + case RG_HYLIAN_SHIELD: + case RG_MIRROR_SHIELD: + case RG_MASTER_SWORD: + case RG_BIGGORON_SWORD: + case RG_IRON_BOOTS: + case RG_HOVER_BOOTS: + return ctx->CheckEquipment(Context::RandoGetToEquipFlag.at(itemName)); + case RG_GORONS_BRACELET: + return ctx->CurrentUpgrade(UPG_STRENGTH); + case RG_SILVER_GAUNTLETS: + return ctx->CurrentUpgrade(UPG_STRENGTH) >= 2; + case RG_GOLDEN_GAUNTLETS: + return ctx->CurrentUpgrade(UPG_STRENGTH) >= 3; + case RG_PROGRESSIVE_BOMB_BAG: + case RG_BOMB_BAG: + return ctx->CurrentUpgrade(UPG_BOMB_BAG); + case RG_MAGIC_SINGLE: + return ctx->GetSaveContext()->magicLevel >= 1; + // Songs + case RG_ZELDAS_LULLABY: + case RG_EPONAS_SONG: + case RG_SARIAS_SONG: + case RG_SUNS_SONG: + case RG_SONG_OF_TIME: + case RG_SONG_OF_STORMS: + case RG_MINUET_OF_FOREST: + case RG_BOLERO_OF_FIRE: + case RG_SERENADE_OF_WATER: + case RG_REQUIEM_OF_SPIRIT: + case RG_NOCTURNE_OF_SHADOW: + case RG_PRELUDE_OF_LIGHT: + // Dungeon Rewards + case RG_KOKIRI_EMERALD: + case RG_GORON_RUBY: + case RG_ZORA_SAPPHIRE: + case RG_FOREST_MEDALLION: + case RG_FIRE_MEDALLION: + case RG_WATER_MEDALLION: + case RG_SPIRIT_MEDALLION: + case RG_SHADOW_MEDALLION: + case RG_LIGHT_MEDALLION: + // Misc Quest Items + case RG_STONE_OF_AGONY: + case RG_GERUDO_MEMBERSHIP_CARD: + return ctx->CheckQuestItem(Context::RandoGetToQuestItem.at(itemName)); + case RG_RUTOS_LETTER: + return ctx->CheckEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); + case RG_DOUBLE_DEFENSE: + return ctx->GetSaveContext()->isDoubleDefenseAcquired; + case RG_FISHING_POLE: + case RG_ZELDAS_LETTER: + case RG_WEIRD_EGG: + case RG_GREG_RUPEE: + // Ocarina Buttons + case RG_OCARINA_A_BUTTON: + case RG_OCARINA_C_LEFT_BUTTON: + case RG_OCARINA_C_RIGHT_BUTTON: + case RG_OCARINA_C_DOWN_BUTTON: + case RG_OCARINA_C_UP_BUTTON: + // Boss Souls + case RG_GOHMA_SOUL: + case RG_KING_DODONGO_SOUL: + case RG_BARINADE_SOUL: + case RG_PHANTOM_GANON_SOUL: + case RG_VOLVAGIA_SOUL: + case RG_MORPHA_SOUL: + case RG_BONGO_BONGO_SOUL: + case RG_TWINROVA_SOUL: + case RG_GANON_SOUL: + case RG_SKELETON_KEY: + return ctx->CheckRandoInf(Context::RandoGetToRandInf.at(itemName)); + // Boss Keys + case RG_FOREST_TEMPLE_BOSS_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + case RG_GANONS_CASTLE_BOSS_KEY: + return ctx->CheckDungeonItem(DUNGEON_KEY_BOSS, Context::RandoGetToDungeonScene.at(itemName)); + // Maps + case RG_DEKU_TREE_MAP: + case RG_DODONGOS_CAVERN_MAP: + case RG_JABU_JABUS_BELLY_MAP: + case RG_FOREST_TEMPLE_MAP: + case RG_FIRE_TEMPLE_MAP: + case RG_WATER_TEMPLE_MAP: + case RG_SPIRIT_TEMPLE_MAP: + case RG_SHADOW_TEMPLE_MAP: + case RG_BOTTOM_OF_THE_WELL_MAP: + case RG_ICE_CAVERN_MAP: + return ctx->CheckDungeonItem(DUNGEON_MAP, Context::RandoGetToDungeonScene.at(itemName)); + // Compasses + case RG_DEKU_TREE_COMPASS: + case RG_DODONGOS_CAVERN_COMPASS: + case RG_JABU_JABUS_BELLY_COMPASS: + case RG_FOREST_TEMPLE_COMPASS: + case RG_FIRE_TEMPLE_COMPASS: + case RG_WATER_TEMPLE_COMPASS: + case RG_SPIRIT_TEMPLE_COMPASS: + case RG_SHADOW_TEMPLE_COMPASS: + case RG_BOTTOM_OF_THE_WELL_COMPASS: + case RG_ICE_CAVERN_COMPASS: + return ctx->CheckDungeonItem(DUNGEON_COMPASS, Context::RandoGetToDungeonScene.at(itemName)); + // Wallets + case RG_CHILD_WALLET: + return ctx->CheckRandoInf(RAND_INF_HAS_WALLET); + case RG_ADULT_WALLET: + return ctx->CurrentUpgrade(UPG_WALLET) >= 1; + case RG_GIANT_WALLET: + return ctx->CurrentUpgrade(UPG_WALLET) >= 2; + case RG_TYCOON_WALLET: + return ctx->CurrentUpgrade(UPG_WALLET) >= 3; + // Scales + case RG_BRONZE_SCALE: + return ctx->CheckRandoInf(RAND_INF_CAN_SWIM); + case RG_SILVER_SCALE: + return ctx->CurrentUpgrade(UPG_SCALE) >= 1; + case RG_GOLDEN_SCALE: + return ctx->CurrentUpgrade(UPG_SCALE) >= 2; + case RG_POCKET_EGG: + case RG_COJIRO: + case RG_ODD_MUSHROOM: + case RG_ODD_POTION: + case RG_POACHERS_SAW: + case RG_BROKEN_SWORD: + case RG_PRESCRIPTION: + case RG_EYEBALL_FROG: + case RG_EYEDROPS: + case RG_CLAIM_CHECK: + return ctx->HasAdultTrade(StaticData::RetrieveItem(itemName).GetGIEntry()->itemId); + } + SPDLOG_ERROR("HasItem reached `return false;`. Missing case for RandomizerGet of {}", static_cast(itemName)); + assert(false); + return false; } //Can the passed in item be used? @@ -124,37 +260,62 @@ namespace Rando { return IsChild;// || StickAsAdult; case RG_DEKU_SHIELD: return IsChild;// || DekuShieldAsAdult; + case RG_WEIRD_EGG: + return IsChild; + case RG_RUTOS_LETTER: + return IsChild; + + // Adult Trade + case RG_POCKET_EGG: + return IsAdult; + case RG_COJIRO: + return IsAdult; + case RG_ODD_MUSHROOM: + return IsAdult; + case RG_ODD_POTION: + return IsAdult; + case RG_POACHERS_SAW: + return IsAdult; + case RG_BROKEN_SWORD: + return IsAdult; + case RG_PRESCRIPTION: + return IsAdult; + case RG_EYEBALL_FROG: + return IsAdult; + case RG_EYEDROPS: + return IsAdult; + case RG_CLAIM_CHECK: + return IsAdult; // Songs case RG_ZELDAS_LULLABY: - return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton; + return Ocarina && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); case RG_EPONAS_SONG: - return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton; + return Ocarina && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); case RG_SARIAS_SONG: - return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_SUNS_SONG: - return Ocarina && OcarinaCRightButton && OcarinaCUpButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_SONG_OF_TIME: - return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_SONG_OF_STORMS: - return Ocarina && OcarinaAButton && OcarinaCUpButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_MINUET_OF_FOREST: - return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); case RG_BOLERO_OF_FIRE: - return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_SERENADE_OF_WATER: - return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_REQUIEM_OF_SPIRIT: - return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_NOCTURNE_OF_SHADOW: - return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton; + return Ocarina && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); case RG_PRELUDE_OF_LIGHT: - return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton; + return Ocarina && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); // Misc. Items - // TODO: Once child wallet shuffle is added, this will need to be updated to account for the fishing pond entry fee. case RG_FISHING_POLE: - return true; // as long as you have enough rubies + return HasItem(RG_CHILD_WALLET); // as long as you have enough rubies // Magic items default: @@ -171,31 +332,23 @@ namespace Rando { } bool Logic::HasBossSoul(RandomizerGet itemName) { - auto ctx = Rando::Context::GetInstance(); if (!ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS)) { return true; } switch(itemName) { case RG_GOHMA_SOUL: - return CanSummonGohma; case RG_KING_DODONGO_SOUL: - return CanSummonKingDodongo; case RG_BARINADE_SOUL: - return CanSummonBarinade; case RG_PHANTOM_GANON_SOUL: - return CanSummonPhantomGanon; case RG_VOLVAGIA_SOUL: - return CanSummonVolvagia; case RG_MORPHA_SOUL: - return CanSummonMorpha; case RG_BONGO_BONGO_SOUL: - return CanSummonBongoBongo; case RG_TWINROVA_SOUL: - return CanSummonTwinrova; + return HasItem(itemName); case RG_GANON_SOUL: - return ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON) ? CanSummonGanon : true; + return ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON) ? HasItem(RG_GANON_SOUL) : true; default: - break; + return false; } } @@ -223,7 +376,7 @@ namespace Rando { case GlitchType::EquipSwap: // todo: add bunny hood to adult item equippable list and child trade item to child item equippable list return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || - (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && false; //GlitchEquipSwap; + ctx->GetAmmo(ITEM_BEAN) > 0 || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && false; //GlitchEquipSwap; } //Shouldn't be reached @@ -254,33 +407,116 @@ namespace Rando { } + uint8_t Logic::BottleCount() { + uint8_t count = 0; + for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) { + uint8_t item = ctx->GetSaveContext()->inventory.items[i]; + if (item != ITEM_NONE && (item != ITEM_LETTER_RUTO || (item == ITEM_LETTER_RUTO && DeliverLetter)) && item != ITEM_BIG_POE) { + count++; + } + } + return count; + } + // Updates all logic helpers. Should be called whenever a non-helper is changed void Logic::UpdateHelpers() { - auto ctx = Rando::Context::GetInstance(); - OcarinaButtons = (OcarinaAButton ? 1 : 0) + - (OcarinaCLeftButton ? 1 : 0) + - (OcarinaCRightButton ? 1 : 0) + - (OcarinaCUpButton ? 1 : 0) + - (OcarinaCDownButton ? 1 : 0); - NumBottles = ((NoBottles) ? 0 : (Bottles + ((DeliverLetter) ? 1 : 0))); + OcarinaButtons = (HasItem(RG_OCARINA_A_BUTTON) ? 1 : 0) + + (HasItem(RG_OCARINA_C_LEFT_BUTTON) ? 1 : 0) + + (HasItem(RG_OCARINA_C_RIGHT_BUTTON) ? 1 : 0) + + (HasItem(RG_OCARINA_C_UP_BUTTON) ? 1 : 0) + + (HasItem(RG_OCARINA_C_DOWN_BUTTON) ? 1 : 0); + ZeldasLetter = HasItem(RG_ZELDAS_LETTER); + WeirdEgg = CanUse(RG_WEIRD_EGG); + Bombchus = HasItem(RG_PROGRESSIVE_BOMBCHUS); + BuySeed = GetInLogic(LOGIC_BUY_SEED); + BuyArrow = GetInLogic(LOGIC_BUY_ARROW); + BuyBomb = GetInLogic(LOGIC_BUY_BOMB); + BuyMagicPotion = GetInLogic(LOGIC_BUY_MAGIC_POTION); + BuyBombchus = GetInLogic(LOGIC_BUY_BOMBCHUS); + MagicBean = ctx->GetAmmo(ITEM_BEAN) > 0; + RutosLetter = CanUse(RG_RUTOS_LETTER); + Boomerang = CanUse(RG_BOOMERANG); + DinsFire = CanUse(RG_DINS_FIRE); + FaroresWind = CanUse(RG_FARORES_WIND); + NayrusLove = CanUse(RG_NAYRUS_LOVE); + LensOfTruth = CanUse(RG_LENS_OF_TRUTH); + ShardOfAgony = HasItem(RG_STONE_OF_AGONY); + //SkullMask = false; + //MaskOfTruth = false; + + //Adult logic + Hammer = CanUse(RG_MEGATON_HAMMER); + IronBoots = CanUse(RG_IRON_BOOTS); + HoverBoots = CanUse(RG_HOVER_BOOTS); + DekuShield = CanUse(RG_DEKU_SHIELD); + HylianShield = CanUse(RG_HYLIAN_SHIELD); + MirrorShield = CanUse(RG_MIRROR_SHIELD); + GoronTunic = CanUse(RG_GORON_TUNIC); + ZoraTunic = CanUse(RG_ZORA_TUNIC); + //Epona = false; + //BigPoe = false; + GerudoToken = HasItem(RG_GERUDO_MEMBERSHIP_CARD); + FireArrows = CanUse(RG_FIRE_ARROWS); + IceArrows = CanUse(RG_ICE_ARROWS); + LightArrows = CanUse(RG_LIGHT_ARROWS); + KokiriSword = CanUse(RG_KOKIRI_SWORD); + MasterSword = CanUse(RG_MASTER_SWORD); + BiggoronSword = CanUse(RG_MASTER_SWORD); + NumBottles = ((NoBottles) ? 0 : BottleCount()); HasBottle = NumBottles >= 1; - Slingshot = (ProgressiveBulletBag >= 1) && (BuySeed || AmmoCanDrop); - Ocarina = ProgressiveOcarina >= 1; - OcarinaOfTime = ProgressiveOcarina >= 2; - MagicMeter = (ProgressiveMagic >= 1) && (AmmoCanDrop || (HasBottle && BuyMagicPotion)); - BombBag = (ProgressiveBombBag >= 1) && (BuyBomb || AmmoCanDrop); - Hookshot = ProgressiveHookshot >= 1; - Longshot = ProgressiveHookshot >= 2; - Bow = (ProgressiveBow >= 1) && (BuyArrow || AmmoCanDrop); - GoronBracelet = ProgressiveStrength >= 1; - SilverGauntlets = ProgressiveStrength >= 2; - GoldenGauntlets = ProgressiveStrength >= 3; - Swim = ProgressiveScale >= 1; - SilverScale = ProgressiveScale >= 2; - GoldScale = ProgressiveScale >= 3; - ChildsWallet = ProgressiveWallet >= 1; - AdultsWallet = ProgressiveWallet >= 2; - BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2; + Slingshot = CanUse(RG_FAIRY_SLINGSHOT) && (BuySeed || AmmoCanDrop); + Ocarina = HasItem(RG_FAIRY_OCARINA); + OcarinaOfTime = HasItem(RG_OCARINA_OF_TIME); + MagicMeter = HasItem(RG_MAGIC_SINGLE) && (AmmoCanDrop || (HasBottle && BuyMagicPotion)); + BombBag = HasItem(RG_BOMB_BAG) && (BuyBomb || AmmoCanDrop); + Hookshot = CanUse(RG_HOOKSHOT); + Longshot = CanUse(RG_LONGSHOT); + Bow = CanUse(RG_FAIRY_BOW) && (BuyArrow || AmmoCanDrop); + GoronBracelet = HasItem(RG_GORONS_BRACELET); + SilverGauntlets = HasItem(RG_SILVER_GAUNTLETS); + GoldenGauntlets = HasItem(RG_GOLDEN_GAUNTLETS); + Swim = HasItem(RG_BRONZE_SCALE); + SilverScale = HasItem(RG_SILVER_SCALE); + GoldScale = HasItem(RG_GOLDEN_SCALE); + ChildsWallet = HasItem(RG_CHILD_WALLET); + AdultsWallet = HasItem(RG_ADULT_WALLET); + BiggoronSword = HasItem(RG_BIGGORON_SWORD); + + ProgressiveScale = ctx->CurrentUpgrade(UPG_SCALE) + HasItem(RG_BRONZE_SCALE); + ProgressiveWallet = ctx->CurrentUpgrade(UPG_WALLET) + HasItem(RG_CHILD_WALLET); + + CanSummonGohma = HasBossSoul(RG_GOHMA_SOUL); + CanSummonKingDodongo = HasBossSoul(RG_KING_DODONGO_SOUL); + CanSummonBarinade = HasBossSoul(RG_BARINADE_SOUL); + CanSummonPhantomGanon = HasBossSoul(RG_PHANTOM_GANON_SOUL); + CanSummonVolvagia = HasBossSoul(RG_VOLVAGIA_SOUL); + CanSummonMorpha = HasBossSoul(RG_MORPHA_SOUL); + CanSummonBongoBongo = HasBossSoul(RG_BONGO_BONGO_SOUL); + CanSummonTwinrova = HasBossSoul(RG_TWINROVA_SOUL); + CanSummonGanon = HasBossSoul(RG_GANON_SOUL); + + // Boss Keys + BossKeyForestTemple = HasItem(RG_FOREST_TEMPLE_BOSS_KEY); + BossKeyFireTemple = HasItem(RG_FIRE_TEMPLE_BOSS_KEY); + BossKeyWaterTemple = HasItem(RG_WATER_TEMPLE_BOSS_KEY); + BossKeySpiritTemple = HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY); + BossKeyShadowTemple = HasItem(RG_SHADOW_TEMPLE_BOSS_KEY); + BossKeyGanonsCastle = HasItem(RG_GANONS_CASTLE_BOSS_KEY); + + KokiriEmerald = HasItem(RG_KOKIRI_EMERALD); + GoronRuby = HasItem(RG_GORON_RUBY); + ZoraSapphire = HasItem(RG_ZORA_SAPPHIRE); + ForestMedallion = HasItem(RG_FOREST_MEDALLION); + FireMedallion = HasItem(RG_FIRE_MEDALLION); + WaterMedallion = HasItem(RG_WATER_MEDALLION); + SpiritMedallion = HasItem(RG_SPIRIT_MEDALLION); + ShadowMedallion = HasItem(RG_SHADOW_MEDALLION); + LightMedallion = HasItem(RG_LIGHT_MEDALLION); + + DoubleDefense = HasItem(RG_DOUBLE_DEFENSE); + TriforcePieces = ctx->GetSaveContext()->triforcePiecesCollected; + Greg = HasItem(RG_GREG_RUPEE); + GoldSkulltulaTokens = ctx->GetGSCount(); //you need at least 2 buttons for scarecrow song ScarecrowSong = ScarecrowSong || (ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) && Ocarina && OcarinaButtons >= 2) || (ChildScarecrow && AdultScarecrow); @@ -290,21 +526,22 @@ namespace Rando { //Drop Access DekuStickDrop = StickPot || DekuBabaSticks; DekuNutDrop = (NutPot || NutCrate || DekuBabaNuts) && AmmoCanDrop; - BugsAccess = BugShrub || WanderingBugs || BugRock; - FishAccess = LoneFish || FishGroup; - FairyAccess = FairyPot || GossipStoneFairy || BeanPlantFairy || ButterflyFairy || FreeFairies || FairyPond; + BugsAccess = BugShrub || WanderingBugs || BugRock || GetInLogic(LOGIC_BUGS_ACCESS); + FishAccess = LoneFish || FishGroup || GetInLogic(LOGIC_FISH_ACCESS); + FairyAccess = FairyPot || GossipStoneFairy || BeanPlantFairy || ButterflyFairy || FreeFairies || FairyPond || GetInLogic(LOGIC_FAIRY_ACCESS); //refills - Bombs = BombBag; - Nuts = (ProgressiveNutBag != 0 && DekuNutDrop) || Nuts; - Sticks = (ProgressiveStickBag != 0 && DekuStickDrop) || Sticks; + Bombs = HasItem(RG_PROGRESSIVE_BOMB_BAG); + Nuts = DekuNutDrop || HasItem(RG_NUTS); + Sticks = DekuStickDrop || HasItem(RG_STICKS); Bugs = HasBottle && BugsAccess; + BlueFireAccess = BlueFireAccess || GetInLogic(LOGIC_BLUE_FIRE_ACCESS); BlueFire = (HasBottle && BlueFireAccess) || (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && CanUse(RG_ICE_ARROWS)); Fish = HasBottle && FishAccess; Fairy = HasBottle && FairyAccess; - FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20) && (BombBag || ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)); + FoundBombchus = Bombchus && (BombBag || ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)); CanPlayBowling = ChildsWallet && ((ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && FoundBombchus) || (!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && BombBag)); // TODO: Implement Ammo Drop Setting in place of bombchu drops HasBombchus = (BuyBombchus || (ctx->GetOption(RSK_ENABLE_BOMBCHU_DROPS).Is(RO_AMMO_DROPS_ON/*_PLUS_BOMBCHU*/) && FoundBombchus)); @@ -314,15 +551,16 @@ namespace Rando { HasBoots = IronBoots || HoverBoots; //Unshuffled adult trade quest - Eyedrops = Eyedrops || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && ClaimCheck); - EyeballFrog = EyeballFrog || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Eyedrops); - Prescription = Prescription || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && EyeballFrog); - BrokenSword = BrokenSword || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Prescription); - PoachersSaw = PoachersSaw || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && BrokenSword); - OddPoultice = OddPoultice || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && PoachersSaw); - OddMushroom = OddMushroom || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddPoultice); - Cojiro = Cojiro || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddMushroom); - PocketEgg = PocketEgg || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Cojiro); + ClaimCheck = CanUse(RG_CLAIM_CHECK); + Eyedrops = CanUse(RG_EYEDROPS) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && ClaimCheck); + EyeballFrog = CanUse(RG_EYEBALL_FROG) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Eyedrops); + Prescription = CanUse(RG_PRESCRIPTION) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && EyeballFrog); + BrokenSword = CanUse(RG_BROKEN_SWORD) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Prescription); + PoachersSaw = CanUse(RG_POACHERS_SAW) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && BrokenSword); + OddPoultice = CanUse(RG_ODD_POTION) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && PoachersSaw); + OddMushroom = CanUse(RG_ODD_MUSHROOM) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddPoultice); + Cojiro = CanUse(RG_COJIRO) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddMushroom); + PocketEgg = CanUse(RG_POCKET_EGG) || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Cojiro); // IsChild = Age == AGE_CHILD; // IsAdult = Age == AGE_ADULT; @@ -340,7 +578,7 @@ namespace Rando { CanRideEpona = IsAdult && Epona && CanUse(RG_EPONAS_SONG); CanSummonGossipFairyWithoutSuns = CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME); CanSummonGossipFairy = CanSummonGossipFairyWithoutSuns || CanUse(RG_SUNS_SONG); - Hearts = BaseHearts + HeartContainer + (PieceOfHeart >> 2); + Hearts = ctx->GetSaveContext()->healthCapacity / 16; EffectiveHealth = ((Hearts << (2 + DoubleDefense)) >> Multiplier) + ((Hearts << (2 + DoubleDefense)) % (1 << Multiplier) > 0); //Number of half heart hits to die, ranges from 1 to 160 FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0; WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0; @@ -348,14 +586,13 @@ namespace Rando { CanSurviveDamage = !NeedNayrusLove || CanUse(RG_NAYRUS_LOVE); CanTakeDamage = Fairy || CanSurviveDamage; CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(RG_NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2); - //CanPlantBean = IsChild && (MagicBean || MagicBeanPack); CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY)); CanOpenStormGrotto = CanUse(RG_SONG_OF_STORMS) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY)); HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG); CanGetNightTimeGS = (CanUse(RG_SUNS_SONG) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG)); CanBreakUpperBeehives = HookshotOrBoomerang || (ctx->GetTrickOption(RT_BOMBCHU_BEEHIVES) && HasBombchus); CanBreakLowerBeehives = CanBreakUpperBeehives || Bombs; - CanFish = ChildsWallet && (CanUse(RG_FISHING_POLE) || !ctx->GetOption(RSK_SHUFFLE_FISHING_POLE)); + CanFish = ChildsWallet && (HasItem(RG_FISHING_POLE) || !ctx->GetOption(RSK_SHUFFLE_FISHING_POLE)); CanGetChildFish = CanFish && (IsChild || (IsAdult && !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))); CanGetAdultFish = CanFish && IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT); @@ -365,8 +602,8 @@ namespace Rando { HasFireSourceWithTorch = HasFireSource || CanUse(RG_STICKS); //Gerudo Fortress - CanFinishGerudoFortress = (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL) && GerudoFortressKeys >= 4 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_GF_KITCHEN))) || - (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST) && GerudoFortressKeys >= 1 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) || + CanFinishGerudoFortress = (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL) && SmallKeys(RR_GERUDO_FORTRESS, 4) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_GF_KITCHEN))) || + (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST) && SmallKeys(RR_GERUDO_FORTRESS, 1) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) || (ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_NORMAL) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_FAST)); HasShield = CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD); //Mirror shield can't reflect attacks @@ -411,7 +648,7 @@ namespace Rando { } bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched) { - if (SkeletonKey) { + if (HasItem(RG_SKELETON_KEY)) { return true; } switch (dungeon) { @@ -420,55 +657,58 @@ namespace Rando { (GetDifficultyValueFromString(GlitchHover) >= static_cast(GlitchDifficulty::NOVICE) && GetDifficultyValueFromString(GlitchISG) >= static_cast(GlitchDifficulty::INTERMEDIATE)))) { return ForestTempleKeys >= requiredAmountGlitched; }*/ - return ForestTempleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_FOREST_TEMPLE) >= requiredAmountGlitchless; case RR_FIRE_TEMPLE: /*if (IsGlitched && (GetDifficultyValueFromString(GlitchLedgeClip) >= static_cast(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >= static_cast(GlitchDifficulty::INTERMEDIATE))) { return FireTempleKeys >= requiredAmountGlitched; }*/ - return FireTempleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_FIRE_TEMPLE) >= requiredAmountGlitchless; case RR_WATER_TEMPLE: /*if (IsGlitched && (false)) { return WaterTempleKeys >= requiredAmountGlitched; }*/ - return WaterTempleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_WATER_TEMPLE) >= requiredAmountGlitchless; case RR_SPIRIT_TEMPLE: /*if (IsGlitched && (false)) { return SpiritTempleKeys >= requiredAmountGlitched; }*/ - return SpiritTempleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_SPIRIT_TEMPLE) >= requiredAmountGlitchless; case RR_SHADOW_TEMPLE: /*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotClip) >= static_cast(GlitchDifficulty::NOVICE))) { return ShadowTempleKeys >= requiredAmountGlitched; }*/ - return ShadowTempleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_SHADOW_TEMPLE) >= requiredAmountGlitchless; case RR_BOTTOM_OF_THE_WELL: /*if (IsGlitched && (false)) { return BottomOfTheWellKeys >= requiredAmountGlitched; }*/ - return BottomOfTheWellKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_BOTTOM_OF_THE_WELL) >= requiredAmountGlitchless; case RR_GERUDO_TRAINING_GROUNDS: /*if (IsGlitched && (false)) { return GerudoTrainingGroundsKeys >= requiredAmountGlitched; }*/ - return GerudoTrainingGroundsKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_GERUDO_TRAINING_GROUND) >= requiredAmountGlitchless; case RR_GANONS_CASTLE: /*if (IsGlitched && (false)) { return GanonsCastleKeys >= requiredAmountGlitched; }*/ - return GanonsCastleKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_INSIDE_GANONS_CASTLE) >= requiredAmountGlitchless; case RR_MARKET_TREASURE_CHEST_GAME: /*if (IsGlitched && (false)) { return TreasureGameKeys >= requiredAmountGlitched; }*/ - return TreasureGameKeys >= requiredAmountGlitchless; + return ctx->GetSmallKeyCount(SCENE_TREASURE_BOX_SHOP) >= requiredAmountGlitchless; + + case RR_GERUDO_FORTRESS: + return ctx->GetSmallKeyCount(SCENE_THIEVES_HIDEOUT) >= requiredAmountGlitchless; default: return false; @@ -504,8 +744,21 @@ namespace Rando { return false; } + void Logic::SetContext(std::shared_ptr _ctx) { + ctx = _ctx; + } + + bool Logic::GetInLogic(LogicVal logicVal) { + return inLogic[logicVal]; + } + + void Logic::SetInLogic(LogicVal logicVal, bool value) { + inLogic[logicVal] = value; + } + void Logic::Reset() { - auto ctx = Rando::Context::GetInstance(); + ctx->NewSaveContext(); + memset(inLogic, false, sizeof(inLogic)); //Settings-dependent variables IsKeysanity = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || @@ -522,7 +775,6 @@ namespace Rando { Bombchus10 = false; Bombchus20 = false; MagicBean = false; - MagicBeanPack = false; RutosLetter = false; Boomerang = false; DinsFire = false; @@ -541,7 +793,7 @@ namespace Rando { GoronTunic = false; ZoraTunic = false; Epona = false; - BigPoe = false; + //BigPoe = false; GerudoToken = false; FireArrows = false; IceArrows = false; @@ -573,20 +825,6 @@ namespace Rando { EyedropsAccess = false; DisableTradeRevert = false; - //Songs - ZeldasLullaby = false; - SariasSong = false; - SunsSong = false; - SongOfStorms = false; - EponasSong = false; - SongOfTime = false; - MinuetOfForest = false; - BoleroOfFire = false; - SerenadeOfWater = false; - RequiemOfSpirit = false; - NocturneOfShadow = false; - PreludeOfLight = false; - //Stones and Meddallions ForestMedallion = false; FireMedallion = false; @@ -622,40 +860,41 @@ namespace Rando { GregInLacsLogic = false; //Ocarina C Buttons - OcarinaAButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; - OcarinaCLeftButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; - OcarinaCRightButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; - OcarinaCUpButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; - OcarinaCDownButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1; + bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true); + ctx->SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle); + ctx->SetRandoInf(RAND_INF_HAS_OCARINA_C_UP, !ocBtnShuffle); + ctx->SetRandoInf(RAND_INF_HAS_OCARINA_C_DOWN, !ocBtnShuffle); + ctx->SetRandoInf(RAND_INF_HAS_OCARINA_C_LEFT, !ocBtnShuffle); + ctx->SetRandoInf(RAND_INF_HAS_OCARINA_C_RIGHT, !ocBtnShuffle); //Progressive Items - ProgressiveStickBag = ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Is(true) ? 0 : 1; - ProgressiveNutBag = ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Is(true) ? 0 : 1; + ctx->SetUpgrade(UPG_STICKS, ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Is(true) ? 0 : 1); + ctx->SetUpgrade(UPG_NUTS, ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Is(true) ? 0 : 1); ProgressiveBulletBag = 0; ProgressiveBombBag = 0; ProgressiveMagic = 0; //If we're not shuffling swim, we start with it (scale 1) - ProgressiveScale = ctx->GetOption(RSK_SHUFFLE_SWIM).Is(true) ? 0 : 1; + ProgressiveScale = 0; + if (ctx->GetOption(RSK_SHUFFLE_SWIM).Is(false)) { + ProgressiveScale = 1; + ctx->SetRandoInf(RAND_INF_CAN_SWIM, true); + } ProgressiveHookshot = 0; ProgressiveBow = 0; //If we're not shuffling child's wallet, we start with it (wallet 1) - ProgressiveWallet = ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(true) ? 0 : 1; + ProgressiveWallet = 0; + if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) { + ProgressiveWallet = 1; + ctx->SetRandoInf(RAND_INF_HAS_WALLET, true); + } ProgressiveStrength = 0; ProgressiveOcarina = 0; ProgressiveGiantKnife = 0; - //Keys - ForestTempleKeys = 0; //If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla FiT - FireTempleKeys = IsKeysanity || ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsMQ() ? 0 : 1; - WaterTempleKeys = 0; - SpiritTempleKeys = 0; - ShadowTempleKeys = 0; - GanonsCastleKeys = 0; - GerudoFortressKeys = 0; - GerudoTrainingGroundsKeys = 0; - BottomOfTheWellKeys = 0; - TreasureGameKeys = 0; + if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { + ctx->SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1); + } //Boss Keys BossKeyForestTemple = 0; @@ -676,9 +915,6 @@ namespace Rando { //Triforce Pieces TriforcePieces = 0; - //Skeleton Key - SkeletonKey = false; - //Boss Souls CanSummonGohma = false; CanSummonKingDodongo = false; @@ -830,6 +1066,7 @@ namespace Rando { AtDay = false; AtNight = false; Age = ctx->GetSettings()->ResolvedStartingAge(); + ctx->GetSaveContext()->linkAge = !Age; //Events ShowedMidoSwordAndShield = false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 799b8402a..4c23dc321 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -40,7 +40,6 @@ class Logic { bool Bombchus10 = false; bool Bombchus20 = false; bool MagicBean = false; - bool MagicBeanPack = false; bool RutosLetter = false; bool Boomerang = false; bool DinsFire = false; @@ -59,7 +58,7 @@ class Logic { bool GoronTunic = false; bool ZoraTunic = false; bool Epona = false; - bool BigPoe = false; + //bool BigPoe = false; //unused bool GerudoToken = false; bool FireArrows = false; bool IceArrows = false; @@ -91,20 +90,6 @@ class Logic { bool EyedropsAccess = false; bool DisableTradeRevert = false; - // Songs - bool ZeldasLullaby = false; - bool SariasSong = false; - bool SunsSong = false; - bool SongOfStorms = false; - bool EponasSong = false; - bool SongOfTime = false; - bool MinuetOfForest = false; - bool BoleroOfFire = false; - bool SerenadeOfWater = false; - bool RequiemOfSpirit = false; - bool NocturneOfShadow = false; - bool PreludeOfLight = false; - // Stones and Meddallions bool ForestMedallion = false; bool FireMedallion = false; @@ -140,8 +125,6 @@ class Logic { bool GregInLacsLogic = false; // Progressive Items - uint8_t ProgressiveStickBag = 0; - uint8_t ProgressiveNutBag = 0; uint8_t ProgressiveBulletBag = 0; uint8_t ProgressiveBombBag = 0; uint8_t ProgressiveMagic = 0; @@ -171,9 +154,6 @@ class Logic { // Triforce Pieces uint8_t TriforcePieces = 0; - // Skeleton Key - bool SkeletonKey = false; - // Boss Keys bool BossKeyForestTemple = false; bool BossKeyFireTemple = false; @@ -422,6 +402,7 @@ class Logic { void UpdateHelpers(); bool CanUse(RandomizerGet itemName); bool HasProjectile(HasProjectileAge age); + bool HasItem(RandomizerGet itemName); bool HasBossSoul(RandomizerGet itemName); bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount); bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); @@ -430,11 +411,16 @@ class Logic { bool CanKillEnemy(std::string enemy); bool CanPassEnemy(std::string enemy); bool EventsUpdated(); + uint8_t BottleCount(); void Reset(); + void SetContext(std::shared_ptr _ctx); + bool GetInLogic(LogicVal logicVal); + void SetInLogic(LogicVal logicVal, bool remove); private: static bool IsMagicItem(RandomizerGet item); static bool IsMagicArrow(RandomizerGet item); - bool HasItem(RandomizerGet itemName); + std::shared_ptr ctx; + bool inLogic[LOGIC_MAX]; }; // class Logic } // namespace Rando \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 1b772367d..6162b3341 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -53,6 +53,156 @@ typedef enum { HINT_TYPE_MAX } HintType; +typedef enum { + LOGIC_NONE, + LOGIC_KOKIRI_SWORD, + LOGIC_MASTER_SWORD, + LOGIC_BIGGORON_SWORD, + LOGIC_DEKU_SHIELD, + LOGIC_HYLIAN_SHIELD, + LOGIC_MIRROR_SHIELD, + LOGIC_GORON_TUNIC, + LOGIC_ZORA_TUNIC, + LOGIC_IRON_BOOTS, + LOGIC_HOVER_BOOTS, + LOGIC_BOOMERANG, + LOGIC_LENS_OF_TRUTH, + LOGIC_HAMMER, + LOGIC_STONE_OF_AGONY, + LOGIC_DINS_FIRE, + LOGIC_FARORES_WIND, + LOGIC_NAYRUS_LOVE, + LOGIC_FIRE_ARROWS, + LOGIC_ICE_ARROWS, + LOGIC_LIGHT_ARROWS, + LOGIC_GERUDO_CARD, + LOGIC_MAGIC_BEAN, + LOGIC_MAGIC_BEANPACK, + LOGIC_DOUBLE_DEFENSE, + LOGIC_WEIRD_EGG, + LOGIC_ZELDAS_LETTER, + LOGIC_POCKET_EGG, + LOGIC_COJIRO, + LOGIC_ODD_MUSHROOM, + LOGIC_ODD_POULTICE, + LOGIC_POACHERS_SAW, + LOGIC_BROKEN_SWORD, + LOGIC_PRESCRIPTION, + LOGIC_EYEBALL_FROG, + LOGIC_EYEDROPS, + LOGIC_CLAIM_CHECK, + LOGIC_GOLD_SKULLTULA_TOKENS, + LOGIC_PROGRESSIVE_HOOKSHOT, + LOGIC_PROGRESSIVE_STRENGTH, + LOGIC_PROGRESSIVE_BOMB_BAG, + LOGIC_PROGRESSIVE_BOW, + LOGIC_PROGRESSIVE_BULLET_BAG, + LOGIC_PROGRESSIVE_STICK_BAG, + LOGIC_PROGRESSIVE_NUT_BAG, + LOGIC_PROGRESSIVE_WALLET, + LOGIC_PROGRESSIVE_SCALE, + LOGIC_BOMBCHUS, + LOGIC_PROGRESSIVE_MAGIC, + LOGIC_PROGRESSIVE_OCARINA, + LOGIC_PROGRESSIVE_GIANT_KNIFE, + LOGIC_BOTTLES, + LOGIC_RUTOS_LETTER, + LOGIC_BOTTLE_WITH_BIG_POE, + LOGIC_ZELDAS_LULLABY, + LOGIC_EPONAS_SONG, + LOGIC_SARIAS_SONG, + LOGIC_SUNS_SONG, + LOGIC_SONG_OF_TIME, + LOGIC_SONG_OF_STORMS, + LOGIC_MINUET_OF_FOREST, + LOGIC_BOLERO_OF_FIRE, + LOGIC_SERENADE_OF_WATER, + LOGIC_NOCTURNE_OF_SHADOW, + LOGIC_REQUIEM_OF_SPIRIT, + LOGIC_PRELUDE_OF_LIGHT, + LOGIC_MAP_DEKU_TREE, + LOGIC_MAP_DODONGOS_CAVERN, + LOGIC_MAP_JABU_JABUS_BELLY, + LOGIC_MAP_FOREST_TEMPLE, + LOGIC_MAP_FIRE_TEMPLE, + LOGIC_MAP_WATER_TEMPLE, + LOGIC_MAP_SPIRIT_TEMPLE, + LOGIC_MAP_SHADOW_TEMPLE, + LOGIC_MAP_BOTTOM_OF_THE_WELL, + LOGIC_MAP_ICE_CAVERN, + LOGIC_COMPASS_DEKU_TREE, + LOGIC_COMPASS_DODONGOS_CAVERN, + LOGIC_COMPASS_JABU_JABUS_BELLY, + LOGIC_COMPASS_FOREST_TEMPLE, + LOGIC_COMPASS_FIRE_TEMPLE, + LOGIC_COMPASS_WATER_TEMPLE, + LOGIC_COMPASS_SPIRIT_TEMPLE, + LOGIC_COMPASS_SHADOW_TEMPLE, + LOGIC_COMPASS_BOTTOM_OF_THE_WELL, + LOGIC_COMPASS_ICE_CAVERN, + LOGIC_BOSS_KEY_FOREST_TEMPLE, + LOGIC_BOSS_KEY_FIRE_TEMPLE, + LOGIC_BOSS_KEY_WATER_TEMPLE, + LOGIC_BOSS_KEY_SPIRIT_TEMPLE, + LOGIC_BOSS_KEY_SHADOW_TEMPLE, + LOGIC_BOSS_KEY_GANONS_CASTLE, + LOGIC_FOREST_TEMPLE_KEYS, + LOGIC_FIRE_TEMPLE_KEYS, + LOGIC_WATER_TEMPLE_KEYS, + LOGIC_SPIRIT_TEMPLE_KEYS, + LOGIC_SHADOW_TEMPLE_KEYS, + LOGIC_BOTTOM_OF_THE_WELL_KEYS, + LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, + LOGIC_GERUDO_FORTRESS_KEYS, + LOGIC_GANONS_CASTLE_KEYS, + LOGIC_TREASURE_GAME_KEYS, + LOGIC_SKELETON_KEY, + LOGIC_KOKIRI_EMERALD, + LOGIC_GORON_RUBY, + LOGIC_ZORA_SAPPHIRE, + LOGIC_FOREST_MEDALLION, + LOGIC_FIRE_MEDALLION, + LOGIC_WATER_MEDALLION, + LOGIC_SPIRIT_MEDALLION, + LOGIC_SHADOW_MEDALLION, + LOGIC_LIGHT_MEDALLION, + LOGIC_GREG, + LOGIC_PIECE_OF_HEART, + LOGIC_HEART_CONTAINER, + LOGIC_BOMBCHUS_5, + LOGIC_BOMBCHUS_10, + LOGIC_BOMBCHUS_20, + LOGIC_BOMBCHU_DROP, + LOGIC_NUTS, + LOGIC_BUY_ARROW, + LOGIC_BUY_BOMB, + LOGIC_STICKS, + LOGIC_FISH_ACCESS, + LOGIC_BUY_MAGIC_POTION, + LOGIC_BUY_BOMBCHUS, + LOGIC_BUY_SEED, + LOGIC_BLUE_FIRE_ACCESS, + LOGIC_BUGS_ACCESS, + LOGIC_FAIRY_ACCESS, + LOGIC_CAN_SUMMON_GOHMA, + LOGIC_CAN_SUMMON_KINGDODONGO, + LOGIC_CAN_SUMMON_BARINADE, + LOGIC_CAN_SUMMON_PHANTOMGANON, + LOGIC_CAN_SUMMON_VOLVAGIA, + LOGIC_CAN_SUMMON_MORPHA, + LOGIC_CAN_SUMMON_BONGOBONGO, + LOGIC_CAN_SUMMON_TWINROVA, + LOGIC_CAN_SUMMON_GANON, + LOGIC_FISHING_POLE, + LOGIC_OCARINA_A_BUTTON, + LOGIC_OCARINA_C_UP_BUTTON, + LOGIC_OCARINA_C_DOWN_BUTTON, + LOGIC_OCARINA_C_LEFT_BUTTON, + LOGIC_OCARINA_C_RIGHT_BUTTON, + LOGIC_TRIFORCE_PIECES, + LOGIC_MAX +} LogicVal; + typedef enum { RA_NONE, RA_LINKS_POCKET, @@ -2024,6 +2174,7 @@ typedef enum { // Logic Only RG_DISTANT_SCARECROW, RG_STICKS, + RG_NUTS, RG_MAX } RandomizerGet; diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8d3e96239..20aab3032 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -295,6 +295,17 @@ typedef enum { RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS, RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN, + + RAND_INF_ZELDAS_LETTER, + RAND_INF_WEIRD_EGG, + RAND_INF_CHILD_TRADES_MASK_KEATON, + RAND_INF_CHILD_TRADES_MASK_SKULL, + RAND_INF_CHILD_TRADES_MASK_SPOOKY, + RAND_INF_CHILD_TRADES_MASK_BUNNY, + RAND_INF_CHILD_TRADES_MASK_GORON, + RAND_INF_CHILD_TRADES_MASK_ZORA, + RAND_INF_CHILD_TRADES_MASK_GERUDO, + RAND_INF_CHILD_TRADES_MASK_TRUTH, // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 4415cd7dd..00cd3115e 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -2843,8 +2843,9 @@ extern "C" void Save_SaveGlobal(void) { extern "C" void Save_LoadFile(void) { if (gSaveContext.questId == QUEST_RANDOMIZER) { // Reset rando context for rando saves. - OTRGlobals::Instance->gRandoContext.reset(); + OTRGlobals::Instance->gRandoContext.reset(); OTRGlobals::Instance->gRandoContext = Rando::Context::CreateInstance(); + OTRGlobals::Instance->gRandoContext->SetSaveContext(&gSaveContext); OTRGlobals::Instance->gRandoContext->AddExcludedOptions(); OTRGlobals::Instance->gRandoContext->GetSettings()->CreateOptions(); } From 5e6cd710314b04f749fd86d0e9e80662726e9d46 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:54:33 +0200 Subject: [PATCH 290/300] Update item_list.cpp (#4272) --- soh/soh/Enhancements/randomizer/item_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 6e4524939..526c7b3ae 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -293,8 +293,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_NUT_UPGRADE_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_MAGIC_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); From 03e32587927119efb0c2148f06c6f923b5be4993 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 2 Aug 2024 08:54:25 -0700 Subject: [PATCH 291/300] It's not master sword. (#4273) --- soh/soh/Enhancements/randomizer/logic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 3814e12c5..a4bc5a08c 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -461,7 +461,7 @@ namespace Rando { LightArrows = CanUse(RG_LIGHT_ARROWS); KokiriSword = CanUse(RG_KOKIRI_SWORD); MasterSword = CanUse(RG_MASTER_SWORD); - BiggoronSword = CanUse(RG_MASTER_SWORD); + BiggoronSword = CanUse(RG_BIGGORON_SWORD); NumBottles = ((NoBottles) ? 0 : BottleCount()); HasBottle = NumBottles >= 1; Slingshot = CanUse(RG_FAIRY_SLINGSHOT) && (BuySeed || AmmoCanDrop); From c6b05b2087adcb90e60c0c57747d9ee85947b27a Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 4 Aug 2024 15:32:11 -0700 Subject: [PATCH 292/300] Change `RSK_SHUFFLE` instance in mixed pool code to `RSK_MIX`. (#4276) --- soh/soh/Enhancements/randomizer/entrance.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 2f4b43d26..b75ab3d48 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -1392,16 +1392,16 @@ int EntranceShuffler::ShuffleAllEntrances() { poolsToMix.insert(EntranceType::BossReverse); } } - if (ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { + if (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES)) { poolsToMix.insert(EntranceType::Overworld); } - if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES)) { + if (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES)) { poolsToMix.insert(EntranceType::Interior); if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { poolsToMix.insert(EntranceType::InteriorReverse); } } - if (ctx->GetOption(RSK_SHUFFLE_GROTTO_ENTRANCES)) { + if (ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES)) { poolsToMix.insert(EntranceType::GrottoGrave); if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { poolsToMix.insert(EntranceType::GrottoGraveReverse); From 483dbea33068f11a0f02afb84ee46b2d66fbfcd9 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 4 Aug 2024 17:05:29 -0700 Subject: [PATCH 293/300] Fix RSK for mixing boss entrances. (#4277) --- soh/soh/Enhancements/randomizer/entrance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index b75ab3d48..16fbdfd3b 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -1386,7 +1386,7 @@ int EntranceShuffler::ShuffleAllEntrances() { poolsToMix.insert(EntranceType::DungeonReverse); } } - if (ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES)) { + if (ctx->GetOption(RSK_MIX_BOSS_ENTRANCES)) { poolsToMix.insert(EntranceType::Boss); if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { poolsToMix.insert(EntranceType::BossReverse); From f11f97e84e508dfca79c1232ee39e746cb0afb1c Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 5 Aug 2024 15:20:40 -0400 Subject: [PATCH 294/300] Custom Skeleton Fixes for various bosses and enemies (#3436) * Skeleton Fixes for various bosses and enemies * cleanup * revert breakpart changes --------- Co-authored-by: Adam Bird --- soh/include/functions.h | 2 ++ soh/include/z64.h | 2 ++ soh/src/code/z_skelanime.c | 20 +++++++++++ .../actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 17 +++++++-- .../actors/ovl_Boss_Goma/z_boss_goma.c | 36 ++++++++++++++++--- .../actors/ovl_Door_Warp1/z_door_warp1.c | 4 +-- .../overlays/actors/ovl_En_Bili/z_en_bili.c | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 4 +-- soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c | 4 +-- .../overlays/actors/ovl_En_Eiyer/z_en_eiyer.c | 4 +-- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 2 +- .../actors/ovl_En_Firefly/z_en_firefly.c | 7 ++-- .../actors/ovl_En_Partner/z_en_partner.c | 2 +- .../actors/ovl_En_Po_Desert/z_en_po_desert.c | 2 +- .../actors/ovl_En_Po_Field/z_en_po_field.c | 5 ++- .../ovl_En_Po_Sisters/z_en_po_sisters.c | 8 ++--- soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c | 4 +-- .../overlays/actors/ovl_En_Vali/z_en_vali.c | 2 +- .../actors/ovl_En_Weiyer/z_en_weiyer.c | 6 ++-- soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c | 4 +-- 20 files changed, 100 insertions(+), 37 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 3a1aa8ae2..553630672 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1259,6 +1259,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListIndex); void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg); +Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, + PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx); void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable, OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg); void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount, diff --git a/soh/include/z64.h b/soh/include/z64.h index f790dddc7..be0bceed2 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1405,6 +1405,8 @@ typedef struct PlayState { /* 0x1242B */ u8 unk_1242B; /* 0x1242C */ SceneTableEntry* loadedScene; /* 0x12430 */ char unk_12430[0xE8]; + // SOH [Custom Models] MTX tracker for flex based skeletons + Mtx** flexLimbOverrideMTX; } PlayState; // size = 0x12518 typedef struct { diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 2123c2d3b..ae59e187b 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -148,6 +148,8 @@ void SkelAnime_DrawFlexLimbLod(PlayState* play, s32 limbIndex, void** skeleton, newDList = limbDList = limb->dLists[lod]; + play->flexLimbOverrideMTX = mtx; + if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { @@ -220,6 +222,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, newDList = limbDList = rootLimb->dLists[lod]; + play->flexLimbOverrideMTX = &mtx; + if ((overrideLimbDraw == 0) || !overrideLimbDraw(play, 1, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { @@ -306,6 +310,20 @@ void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLi } } +Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, + PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx) +{ + if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_NORMAL) { + return SkelAnime_Draw(play, skelAnime->skeleton, skelAnime->jointTable, overrideLimbDraw, postLimbDraw, arg, gfx); + } else if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + FlexSkeletonHeader* flexHeader = (FlexSkeletonHeader*)skelAnime->skeletonHeader; + return SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, flexHeader->dListCount, + overrideLimbDraw, postLimbDraw, arg, gfx); + } + + return gfx; +} + /** * Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer */ @@ -383,6 +401,8 @@ void SkelAnime_DrawFlexLimbOpa(PlayState* play, s32 limbIndex, void** skeleton, newDList = limbDList = limb->dList; + play->flexLimbOverrideMTX = limbMatricies; + if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 1f2791540..3a8a8215f 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -1288,6 +1288,10 @@ block_1: if (*dList != NULL) { OPEN_DISPS(play->state.gfxCtx); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + mtxScaleZ = 1.0f; mtxScaleY = 1.0f; @@ -1308,11 +1312,20 @@ block_1: Matrix_RotateX(-(this->unk_25C[limbIndex] * 0.115f), MTXMODE_APPLY); } - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } + CLOSE_DISPS(play->state.gfxCtx); } { s32 pad; } // Required to match diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 6de72fd2d..f6e2b3f31 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -2015,12 +2015,26 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f Matrix_TranslateRotateZYX(pos, rot); if (*dList != NULL) { + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + Matrix_Push(); Matrix_Scale(this->eyeIrisScaleX, this->eyeIrisScaleY, 1.0f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } } doNotDrawLimb = true; @@ -2034,14 +2048,28 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f Matrix_TranslateRotateZYX(pos, rot); if (*dList != NULL) { + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + Matrix_Push(); Matrix_Scale(this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } } doNotDrawLimb = true; diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 5940f8c03..08b9a0749 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -1055,7 +1055,7 @@ void DoorWarp1_DrawBlueCrystal(DoorWarp1* this, PlayState* play) { gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (u8)this->crystalAlpha); gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (u8)this->crystalAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); @@ -1079,7 +1079,7 @@ void DoorWarp1_DrawPurpleCrystal(DoorWarp1* this, PlayState* play) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->crystalAlpha); gDPSetEnvColor(POLY_XLU_DISP++, 150, 0, 100, (u8)this->crystalAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c b/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c index 74f89cbe3..a50dabe01 100644 --- a/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c +++ b/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c @@ -768,7 +768,7 @@ void EnBili_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_XLU_DISP++, 0x09, D_809C1700); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBili_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 4f1ef7362..359c983e9 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -947,7 +947,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_EmptyDList(play->state.gfxCtx)); Gfx_SetupDL_25Opa(play->state.gfxCtx); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL, EnBox_PostLimbDraw, this, POLY_OPA_DISP); } else if (this->alpha != 0) { gDPPipeSync(POLY_XLU_DISP++); @@ -958,7 +958,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) { } else { gSPSegment(POLY_XLU_DISP++, 0x08, func_809CA4A0(play->state.gfxCtx)); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL, EnBox_PostLimbDraw, this, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c index a57594a0f..e64abd8df 100644 --- a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c +++ b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c @@ -856,7 +856,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gDPSetEnvColor(POLY_OPA_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a); gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBw_OverrideLimbDraw, NULL, this, POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); @@ -864,7 +864,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) { gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 0, 0, 0, this->color1.a); gDPSetEnvColor(POLY_XLU_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a); gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBw_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c b/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c index 049570716..7340d9cf5 100644 --- a/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c +++ b/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c @@ -708,14 +708,14 @@ void EnEiyer_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, EnEiyer_OverrideLimbDraw, NULL, this, POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, EnEiyer_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 2191daeab..ec288eed3 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1540,7 +1540,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) { gSPEndDisplayList(dListHead++); gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b, (u8)(envAlpha * alphaScale)); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnElf_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index bf7b79b7f..f0fcf03a1 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -837,8 +837,9 @@ void EnFirefly_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); } - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, + &this->actor, POLY_OPA_DISP); + CLOSE_DISPS(play->state.gfxCtx); } @@ -854,7 +855,7 @@ void EnFirefly_DrawInvisible(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 255); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index 8780ab10c..7f7b92c55 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -858,7 +858,7 @@ void EnPartner_Draw(Actor* thisx, PlayState* play) { gSPEndDisplayList(dListHead++); gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b, (u8)(envAlpha * alphaScale)); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPartner_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c b/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c index 55155226b..2c00b284b 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c +++ b/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c @@ -267,7 +267,7 @@ void EnPoDesert_Draw(Actor* thisx, PlayState* play) { } else { gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280 + 2); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoDesert_OverrideLimbDraw, EnPoDesert_PostLimbDraw, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c index c11feb327..eba331a08 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c +++ b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c @@ -944,15 +944,14 @@ void EnPoField_Draw(Actor* thisx, PlayState* play) { this->lightColor.a)); gSPSegment(POLY_OPA_DISP++, 0x0C, D_80116280 + 2); POLY_OPA_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_OPA_DISP); } else { gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_EnvColor(play->state.gfxCtx, this->lightColor.r, this->lightColor.g, this->lightColor.b, this->lightColor.a)); gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280); - POLY_XLU_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_XLU_DISP); } gDPPipeSync(POLY_OPA_DISP++); diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index ea324c5a5..8bd5c2112 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -1373,14 +1373,12 @@ void EnPoSisters_Draw(Actor* thisx, PlayState* play) { if (this->unk_22E.a == 255 || this->unk_22E.a == 0) { gDPSetEnvColor(POLY_OPA_DISP++, this->unk_22E.r, this->unk_22E.g, this->unk_22E.b, this->unk_22E.a); gSPSegment(POLY_OPA_DISP++, 0x09, D_80116280 + 2); - POLY_OPA_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoSisters_OverrideLimbDraw, + EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->unk_22E.a); gSPSegment(POLY_XLU_DISP++, 0x09, D_80116280); - POLY_XLU_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_XLU_DISP); } if (!(this->unk_199 & 0x80)) { diff --git a/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c b/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c index 809150fe6..2c7e90416 100644 --- a/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c +++ b/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c @@ -1085,12 +1085,12 @@ void EnPoh_DrawRegular(Actor* thisx, PlayState* play) { if (this->lightColor.a == 255 || this->lightColor.a == 0) { gDPSetEnvColor(POLY_OPA_DISP++, this->lightColor.r, this->lightColor.g, this->lightColor.b, this->lightColor.a); gSPSegment(POLY_OPA_DISP++, 0x08, D_80116280 + 2); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_OPA_DISP); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->lightColor.a); gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_XLU_DISP); } gDPPipeSync(POLY_OPA_DISP++); diff --git a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c index d7a838d8a..c1c4394ce 100644 --- a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c +++ b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c @@ -814,7 +814,7 @@ void EnVali_Draw(Actor* thisx, PlayState* play) { EnVali_DrawBody(this, play); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnVali_OverrideLimbDraw, EnVali_PostLimbDraw, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c b/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c index 4a267b001..e3f19a3ed 100644 --- a/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c +++ b/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c @@ -640,13 +640,13 @@ void EnWeiyer_Draw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnWeiyer_OverrideLimbDraw, NULL, &this->actor, + POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c index 9aa8204dd..dca0af405 100644 --- a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c +++ b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c @@ -2252,7 +2252,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_OPA_DISP++, 0x09, &D_80116280[2]); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_OPA_DISP); if (this->iceTimer != 0) { @@ -2271,7 +2271,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) { gDPPipeSync(POLY_XLU_DISP++); gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_XLU_DISP++, 0x09, &D_80116280[0]); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_XLU_DISP); } CLOSE_DISPS(play->state.gfxCtx); From 3971e3696ea022be0eb50c4f0a19f3c5a4806fe6 Mon Sep 17 00:00:00 2001 From: Spodi Date: Tue, 6 Aug 2024 01:31:20 +0200 Subject: [PATCH 295/300] Use manifest for windows DPI awareness (#3270) (#4256) * Use manifest for windows DPI awareness (#3270) * Update libultraship * Update libultraship --- libultraship | 2 +- soh/SHIPOFHARKINIAN.manifest | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libultraship b/libultraship index 275c741d5..1ca7d0fa7 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 275c741d5dd48d78b6a746c0709c75d095e48eeb +Subproject commit 1ca7d0fa78013e49450a4a9881236a19a6600d64 diff --git a/soh/SHIPOFHARKINIAN.manifest b/soh/SHIPOFHARKINIAN.manifest index 80d9f6036..6f47a937f 100644 --- a/soh/SHIPOFHARKINIAN.manifest +++ b/soh/SHIPOFHARKINIAN.manifest @@ -28,4 +28,10 @@ + + + true/pm + permonitorv2,permonitor + + From 91d1e5970d787eab37884ce578b73f45992ef5de Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 10 Aug 2024 17:07:03 -0400 Subject: [PATCH 296/300] Fix an issue with a stray Rando::Context shared_ptr hanging around. (#4259) * Fix an issue with a stray Rando::Context shared_ptr hanging around. * Fixes accidental leftover from when I found this bug on another branch * Properly reset randoContext on every save load, not just after save creation --- soh/soh/Enhancements/randomizer/3drando/location_access.cpp | 4 ++-- soh/soh/Enhancements/randomizer/3drando/location_access.hpp | 2 +- soh/soh/Enhancements/randomizer/entrance.cpp | 5 +++++ soh/soh/Enhancements/randomizer/entrance.h | 1 + soh/soh/SaveManager.cpp | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index b181a3cdb..a64ef5f55 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -240,12 +240,12 @@ bool HasAccessTo(const RandomizerRegion area) { return areaTable[area].HasAccess(); } -std::shared_ptr randoCtx; +Rando::Context* randoCtx; std::shared_ptr logic; void AreaTable_Init() { using namespace Rando; - randoCtx = Context::GetInstance(); + randoCtx = Context::GetInstance().get(); logic = randoCtx->GetLogic(); grottoEvents = { EventAccess(&logic->GossipStoneFairy, { [] { return logic->GossipStoneFairy || logic->CanSummonGossipFairy; } }), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 1492e82ec..286551cab 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -12,7 +12,7 @@ typedef bool (*ConditionFn)(); // I hate this but every alternative I can think of right now is worse -extern std::shared_ptr randoCtx; +extern Rando::Context* randoCtx; extern std::shared_ptr logic; class EventAccess { diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 16fbdfd3b..39eab1398 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -235,6 +235,11 @@ Entrance* Entrance::AssumeReachable() { return assumed; } +EntranceShuffler::EntranceShuffler() { + playthroughEntrances = {}; + entranceOverrides = {}; +} + bool EntranceShuffler::HasNoRandomEntrances() { return mNoRandomEntrances; } diff --git a/soh/soh/Enhancements/randomizer/entrance.h b/soh/soh/Enhancements/randomizer/entrance.h index e17687842..08861ff0d 100644 --- a/soh/soh/Enhancements/randomizer/entrance.h +++ b/soh/soh/Enhancements/randomizer/entrance.h @@ -115,6 +115,7 @@ using EntrancePools = std::map>; class EntranceShuffler { public: + EntranceShuffler(); std::array entranceOverrides; std::vector> playthroughEntrances; bool HasNoRandomEntrances(); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 00cd3115e..448a8d2e0 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -2841,7 +2841,7 @@ extern "C" void Save_SaveGlobal(void) { } extern "C" void Save_LoadFile(void) { - if (gSaveContext.questId == QUEST_RANDOMIZER) { + if (SaveManager::Instance->fileMetaInfo[gSaveContext.fileNum].randoSave) { // Reset rando context for rando saves. OTRGlobals::Instance->gRandoContext.reset(); OTRGlobals::Instance->gRandoContext = Rando::Context::CreateInstance(); From f4d951aab8966add4e19a4151b41ff53d746d9f6 Mon Sep 17 00:00:00 2001 From: Extloga <141232749+Extloga@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:08:42 +0200 Subject: [PATCH 297/300] Additions and fixes for the German translation in several files (#4195) * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in hint_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in z_message_OTR.cpp * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in randomizer.cpp * Additions for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Additions for the German translation in hint_list_item.cpp * Additions for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Additions for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in z_message_OTR.cpp * Fixes for the German translation in z_message_OTR.cpp * Additions for the German translation in item_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in hint_list.cpp * Fixes for the German translation in hint_list.cpp * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in hint_list_item.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in item_list.cpp * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in randomizer.cpp * Fixes for the German translation in randomizer.cpp --- .../randomizer/3drando/hint_list.cpp | 363 ++-- .../3drando/hint_list/hint_list_item.cpp | 1596 ++++++++--------- soh/soh/Enhancements/randomizer/item_list.cpp | 508 +++--- .../Enhancements/randomizer/randomizer.cpp | 115 +- soh/soh/z_message_OTR.cpp | 8 +- 5 files changed, 1300 insertions(+), 1290 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index ca60835e6..3a35118d2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -949,122 +949,126 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_LINKS_POCKET] = HintText(CustomMessage("Link's Pocket", - /*german*/ "", + /*german*/ "Links Taschen", /*french*/ "les Poches de @")); // /*spanish*/el bolsillo de @ hintTextTable[RHT_KOKIRI_FOREST] = HintText(CustomMessage("Kokiri Forest", - /*german*/ "", + /*german*/ "Kokiri-Wald", /*french*/ "la Forêt Kokiri")); // /*spanish*/el Bosque Kokiri hintTextTable[RHT_THE_LOST_WOODS] = HintText(CustomMessage("the Lost Woods", - /*german*/ "", + /*german*/ "Verlorene Wälder", /*french*/ "les Bois Perdus")); // /*spanish*/el Bosque Perdido + hintTextTable[RHT_SACRED_FOREST_MEADOW] = HintText(CustomMessage("Sacred Forest Meadow", - /*german*/ "", + /*german*/ "Heilige Lichtung", /*french*/ "le Bosquet Sacré")); // /*spanish*/la pradera sagrada del bosque hintTextTable[RHT_HYRULE_FIELD] = HintText(CustomMessage("Hyrule Field", - /*german*/ "", + /*german*/ "Hylianische Steppe", /*french*/ "la Plaine d'Hyrule")); // /*spanish*/la Llanura de Hyrule hintTextTable[RHT_LAKE_HYLIA] = HintText(CustomMessage("Lake Hylia", - /*german*/ "", + /*german*/ "Hylia-See", /*french*/ "le Lac Hylia")); // /*spanish*/el Lago Hylia hintTextTable[RHT_GERUDO_VALLEY] = HintText(CustomMessage("Gerudo Valley", - /*german*/ "", + /*german*/ "Gerudotal", /*french*/ "la Vallée Gerudo")); // /*spanish*/el Valle Gerudo hintTextTable[RHT_GERUDO_FORTRESS] = HintText(CustomMessage("Gerudo's Fortress", - /*german*/ "", + /*german*/ "Gerudo-Festung", /*french*/ "le Repaire des Voleurs")); // /*spanish*/la Fortaleza Gerudo hintTextTable[RHT_HAUNTED_WASTELAND] = HintText(CustomMessage("Haunted Wasteland", - /*german*/ "", + /*german*/ "Gespensterwüste", /*french*/ "le Désert Hanté")); // /*spanish*/el desierto encantado hintTextTable[RHT_DESERT_COLOSSUS] = HintText(CustomMessage("Desert Colossus", - /*german*/ "", + /*german*/ "Wüstenkoloß", /*french*/ "le Colosse du Désert")); // /*spanish*/el Coloso del Desierto hintTextTable[RHT_THE_MARKET] = HintText(CustomMessage("the Market", - /*german*/ "", + /*german*/ "Markt", /*french*/ "la Place du Marché")); // /*spanish*/la plaza del mercado hintTextTable[RHT_TEMPLE_OF_TIME] = HintText(CustomMessage("Temple of Time", - /*german*/ "", + /*german*/ "Zitadelle der Zeit", /*french*/ "le Temple du Temps")); // /*spanish*/el Templo del Tiempo + hintTextTable[RHT_CASTLE_GROUNDS] = HintText(CustomMessage("the Castle Grounds", - /*german*/ "", + /*german*/ "Anlage von Schloß Hyrule", /*french*/ "le Château d'Hyrule")); // /*spanish*/ + hintTextTable[RHT_HYRULE_CASTLE] = HintText(CustomMessage("Hyrule Castle", - /*german*/ "", + /*german*/ "Schloß Hyrule", /*french*/ "le Château d'Hyrule")); // /*spanish*/el Castillo de Hyrule hintTextTable[RHT_OUTSIDE_GANONS_CASTLE] = HintText(CustomMessage("outside Ganon's Castle", - /*german*/ "", + /*german*/ "außerhalb von Ganons Schloß", /*french*/ "les alentours du Château de Ganon")); // /*spanish*/el exterior del Castillo de Ganon hintTextTable[RHT_CASTLE_GROUNDS] = HintText(CustomMessage("the Castle Grounds", - /*german*/ "", + /*german*/ "Anlage von Schloß Hyrule", /*french*/ "le Château d'Hyrule")); // /*spanish*/ + hintTextTable[RHT_KAKARIKO_VILLAGE] = HintText(CustomMessage("Kakariko Village", - /*german*/ "", + /*german*/ "Kakariko", /*french*/ "le Village Cocorico")); // /*spanish*/Kakariko hintTextTable[RHT_THE_GRAVEYARD] = HintText(CustomMessage("the Graveyard", - /*german*/ "", + /*german*/ "Friedhof", /*french*/ "le Cimetière")); // /*spanish*/el cementerio hintTextTable[RHT_DEATH_MOUNTAIN_TRAIL] = HintText(CustomMessage("Death Mountain Trail", - /*german*/ "", + /*german*/ "Gebirgspfad", /*french*/ "le Chemin du Péril")); // /*spanish*/el sendero de la Montaña de la Muerte hintTextTable[RHT_GORON_CITY] = HintText(CustomMessage("Goron City", - /*german*/ "", + /*german*/ "Goronia", /*french*/ "le Village Goron")); // /*spanish*/la Ciudad Goron hintTextTable[RHT_DEATH_MOUNTAIN_CRATER] = HintText(CustomMessage("Death Mountain Crater", - /*german*/ "", + /*german*/ "Todeskrater", /*french*/ "le Cratère du Péril")); // /*spanish*/el cráter de la Montaña de la Muerte hintTextTable[RHT_ZORAS_RIVER] = HintText(CustomMessage("Zora's River", - /*german*/ "", + /*german*/ "Zoras Fluß", /*french*/ "la Rivière Zora")); // /*spanish*/el Río Zora hintTextTable[RHT_ZORAS_DOMAIN] = HintText(CustomMessage("Zora's Domain", - /*german*/ "", + /*german*/ "Zoras Reich", /*french*/ "le Domaine Zora")); // /*spanish*/la Región de los Zora hintTextTable[RHT_ZORAS_FOUNTAIN] = HintText(CustomMessage("Zora's Fountain", - /*german*/ "", + /*german*/ "Zoras Quelle", /*french*/ "la Fontaine Zora")); // /*spanish*/la Fuente Zora hintTextTable[RHT_LON_LON_RANCH] = HintText(CustomMessage("Lon Lon Ranch", - /*german*/ "", + /*german*/ "Lon Lon-Farm", /*french*/ "le Ranch Lon Lon")); // /*spanish*/el Rancho Lon Lon @@ -1073,382 +1077,387 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_KF_LINKS_HOUSE] = HintText(CustomMessage("Link's House", - /*german*/ "", + /*german*/ "Links Haus", /*french*/ "la #maison de @#")); // /*spanish*/la casa de @ hintTextTable[RHT_KF_MIDOS_HOUSE] = HintText(CustomMessage("Mido's house", - /*german*/ "", + /*german*/ "Midos Haus", /*french*/ "la Cabane du Grand Mido")); // /*spanish*/la casa de Mido + hintTextTable[RHT_KF_SARIAS_HOUSE] = HintText(CustomMessage("Saria's House", - /*german*/ "", + /*german*/ "Salias Haus", /*french*/ "la Cabane de Saria")); // /*spanish*/la casa de Saria hintTextTable[RHT_KF_HOUSE_OF_TWINS] = HintText(CustomMessage("the #House of Twins#", - /*german*/ "", + /*german*/ "das #Haus der Zwillinge#", /*french*/ "la Cabane des Jumelles")); // /*spanish*/la casa de las gemelas hintTextTable[RHT_KF_KNOW_IT_ALL_HOUSE] = HintText(CustomMessage("Know-It-All Brothers' House", - /*german*/ "", + /*german*/ "das #Haus der allwissenden Brüder#", /*french*/ "la Cabane des frères Je-Sais-Tout")); // /*spanish*/la casa de los hermanos Sabelotodo hintTextTable[RHT_KF_KOKIRI_SHOP] = HintText(CustomMessage("the #Kokiri Shop#", - /*german*/ "", + /*german*/ "der #Kokiri-Laden#", /*french*/ "le #Magasin Kokiri#")); // /*spanish*/la tienda kokiri + hintTextTable[RHT_LH_LAB] = HintText(CustomMessage("the #Lakeside Laboratory#", - /*german*/ "", + /*german*/ "das #Laboratorium des Sees#", /*french*/ "le #Laboratoire du Lac#")); // /*spanish*/el laboratorio del lago hintTextTable[RHT_LH_FISHING_HOLE] = HintText(CustomMessage("the #Fishing Pond#", - /*german*/ "", + /*german*/ "der #Angelteich#", /*french*/ "l'#Étang#")); // /*spanish*/el estanque hintTextTable[RHT_GV_CARPENTER_TENT] = HintText(CustomMessage("the #Carpenters' tent#", - /*german*/ "", + /*german*/ "das #Zelt der Zimmerleute#", /*french*/ "la #Tente des charpentiers#")); // /*spanish*/la #tienda de campaña de los carpinteros# hintTextTable[RHT_MARKET_GUARD_HOUSE] = HintText(CustomMessage("the #Guard House#", - /*german*/ "", + /*german*/ "das #Haus der Wachen#", /*french*/ "le #poste de garde#")); // /*spanish*/la caseta de guardia hintTextTable[RHT_MARKET_MASK_SHOP] = HintText(CustomMessage("the #Happy Mask Shop#", - /*german*/ "", + /*german*/ "der #Fröhliche Maskenladen#", /*french*/ "la #Foire Aux Masques#")); // /*spanish*/la tienda de La Máscara Feliz hintTextTable[RHT_MARKET_BOMBCHU_BOWLING] = HintText(CustomMessage("the #Bombchu Bowling Alley#", - /*german*/ "", + /*german*/ "die #Krabbelminenbowlingbahn", /*french*/ "le #Bowling Teigneux#")); // /*spanish*/la Bolera Bombchu hintTextTable[RHT_MARKET_POTION_SHOP] = HintText(CustomMessage("the #Market Potion Shop#", - /*german*/ "", + /*german*/ "der #Magie-Laden des Marktes#", /*french*/ "l'#apothicaire de la Place du Marché#")); // /*spanish*/la tienda de pociones de la plaza del mercado hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME] = HintText(CustomMessage("the #Treasure Chest Shop#", - /*german*/ "", + /*german*/ "der #Schatztruhen-Laden#", /*french*/ "la #Chasse-aux-Trésors#")); // /*spanish*/el Cofre del Tesoro hintTextTable[RHT_MARKET_BOMBCHU_SHOP] = HintText(CustomMessage("the #Bombchu Shop#", - /*german*/ "", + /*german*/ "der #Krabbelminen-Laden#", /*french*/ "le #Magasin de Missiles#")); // /*spanish*/la Tienda Bombchu hintTextTable[RHT_MARKET_MAN_IN_GREEN_HOUSE] = HintText(CustomMessage("Man in Green's House", - /*german*/ "", + /*german*/ "das #Haus des Mannes in grün#", /*french*/ "la #Maison de l'Homme en Vert#")); // /*spanish*/la casa del hombre de verde hintTextTable[RHT_KAK_WINDMILL] = HintText(CustomMessage("the #Windmill#", - /*german*/ "", + /*german*/ "die #Windmühle#", /*french*/ "le #Moulin#")); // /*spanish*/el #molino# hintTextTable[RHT_KAK_CARPENTER_BOSS_HOUSE] = HintText(CustomMessage("the #Carpenters' Boss House#", - /*german*/ "", + /*german*/ "das #Haus des Chefs der Zimmerleute#", /*french*/ "la #Maison du Chef des ouvriers#")); // /*spanish*/la casa del capataz de los carpinteros hintTextTable[RHT_KAK_HOUSE_OF_SKULLTULA] = HintText(CustomMessage("the #House of Skulltula#", - /*german*/ "", + /*german*/ "das #Haus der Skulltula#", /*french*/ "la #Maison des Skulltulas#")); // /*spanish*/la casa de las Skulltulas hintTextTable[RHT_KAK_IMPAS_HOUSE] = HintText(CustomMessage("Impa's House", - /*german*/ "", + /*german*/ "das #Haus von Impa#", /*french*/ "la #Maison d'Impa#")); // /*spanish*/la casa de Impa hintTextTable[RHT_KAK_IMPAS_HOUSE_BACK] = HintText(CustomMessage("Impa's cow cage", - /*german*/ "", + /*german*/ "der #Kuhkäfig von Impa#", /*french*/ "la #cage à vache d'Impa#")); // /*spanish*/la jaula de la vaca de Impa hintTextTable[RHT_KAK_ODD_POTION_BUILDING] = HintText(CustomMessage("Granny's Potion Shop", - /*german*/ "", + /*german*/ "Asas Hexenladen", /*french*/ "la #maison bleue de Cocorico#")); // /*spanish*/la tienda de pociones de la abuela hintTextTable[RHT_GRAVEYARD_DAMPES_HOUSE] = HintText(CustomMessage("Dampé's Hut", - /*german*/ "", + /*german*/ "der #Hut von Boris#", /*french*/ "la #Cabane du Fossoyeur#")); // /*spanish*/la cabaña de Dampé hintTextTable[RHT_GC_SHOP] = HintText(CustomMessage("the #Goron Shop#", - /*german*/ "", + /*german*/ "der #Goronen-Laden#", /*french*/ "la #Boutique Goron#")); // /*spanish*/la #tienda goron# hintTextTable[RHT_ZD_SHOP] = HintText(CustomMessage("the #Zora Shop#", - /*german*/ "", + /*german*/ "der #Zora-Laden#", /*french*/ "la #Boutique Zora#")); // /*spanish*/la #tienda zora# hintTextTable[RHT_LLR_TALONS_HOUSE] = HintText(CustomMessage("Talon's House", - /*german*/ "", + /*german*/ "das #Haus von Talon#", /*french*/ "la #Maison de Talon#")); // /*spanish*/la casa de Talon hintTextTable[RHT_LLR_STABLES] = HintText(CustomMessage("a #stable#", - /*german*/ "", + /*german*/ "ein #Stall#", /*french*/ "l'#Étable#")); // /*spanish*/el establo hintTextTable[RHT_LLR_TOWER] = HintText(CustomMessage("the #Lon Lon Tower#", - /*german*/ "", + /*german*/ "der #Lon Lon-Turm#", /*french*/ "le #silo du Ranch Lon Lon#")); // /*spanish*/la torre Lon Lon hintTextTable[RHT_MARKET_BAZAAR] = HintText(CustomMessage("the #Market Bazaar#", - /*german*/ "", + /*german*/ "der #Basar des Marktes#", /*french*/ "le #Bazar de la Place du Marché#")); // /*spanish*/el bazar de la plaza del mercado hintTextTable[RHT_MARKET_SHOOTING_GALLERY] = HintText(CustomMessage("a #Slingshot Shooting Gallery#", - /*german*/ "", + /*german*/ "die #Schießbude des Marktes#", /*french*/ "le #Jeu d'Adresse de la Place du Marché#")); // /*spanish*/el Tiro al Blanco con tirachinas hintTextTable[RHT_KAK_BAZAAR] = HintText(CustomMessage("the #Kakariko Bazaar#", - /*german*/ "", + /*german*/ "der #Basar von Kakariko#", /*french*/ "le #Bazar de Cocorico#")); // /*spanish*/el bazar de Kakariko hintTextTable[RHT_KAK_POTION_SHOP_FRONT] = HintText(CustomMessage("the #Kakariko Potion Shop#", - /*german*/ "", + /*german*/ "der #Magie-Laden von Kakariko#", /*french*/ "l'#apothicaire de Cocorico#")); // /*spanish*/la tienda de pociones de Kakariko hintTextTable[RHT_KAK_POTION_SHOP_BACK] = HintText(CustomMessage("the #Kakariko Potion Shop#", - /*german*/ "", + /*german*/ "der #Magie-Laden von Kakariko#", /*french*/ "l'#apothicaire de Cocorico#")); // /*spanish*/la tienda de pociones de Kakariko hintTextTable[RHT_KAK_SHOOTING_GALLERY] = HintText(CustomMessage("a #Bow Shooting Gallery#", - /*german*/ "", + /*german*/ "eine #Schießbude von Kakariko#", /*french*/ "le #jeu d'adresse de Cocorico#")); // /*spanish*/el Tiro al Blanco con arco hintTextTable[RHT_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_HC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_OGC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_DMC_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_DMT_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_ZF_GREAT_FAIRY_FOUNTAIN] = HintText(CustomMessage("a #Great Fairy Fountain#", - /*german*/ "", + /*german*/ "eine #Feen-Quelle#", /*french*/ "une #Fontaine Royale des Fées#")); // /*spanish*/una fuente de la Gran Hada hintTextTable[RHT_GRAVEYARD_SHIELD_GRAVE] = HintText(CustomMessage("a #grave with a free chest#", - /*german*/ "", + /*german*/ "ein #Grab mit einer Gratistruhe#", /*french*/ "le #tombeau avec un trésor#")); // /*spanish*/la #tumba con un cofre# hintTextTable[RHT_GRAVEYARD_HEART_PIECE_GRAVE] = HintText(CustomMessage("a chest spawned by #Sun's Song#", - /*german*/ "", + /*german*/ "eine von der #Hymne der Sonne# geschaffene Truhe", /*french*/ "un #coffre apparaît avec le Chant du Soleil#")); // /*spanish*/la #tumba de la Canción del Sol# hintTextTable[RHT_GRAVEYARD_COMPOSERS_GRAVE] = HintText(CustomMessage("the #Composers' Grave#", - /*german*/ "", + /*german*/ "das Königsgrab", /*french*/ "la #Tombe royale#")); // /*spanish*/el #Panteón Real# hintTextTable[RHT_GRAVEYARD_DAMPES_GRAVE] = HintText(CustomMessage("Dampé's Grave", - /*german*/ "", + /*german*/ "das Grab von Boris", /*french*/ "la #Tombe d'Igor#")); // /*spanish*/la #tumba de Dampé# hintTextTable[RHT_DMT_COW_GROTTO] = HintText(CustomMessage("a solitary #Cow#", - /*german*/ "", + /*german*/ "eine solitäre #Kuh#", /*french*/ "la #grotte avec une vache#")); // /*spanish*/una #vaca# solitaria + hintTextTable[RHT_HC_STORMS_GROTTO] = HintText(CustomMessage("a sandy grotto with #fragile walls#", - /*german*/ "", + /*german*/ "eine sandige Grotte mit #fragilen Wänden#", /*french*/ "la #grotte avec des murs fragiles#")); // /*spanish*/la arenosa gruta de #frágiles paredes# hintTextTable[RHT_HF_TEKTITE_GROTTO] = HintText(CustomMessage("a pool guarded by a #Tektite#", - /*german*/ "", + /*german*/ "ein poolbewachender #Arachno#", /*french*/ "l'#étang sous-terrain avec un Araknon#")); // /*spanish*/un charco custodiado por un #Tektite# hintTextTable[RHT_HF_NEAR_KAK_GROTTO] = HintText(CustomMessage("a #Big Skulltula# guarding a Gold one", - /*german*/ "", + /*german*/ "eine goldene Skulltula bewachende #große Skulltula#", /*french*/ "la #grotte d'araignées#")); // /*spanish*/una #gran Skulltula# custodiando una dorada hintTextTable[RHT_HF_COW_GROTTO] = HintText(CustomMessage("a grotto full of #spider webs#", - /*german*/ "", + /*german*/ "eine mit #Spinnweben# gefüllte Grotte", /*french*/ "la #grotte couverte de toiles d'araignées#")); // /*spanish*/una gruta llena de #telarañas# hintTextTable[RHT_KAK_REDEAD_GROTTO] = HintText(CustomMessage("#ReDeads# guarding a chest", - /*german*/ "", + /*german*/ "truhenbewachende #Remorts#", /*french*/ "le tombeau de #deux morts#")); // /*spanish*/los #ReDeads# que custodian un cofre hintTextTable[RHT_SFM_WOLFOS_GROTTO] = HintText(CustomMessage("#Wolfos# guarding a chest", - /*german*/ "", + /*german*/ "truhenbewachende #Wolfos#", /*french*/ "la #grotte iridescente#")); // /*spanish*/los #Wolfos# que custodian un cofre hintTextTable[RHT_GV_OCTOROK_GROTTO] = HintText(CustomMessage("an #Octorok# guarding a rich pool", - /*german*/ "", + /*german*/ "ein poolbewachender #Oktorok#", /*french*/ "un #étang sous-terrain avec un Octorok#")); // /*spanish*/un #Octorok# que custodia un lujoso charco hintTextTable[RHT_DEKU_THEATER] = HintText(CustomMessage("the #Lost Woods Stage#", - /*german*/ "", + /*german*/ "die #Verlorenen Wälder#", /*french*/ "le #théâtre sylvestre#")); // /*spanish*/el #escenario del Bosque Perdido# hintTextTable[RHT_ZR_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# + hintTextTable[RHT_DMC_UPPER_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_DMT_STORMS_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_KAK_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_HF_NEAR_MARKET_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_HF_OPEN_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# + hintTextTable[RHT_HF_SOUTHEAST_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_KF_STORMS_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_LW_NEAR_SHORTCUTS_GROTTO] = HintText(CustomMessage("a #generic grotto#", - /*german*/ "", + /*german*/ "eine #generische Grotte#", /*french*/ "une #grotte avec un trésor#")); // /*spanish*/una #cueva genérica# hintTextTable[RHT_HF_INSIDE_FENCE_GROTTO] = HintText(CustomMessage("a #single Upgrade Deku Scrub#", - /*german*/ "", + /*german*/ "ein #einzelner Upgrade-Deku#", /*french*/ "une #grotte avec une peste Mojo#")); // /*spanish*/una cueva con un #solitario mercader deku# hintTextTable[RHT_LW_SCRUBS_GROTTO] = HintText(CustomMessage("#2 Deku Scrubs# including an Upgrade one", - /*german*/ "", + /*german*/ "#zwei Dekus# inklusive einem Upgrade-Deku", /*french*/ "une #grotte avec deux pestes Mojo#")); // /*spanish*/una cueva con #dos mercaderes deku# hintTextTable[RHT_COLOSSUS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", - /*german*/ "", + /*german*/ "zwei Dekus", /*french*/ "une #grotte avec deux pestes Mojo#")); // /*spanish*/una cueva con #dos mercaderes deku# hintTextTable[RHT_ZR_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", - /*german*/ "", + /*german*/ "zwei Dekus", /*french*/ "une #grotte avec deux pestes Mojo#")); // /*spanish*/una cueva con #dos mercaderes deku# hintTextTable[RHT_SFM_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", - /*german*/ "", + /*german*/ "zwei Dekus", /*french*/ "une #grotte avec deux pestes Mojo#")); // /*spanish*/una cueva con #dos mercaderes deku# hintTextTable[RHT_GV_STORMS_GROTTO] = HintText(CustomMessage("2 Deku Scrubs", - /*german*/ "", + /*german*/ "zwei Dekus", /*french*/ "une #grotte avec deux pestes Mojo#")); // /*spanish*/una cueva con #dos mercaderes deku# hintTextTable[RHT_LH_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", - /*german*/ "", + /*german*/ "drei Dekus", /*french*/ "une #grotte avec trois pestes Mojo#")); // /*spanish*/una cueva con #tres mercaderes deku# hintTextTable[RHT_DMC_HAMMER_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", - /*german*/ "", + /*german*/ "drei Dekus", /*french*/ "une #grotte avec trois pestes Mojo#")); // /*spanish*/una cueva con #tres mercaderes deku# hintTextTable[RHT_GC_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", - /*german*/ "", + /*german*/ "drei Dekus", /*french*/ "une #grotte avec trois pestes Mojo#")); // /*spanish*/una cueva con #tres mercaderes deku# hintTextTable[RHT_LLR_GROTTO] = HintText(CustomMessage("3 Deku Scrubs", - /*german*/ "", + /*german*/ "drei Dekus", /*french*/ "une #grotte avec trois pestes Mojo#")); // /*spanish*/una cueva con #tres mercaderes deku# hintTextTable[RHT_ZR_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", - /*german*/ "", + /*german*/ "ein kleiner #Feen-Brunnen#", /*french*/ "une #fontaine de fées#")); // /*spanish*/una pequeña #fuente de hadas# hintTextTable[RHT_HF_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", - /*german*/ "", + /*german*/ "ein kleiner #Feen-Brunnen#", /*french*/ "une #fontaine de fées#")); // /*spanish*/una pequeña #fuente de hadas# hintTextTable[RHT_SFM_FAIRY_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", - /*german*/ "", + /*german*/ "ein kleiner #Feen-Brunnen#", /*french*/ "une #fontaine de fées#")); // /*spanish*/una pequeña #fuente de hadas# hintTextTable[RHT_ZD_STORMS_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", - /*german*/ "", + /*german*/ "ein kleiner #Feen-Brunnen#", /*french*/ "une #fontaine de fées#")); // /*spanish*/una pequeña #fuente de hadas# hintTextTable[RHT_GF_STORMS_GROTTO] = HintText(CustomMessage("a small #Fairy Fountain#", - /*german*/ "", + /*german*/ "ein kleiner #Feen-Brunnen#", /*french*/ "une #fontaine de fées#")); // /*spanish*/una pequeña #fuente de hadas# @@ -1503,9 +1512,9 @@ void StaticData::HintTable_Init() { // /*spanish*/Salva tu futuro, acaba con el dueño de La Máscara Feliz. hintTextTable[RHT_JUNK11] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.", - /*german*/ "Los glitches son el camino a muchas habilidades que varios consideran... nada natural.", + /*german*/ "", /*french*/ "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire ")); - // /*spanish*/à la nature. + // /*spanish*/ Los glitches son el camino a muchas habilidades que varios consideran... nada natural. hintTextTable[RHT_JUNK12] = HintText(CustomMessage("I'm stoned. Get it?", /*german*/ "", @@ -2261,122 +2270,122 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_DEKU_TREE] = HintText(CustomMessage("Deku Tree", - /*german*/ "", + /*german*/ "Deku-Baum", /*french*/ "l'Arbre Mojo"), // /*spanish*/el Gran Árbol Deku {}, {CustomMessage("an ancient tree", - /*german*/ "", + /*german*/ "ein antiker Baum", /*french*/ "le vieil arbre")}); // /*spanish*/un ancestral árbol hintTextTable[RHT_DODONGOS_CAVERN] = HintText(CustomMessage("Dodongo's Cavern", - /*german*/ "", + /*german*/ "Dodongos Kaverne", /*french*/ "la Caverne Dodongo"), // /*spanish*/la Cueva de los Dodongos {}, {CustomMessage("an immense cavern", - /*german*/ "", + /*german*/ "eine riesige Kaverne", /*french*/ "l'immense caverne")}); // /*spanish*/una descomunal cueva hintTextTable[RHT_JABU_JABUS_BELLY] = HintText(CustomMessage("Jabu-Jabu's Belly", - /*german*/ "", + /*german*/ "Jabu-Jabus Bauch", /*french*/ "le Ventre de Jabu-Jabu"), // /*spanish*/tripa de Jabu-Jabu {}, {CustomMessage("the belly of a deity", - /*german*/ "", + /*german*/ "der Bauch einer Gottheit", /*french*/ "le ventre d'un gardien")}); // /*spanish*/la tripa de cierta deidad hintTextTable[RHT_FOREST_TEMPLE] = HintText(CustomMessage("Forest Temple", - /*german*/ "", + /*german*/ "Waldtempel", /*french*/ "le Temple de la Forêt"), // /*spanish*/el Templo del Bosque {}, {CustomMessage("a deep forest", - /*german*/ "", + /*german*/ "ein tiefer Wald", /*french*/ "la profonde forêt")}); // /*spanish*/las profundidades del bosque hintTextTable[RHT_FIRE_TEMPLE] = HintText(CustomMessage("Fire Temple", - /*german*/ "", + /*german*/ "Feuertempel", /*french*/ "le Temple du Feu"), // /*spanish*/el Templo del Fuego {}, {CustomMessage("a high mountain", - /*german*/ "", + /*german*/ "ein hoher Berg", /*french*/ "la grande montagne")}); // /*spanish*/una alta montaña hintTextTable[RHT_WATER_TEMPLE] = HintText(CustomMessage("Water Temple", - /*german*/ "", + /*german*/ "Wassertempel", /*french*/ "le Temple de l'Eau"), // /*spanish*/el Templo del Agua {}, {CustomMessage("a vast lake", - /*german*/ "", + /*german*/ "ein gewaltiger See", /*french*/ "le vaste lac")}); // /*spanish*/un lago inmenso hintTextTable[RHT_SPIRIT_TEMPLE] = HintText(CustomMessage("Spirit Temple", - /*german*/ "", + /*german*/ "Geistertempel", /*french*/ "le Temple de l'Esprit"), // /*spanish*/el Templo del Espíritu {}, {CustomMessage("the goddess of the sand", - /*german*/ "", + /*german*/ "die Göttin des Sandes", /*french*/ "la déesse des sables")}); // /*spanish*/la diosa de las arenas hintTextTable[RHT_SHADOW_TEMPLE] = HintText(CustomMessage("Shadow Temple", - /*german*/ "", + /*german*/ "Schattentempel", /*french*/ "le Temple de l'Ombre"), // /*spanish*/el Templo de las Sombras {}, {CustomMessage("the house of the dead", - /*german*/ "", + /*german*/ "das Haus der Toten", /*french*/ "la maison des morts")}); // /*spanish*/la casa de la muerte hintTextTable[RHT_ICE_CAVERN] = HintText(CustomMessage("Ice Cavern", - /*german*/ "", + /*german*/ "Eishöhle", /*french*/ "la caverne de glace"), // /*spanish*/la caverna de hielo {}, {CustomMessage("a frozen maze", - /*german*/ "", + /*german*/ "ein gefrorenes Labyrinth", /*french*/ "le dédale glacé")}); // /*spanish*/un gélido laberinto hintTextTable[RHT_BOTTOM_OF_THE_WELL] = HintText(CustomMessage("Bottom of the Well", - /*german*/ "", + /*german*/ "Grund des Brunnens", /*french*/ "le fonds du Puits"), // /*spanish*/el fondo del pozo {}, {CustomMessage("a shadow\'s prison", - /*german*/ "", + /*german*/ "das Gefängnis eines Schattens", /*french*/ "la prison d'une ombre")}); // /*spanish*/la prisión de las sombras hintTextTable[RHT_GERUDO_TRAINING_GROUND] = HintText(CustomMessage("Gerudo Training Grounds", - /*german*/ "", + /*german*/ "Gerudo-Trainingsgelände", /*french*/ "le Gymnase Gerudo"), // /*spanish*/el Centro de Instrucción Gerudo {}, {CustomMessage("the test of thieves", - /*german*/ "", + /*german*/ "die Prüfung der Diebe", /*french*/ "l'épreuve des voleurs")}); // /*spanish*/la prueba de las bandidas hintTextTable[RHT_GANONS_CASTLE] = HintText(CustomMessage("Inside Ganon's Castle", - /*german*/ "", + /*german*/ "In Ganons Schloß", /*french*/ "l'intérieur du Château de Ganon"), // /*spanish*/el interior del Castillo de Ganon {}, {CustomMessage("a conquered citadel", - /*german*/ "", + /*german*/ "eine eroberte Zitadelle", /*french*/ "la citadelle assiégée")}); // /*spanish*/una conquistada ciudadela @@ -2385,82 +2394,82 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_QUEEN_GOHMA] = HintText(CustomMessage("#Queen Gohma# holds", - /*german*/ "", + /*german*/ "#Königin Gohma# hält", /*french*/ "la #Reine Gohma# possède"), // /*spanish*/la #Reina Goma# porta {}, {CustomMessage("the #Parasitic Armored Arachnid# holds", - /*german*/ "", + /*german*/ "die #gepanzerte parasitäre Spinne# hält", /*french*/ "le #monstre insectoïde géant# possède")}); // /*spanish*/el #arácnido parasitario acorazado# porta hintTextTable[RHT_KING_DODONGO] = HintText(CustomMessage("#King Dodongo# holds", - /*german*/ "", + /*german*/ "#König Dodongo# hält", /*french*/ "le #Roi Dodongo# possède"), // /*spanish*/el #Rey Dodongo# porta {}, {CustomMessage("the #Infernal Dinosaur# holds", - /*german*/ "", + /*german*/ "der #infernalische Dinosaurier# hält", /*french*/ "le #dinosaure infernal# possède")}); // /*spanish*/el #dinosaurio infernal# porta hintTextTable[RHT_BARINADE] = HintText(CustomMessage("#Barinade# holds", - /*german*/ "", + /*german*/ "#Barinade# hält", /*french*/ "#Barinade# possède"), // /*spanish*/#Barinade# porta {}, {CustomMessage("the #Bio-Electric Anemone# holds", - /*german*/ "", + /*german*/ "die #bioelektrische Anemone# hält", /*french*/ "l'#anémone bioélectrique# possède")}); // /*spanish*/la #anémona bioeléctrica# porta hintTextTable[RHT_PHANTOM_GANON] = HintText(CustomMessage("#Phantom Ganon# holds", - /*german*/ "", + /*german*/ "#Phantom-Ganon# hält", /*french*/ "#Ganon Spectral# possède"), // /*spanish*/#Ganon Fantasma# porta {}, {CustomMessage("the #Evil Spirit from Beyond# holds", - /*german*/ "", + /*german*/ "der #böse Geist aus dem Jenseits# hält", /*french*/ "l'#esprit maléfique de l'au-delà# possède")}); // /*spanish*/el #espíritu maligno de ultratumba# porta hintTextTable[RHT_VOLVAGIA] = HintText(CustomMessage("#Volvagia# holds", - /*german*/ "", + /*german*/ "#Volvagia# hält", /*french*/ "#Volvagia# possède"), // /*spanish*/#Volvagia# porta {}, {CustomMessage("the #Subterranean Lava Dragon# holds", - /*german*/ "", + /*german*/ "der #subterrane Lavadrache# hält", /*french*/ "le #dragon des profondeurs# possède")}); // /*spanish*/el #dragón de lava subterráneo# porta hintTextTable[RHT_MORPHA] = HintText(CustomMessage("#Morpha# holds", - /*german*/ "", + /*german*/ "#Morpha# hält", /*french*/ "#Morpha# possède"), // /*spanish*/#Morpha# porta {}, {CustomMessage("the #Giant Aquatic Amoeba# holds", - /*german*/ "", + /*german*/ "die #gigantische aquatische Amöbe# hält", /*french*/ "l'#amibe aquatique géante# possède")}); // /*spanish*/la #ameba acuática gigante# porta hintTextTable[RHT_BONGO_BONGO] = HintText(CustomMessage("#Bongo Bongo# holds", - /*german*/ "", + /*german*/ "#Bongo Bongo# hält", /*french*/ "#Bongo Bongo# possède"), // /*spanish*/#Bongo Bongo# porta {}, {CustomMessage("the #Phantom Shadow Beast# holds", - /*german*/ "", + /*german*/ "das #Phantomschattenbiest# hält", /*french*/ "le #monstre de l'ombre# possède")}); // /*spanish*/la #alimaña oscura espectral# porta hintTextTable[RHT_TWINROVA] = HintText(CustomMessage("#Twinrova# holds", - /*german*/ "", + /*german*/ "#Twinrova# hält", /*french*/ "#Twinrova# possède"), // /*spanish*/#Birova# porta {}, {CustomMessage("the #Sorceress Sisters# hold", - /*german*/ "", + /*german*/ "die #Hexenschwestern# halten", /*french*/ "#les sorcières jumelles# possède")}); // /*spanish*/las #hermanas hechiceras# portan /*-------------------------- @@ -2468,34 +2477,34 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_BRIDGE_OPEN_HINT] = HintText(CustomMessage("$lThe awakened ones have #already created a bridge# to the castle where the evil dwells.^", - /*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloss gelegt#...^", + /*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloß gelegt#...^", /*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^", {QM_LBLUE})); // /*spanish*/$lLos sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.^ hintTextTable[RHT_BRIDGE_VANILLA_HINT] = HintText(CustomMessage("$6The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.^", - /*german*/ "$6Die Weisen werden darauf warten, dass der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt.^", + /*german*/ "$6Die Weisen werden darauf warten, daß der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt.^", /*french*/ "$6Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.^", {QM_RED, QM_YELLOW})); // /*spanish*/$6Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto // a la #flecha de luz#.^ hintTextTable[RHT_BRIDGE_STONES_HINT] = HintText(CustomMessage("$0The awakened ones will await for the Hero to collect #[[d]] Spiritual Stone||s|#.^", - /*german*/ "$0Die Weisen werden darauf warten, dass der Held #[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^", + /*german*/ "$0Die Weisen werden darauf warten, daß der Held #[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^", /*french*/ "$0Les êtres de sagesse attendront le héros muni de #[[d]] |Pierre Ancestrale|Pierres Ancestrales|#.^", {QM_BLUE})); // /*spanish*/$0Los sabios aguardarán a que el héroe&obtenga #[[d]] |piedra espiritual|piedras espirituales|#.^ hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText(CustomMessage("$8The awakened ones will await for the Hero to collect #[[d]] Medallion||s|#.^", - /*german*/ "$8Die Weisen werden darauf warten, dass der Held #[[d]] Amulett||e|# sammelt.^", + /*german*/ "$8Die Weisen werden darauf warten, daß der Held #[[d]] Amulett||e|# sammelt.^", /*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^", {QM_RED})); // /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^ hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|" "#Spiritual Stones# and #Medallions#|.^", - /*german*/ "$CDie Weisen werden darauf warten, dass der Held #[[d]]# |#Heiligen Stein# oder #Amulett#|" + /*german*/ "$CDie Weisen werden darauf warten, daß der Held #[[d]]# |#Heiligen Stein# oder #Amulett#|" "#Heilige Steine# oder #Amulette#| sammelt.^", /*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#" "|#Pierres Ancestrales# ou #Médaillons#|.^", @@ -2504,13 +2513,13 @@ void StaticData::HintTable_Init() { //#piedras espirtuales# y #medallones#|.^ hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^", - /*german*/ "$mDie Weisen werden darauf warten, dass der Held #[[d]] Labyrinth||e|# abschließt.^", + /*german*/ "$mDie Weisen werden darauf warten, daß der Held #[[d]] Labyrinth||e|# abschließt.^", /*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^", {QM_PINK})); // /*spanish*/$mLos sabios aguardarán a que el héroe complete #[[d]] mazmorra||s|#.^ hintTextTable[RHT_BRIDGE_TOKENS_HINT] = HintText(CustomMessage("$sThe awakened ones will await for the Hero to collect #[[d]] Gold Skulltula Token||s|#.^", - /*german*/ "$sDie Weisen werden darauf warten, dass der Held #[[d]] Skulltula-Symbol||e|# sammelt.^", + /*german*/ "$sDie Weisen werden darauf warten, daß der Held #[[d]] Skulltula-Symbol||e|# sammelt.^", /*french*/ "$sLes êtres de sagesse attendront le héros muni de #[[d]] Symbole||s| de Skulltula d'or#.^", {QM_YELLOW})); // /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^ @@ -2536,7 +2545,7 @@ void StaticData::HintTable_Init() { // /*spanish*/$bY la llave del #señor del mal# aguardará en un gran cofre de #su torre#.^ hintTextTable[RHT_GANON_BK_OWN_DUNGEON_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be hidden somewhere #inside its castle#.^", - /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Ganons Schloss# zu finden sein.^", + /*german*/ "$bUnd der #Schlüssel des Bösen#, wird irgendwo #in Ganons Schloß# zu finden sein.^", /*french*/ "$bAussi, la #clé du Malin# sera cachée #dans son vaste château#.^", {QM_PINK, QM_PINK})); // /*spanish*/$bY la llave del #señor del mal# aguardará en #algún lugar de su castillo#.^ @@ -2566,7 +2575,7 @@ void StaticData::HintTable_Init() { // /*spanish*/$bY el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#.^ hintTextTable[RHT_GANON_BK_SKULLTULA_HINT] = HintText(CustomMessage("$bAnd the #evil one#'s key will be provided by the cursed rich man once #100 Gold Skulltula Tokens# are retrieved.^", - /*german*/ "", + /*german*/ "$bUnd der #Schlüssel des Bösen# wird von einem verfluchten reichen Mann verliehen, sobald #100 Goldene Skulltula-Symbole# wiedererlangt wurden.^", /*french*/ "$bAussi, la #clé du Malin# sera&donnée par l'homme maudit une fois que #100 Symboles de Skulltula d'or# auront été trouvés.^", {QM_PINK, QM_YELLOW})); // /*spanish*/$bY el rico maldito entregará la llave&del #señor de mal# tras obtener&100 símbolos de skulltula dorada#.^ @@ -2614,52 +2623,52 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_SIX_TRIALS] = HintText(CustomMessage("They say that #Ganon's Tower# is protected by a powerful barrier.", - /*german*/ "Man erzählt sich, daß der #Teufelsturm# sei von einer mächtigen Barriere geschützt sei.", + /*german*/ "Man erzählt sich, daß der #Teufelsturm# von einer mächtigen Barriere geschützt sei.", /*french*/ "Selon moi, #la Tour de Ganon# est protégée par une puissante barrière", {QM_PINK})); // /*spanish*/Según dicen, la #torre de Ganon# está protegida por una poderosa barrera hintTextTable[RHT_ZERO_TRIALS] = HintText(CustomMessage("They say that Sheik dispelled the barrier around #Ganon's Tower#.", - /*german*/ "Man erzählt sich, Shiek habe die Barriere um den #Teufelsturm# aufgelöst sei.", + /*german*/ "Man erzählt sich, Shiek habe die Barriere um den #Teufelsturm# aufgelöst.", /*french*/ "Selon moi, Sheik a dissipé la barrière autour de #la Tour de Ganon#", {QM_YELLOW})); // /*spanish*/Según dicen, Sheik disipó la barrera alrededor de la #torre de Ganon#. hintTextTable[RHT_TRIAL_OFF] = HintText(CustomMessage("They say that #[[1]]# was dispelled by Sheik.", - /*german*/ "Man erzählt sich, daß #[[1]]# sei von Shiek aufgelöst worden sei.", + /*german*/ "Man erzählt sich, daß #[[1]]# von Shiek aufgelöst worden sei.", /*french*/ "Selon moi, #[[1]]# a été dissipée par Sheik.", {QM_YELLOW})); // /*spanish*/Según dicen, #[[1]]# se disipó gracias a Sheik. hintTextTable[RHT_TRIAL_ON] = HintText(CustomMessage("They say that #[[1]]# protects Ganons Tower.", - /*german*/ "Man erzählt sich, daß #[[1]]# schütze den Teufelsturm sei.", + /*german*/ "Man erzählt sich, daß #[[1]]# den Teufelsturm schütze.", /*french*/ "Selon moi, #[[1]]# protège la Tour de Ganon.", {QM_PINK})); // /*spanish*/Según dicen, #[[1]]# protege la torre de Ganon hintTextTable[RHT_LIGHT_TRIAL] = HintText(CustomMessage("the Light Trial", - /*german*/ "", + /*german*/ "die Prüfung des Lichts", /*french*/ "l'épreuve de la Lumière")); // /*spanish*/la prueba de la luz hintTextTable[RHT_FOREST_TRIAL] = HintText(CustomMessage("the Forest Trial", - /*german*/ "", + /*german*/ "die Prüfung des Waldes", /*french*/ "l'épreuve de la Forêt")); // /*spanish*/la prueba del bosque hintTextTable[RHT_FIRE_TRIAL] = HintText(CustomMessage("the Fire Trial", - /*german*/ "", + /*german*/ "die Prüfung des Feuers", /*french*/ "l'épreuve du Feu")); // /*spanish*/la prueba del fuego hintTextTable[RHT_WATER_TRIAL] = HintText(CustomMessage("the Water Trial", - /*german*/ "", + /*german*/ "die Prüfung des Wassers", /*french*/ "l'épreuve de l'Eau")); // /*spanish*/la prueba del agua hintTextTable[RHT_SPIRIT_TRIAL] = HintText(CustomMessage("the Spirit Trial", - /*german*/ "", + /*german*/ "die Prüfung der Geister", /*french*/ "l'épreuve de l'Esprit")); // /*spanish*/la prueba del espíritu hintTextTable[RHT_SHADOW_TRIAL] = HintText(CustomMessage("the Shadow Trial", - /*german*/ "", + /*german*/ "die Prüfung des Schattens", /*french*/ "l'épreuve de l'Ombre")); // /*spanish*/la prueba de las sombras @@ -2699,7 +2708,7 @@ void StaticData::HintTable_Init() { // $8#[[1]]#...^$3#[[2]]#...^$4#[[3]]#...^$5#[[4]]#...^$6#[[5]]#...^$7#[[6]]#...^ hintTextTable[RHT_ADULT_ALTAR_TEXT_END] = HintText(CustomMessage("$kTogether with the Hero of Time, the awakened ones will return the light of peace to the world...", - /*german*/ "$kZusammen mit dem Auserwählten wer-den diese ihre Kräfte einsetzen, um der Welt den Frieden wiederzugeben.", + /*german*/ "$kZusammen mit dem Auserwählten werden diese ihre Kräfte einsetzen, um der Welt den Frieden wiederzugeben.", /*french*/ "$kEnsemble avec le Héros du Temps, ces Sages emprisonneront le mal et réinstaureront la lumière de paix dans le monde...")); // /*spanish*/Con el Héroe del Tiempo, aquellos&que despierten detendrán el mal y&volverán al mundo de luz la paz... @@ -2733,7 +2742,7 @@ void StaticData::HintTable_Init() { {QM_YELLOW, QM_RED})); hintTextTable[RHT_DAMPE_DIARY] = HintText(CustomMessage("Whoever reads this, please enter #[[1]]#. I will let you have my #stretching, shrinking keepsake#.^I'm waiting for you.&--Dampé", - /*german*/ "Wer immer dies liest, der möge folgenden Ort aufsuchen: #[[1]]#. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris", //RANDOTODO color in whatever refers to the hookshot + /*german*/ "Wer immer dies liest, der möge folgenden Ort aufsuchen: #[[1]]#. Ihm gebe ich meinen #dehnenden, schrumpfenden Schatz#.^Ich warte!&Boris", //RANDOTODO color in whatever refers to the hookshot /*french*/ "Toi qui lit ce journal, rends-toi dans #[[1]]#. Et peut-être auras-tu droit à mon précieux #trésor#.^Je t'attends...&--Igor", {QM_RED, QM_RED})); @@ -2772,20 +2781,20 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_MEDIGORON_HINT] = HintText(CustomMessage("How about buying #[[1]]# for #200 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*german*/ "Möchtest du #[[1]]# für #200 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Klar!&Nie im Leben!#", + /*german*/ "Möchtest Du #[[1]]# für #200 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Klar!&Nie im Leben!#", /*french*/ "Veux-tu acheter #[[1]]# pour #200 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", {QM_GREEN, QM_YELLOW, QM_GREEN})); /*spanish*/ // ¿Me compras #[[1]]# por #200 rupias#?&" + TWO_WAY_CHOICE() + "#Comprar&No comprar# hintTextTable[RHT_CARPET_SALESMAN_DIALOG_FIRST] = HintText(CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", - /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten. Stets sonderliche und seltene Ware aus " + /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " "aller Welt für jedermann. Das heutige Angebot bleibt...^#", /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^")); /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ hintTextTable[RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS] = HintText(CustomMessage("Terrifying! I won't tell you what it is until I see the #money#...^How about #200 Rupees#?&&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*german*/ "Furchterregend oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #200 Rubinen#?&&" + + /*german*/ "Furchterregend, oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #200 Rubinen#?&&" + TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#", /*french*/ "Un concentré de puissance! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #200 " "rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", @@ -2795,7 +2804,7 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_CARPET_SALESMAN_DIALOG_HINTED] = HintText(CustomMessage("#[[1]]!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^" "How about #200 Rupees#?&&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*german*/ "#[[1]]#! Ich kann versichern es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich doch " + /*german*/ "#[[1]]#! Ich kann versichern, es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde Dich doch " "nicht #anlügen#, oder?^Wie wär's mit #200 Rubinen#?&&" + TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#", /*french*/ "#[[1]]!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #200 " "rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", @@ -2803,13 +2812,13 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_BEAN_SALESMAN_HINT] = HintText(CustomMessage("I tried to be a #magic bean# salesman, but it turns out my marketing skills weren't worth " "beans!^Anyway, want to buy #[[1]]# for #60 Rupees#?&" + TWO_WAY_CHOICE() + "#Yes&No#", - /*german*/ "Möchten Sie #[[1]]# für #60 Rubine#?&" + TWO_WAY_CHOICE() + "#Ja&Nein#", + /*german*/ "Möchten Sie #[[1]]# für #60 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Ja&Nein#", /*french*/ "J'ai essayé d'être un vendeur de #haricots magiques#, mais j'étais mauvais au niveau du marketing et ça " "me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter #[[1]]# pour #60 Rubis#?&" + TWO_WAY_CHOICE() + "#Oui&Non#", {QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN})); hintTextTable[RHT_GRANNY_HINT] = HintText(CustomMessage("#[[1]]#! How about #100 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", - /*german*/ "#[[1]]#! Sagen wir #100 Rubine#!&" + TWO_WAY_CHOICE() + "#Gerne!&Auf keinen Fall!#", + /*german*/ "#[[1]]#! Sagen wir #100 Rubine#?&" + TWO_WAY_CHOICE() + "#Gerne!&Auf keinen Fall!#", /*french*/ "#[[1]]#! Que dis-tu de #100 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", {QM_GREEN, QM_YELLOW, QM_GREEN}, {true})); // /*spanish*/#[[1]]#. Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar# @@ -2829,19 +2838,19 @@ void StaticData::HintTable_Init() { "Prove yourself to be a horsemaster by scoring 1500 points to win my #[[1]]#!\x0B", {QM_RED, QM_GREEN})); - hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obsticle Course#!^" + hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obstacle Course#!^" "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", {QM_RED, QM_BLUE, QM_GREEN})); - hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obsticle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" - "Challenge the #Obsticle Course?#&\x1B&#Let's go&No thanks#", + hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" + "Challenge the #Obstacle Course?#&\x1B&#Let's go&No thanks#", {QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN})); - hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obsticle Course#, and whoever gets the best time would win a #cow#!^" + hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^" "Elsie loves sharing her #[[1]]# with new people, It'll be fun!^...But Ingo won't let me...", {QM_RED, QM_BLUE, QM_GREEN})); - hintTextTable[RHT_MALON_HINT_INGO_TEMPTED] = HintText(CustomMessage("@! You should come back in the morning and try to beat my time on the #Obsticle Course#!^" + hintTextTable[RHT_MALON_HINT_INGO_TEMPTED] = HintText(CustomMessage("@! You should come back in the morning and try to beat my time on the #Obstacle Course#!^" "If you beat my time, I'll give you my favourite #cow# Elsie and her toy #[[1]]#!", {QM_RED, QM_BLUE, QM_GREEN})); @@ -2943,7 +2952,7 @@ void StaticData::HintTable_Init() { ---------------------------*/ hintTextTable[RHT_YOUR_POCKET] = HintText(CustomMessage("your pocket", - /*german*/ "", + /*german*/ "deine Tasche", /*french*/ "tes poches")); // /*spanish*/tu bolsillo diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index d6e2c2f9a..52bfd1ffc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -6,2058 +6,2058 @@ namespace Rando { void StaticData::HintTable_Init_Item() { - hintTextTable[RHT_KOKIRI_SWORD] = HintText(CustomMessage("the Kokiri Sword", /*german*/"", /*french*/"l'Épée Kokiri"), + hintTextTable[RHT_KOKIRI_SWORD] = HintText(CustomMessage("the Kokiri Sword", /*german*/"das Kokiri-Schwert", /*french*/"l'Épée Kokiri"), // /*spanish*/la Espada Kokiri { - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("a butter knife", /*german*/"", /*french*/"un couteau à beurre"), + CustomMessage("a butter knife", /*german*/"ein Buttermesser", /*french*/"un couteau à beurre"), // /*spanish*/un ágil puñal - CustomMessage("a starter slasher", /*german*/"", /*french*/"une arme de débutant"), + CustomMessage("a starter slasher", /*german*/"ein Anfängerschwert", /*french*/"une arme de débutant"), // /*spanish*/una hoja de principiantes - CustomMessage("a switchblade", /*german*/"", /*french*/"un canif")}); + CustomMessage("a switchblade", /*german*/"ein Stellmesser", /*french*/"un canif")}); // /*spanish*/una navaja - hintTextTable[RHT_MASTER_SWORD] = HintText(CustomMessage("the Master Sword", /*german*/"", /*french*/"l'Épée de Légende"), + hintTextTable[RHT_MASTER_SWORD] = HintText(CustomMessage("the Master Sword", /*german*/"das Master-Schwert", /*french*/"l'Épée de Légende"), // /*spanish*/la Espada Maestra { - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("evil's bane", /*german*/"", /*french*/"le fléau du mal"), + CustomMessage("evil's bane", /*german*/"der böse Fluch", /*french*/"le fléau du mal"), // /*spanish*/la destructora del mal - CustomMessage("a seven year limbo", /*german*/"", /*french*/"une stase de sept ans")}); + CustomMessage("a seven year limbo", /*german*/"eine siebenjährige Erwartung", /*french*/"une stase de sept ans")}); // /*spanish*/unos siete años de espera - hintTextTable[RHT_GIANTS_KNIFE] = HintText(CustomMessage("the Giant's Knife", /*german*/"", /*french*/"la Lame des Géants"), + hintTextTable[RHT_GIANTS_KNIFE] = HintText(CustomMessage("the Giant's Knife", /*german*/"das Langschwert", /*french*/"la Lame des Géants"), // /*spanish*/la daga gigante { - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("a fragile blade", /*german*/"", /*french*/"une lame fragile"), + CustomMessage("a fragile blade", /*german*/"ein fragiles Schwert", /*french*/"une lame fragile"), // /*spanish*/una frágil hoja - CustomMessage("a breakable cleaver", /*german*/"", /*french*/"un espadon de verre")}); + CustomMessage("a breakable cleaver", /*german*/"ein brüchiger Spalter", /*french*/"un espadon de verre")}); // /*spanish*/un rompible acero - hintTextTable[RHT_BIGGORON_SWORD] = HintText(CustomMessage("the Biggoron Sword", /*german*/"", /*french*/"l'Épée de Biggoron"), + hintTextTable[RHT_BIGGORON_SWORD] = HintText(CustomMessage("the Biggoron Sword", /*german*/"das Biggoron-Schwert", /*french*/"l'Épée de Biggoron"), // /*spanish*/la Espada de Biggoron { - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("the biggest blade", /*german*/"", /*french*/"une lame gigantesque"), + CustomMessage("the biggest blade", /*german*/"das größte Schwert", /*french*/"une lame gigantesque"), // /*spanish*/el mayor mandoble - CustomMessage("a colossal cleaver", /*german*/"", /*french*/"un espadon colossal")}); + CustomMessage("a colossal cleaver", /*german*/"ein kolossaler Spalter", /*french*/"un espadon colossal")}); // /*spanish*/un estoque colosal - hintTextTable[RHT_DEKU_SHIELD] = HintText(CustomMessage("a Deku Shield", /*german*/"", /*french*/"un Bouclier Mojo"), + hintTextTable[RHT_DEKU_SHIELD] = HintText(CustomMessage("a Deku Shield", /*german*/"ein Deku-Schild", /*french*/"un Bouclier Mojo"), // /*spanish*/un escudo deku { - CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + CustomMessage("a shield", /*german*/"ein Schild", /*french*/"un bouclier") // /*spanish*/un escudo }, { - CustomMessage("a wooden ward", /*german*/"", /*french*/"un écu d'écorce"), + CustomMessage("a wooden ward", /*german*/"eine hölzerne Abwehr", /*french*/"un écu d'écorce"), // /*spanish*/una protección del bosque - CustomMessage("a burnable barrier", /*german*/"", /*french*/"une protection inflammable")}); + CustomMessage("a burnable barrier", /*german*/"eine brennbare Barriere", /*french*/"une protection inflammable")}); // /*spanish*/una barrera quemable - hintTextTable[RHT_HYLIAN_SHIELD] = HintText(CustomMessage("a Hylian Shield", /*german*/"", /*french*/"un Bouclier Hylien"), + hintTextTable[RHT_HYLIAN_SHIELD] = HintText(CustomMessage("a Hylian Shield", /*german*/"ein Hylia-Schild", /*french*/"un Bouclier Hylien"), // /*spanish*/un escudo hyliano { - CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + CustomMessage("a shield", /*german*/"ein Schild", /*french*/"un bouclier") // /*spanish*/un escudo }, { - CustomMessage("a steel safeguard", /*german*/"", /*french*/"une carapace d'acier"), + CustomMessage("a steel safeguard", /*german*/"ein eiserner Schutz", /*french*/"une carapace d'acier"), // /*spanish*/una protección de acero - CustomMessage("Like Like's metal meal", /*german*/"", /*french*/"un amuse-gueule de Pudding")}); + CustomMessage("Like Like's metal meal", /*german*/"Raubschleims Metallmahlzeit", /*french*/"un amuse-gueule de Pudding")}); // /*spanish*/un alimento de Like Like - hintTextTable[RHT_MIRROR_SHIELD] = HintText(CustomMessage("the Mirror Shield", /*german*/"", /*french*/"le Bouclier Miroir"), + hintTextTable[RHT_MIRROR_SHIELD] = HintText(CustomMessage("the Mirror Shield", /*german*/"das Spiegelschild", /*french*/"le Bouclier Miroir"), // /*spanish*/el escudo espejo { - CustomMessage("a shield", /*german*/"", /*french*/"un bouclier") + CustomMessage("a shield", /*german*/"ein Schild", /*french*/"un bouclier") // /*spanish*/un escudo }, { - CustomMessage("a reflective rampart", /*german*/"", /*french*/"un capteur de lumière"), + CustomMessage("a reflective rampart", /*german*/"ein reflektierender Schutzwall", /*french*/"un capteur de lumière"), // /*spanish*/una muralla reflectora - CustomMessage("Medusa's weakness", /*german*/"", /*french*/"la faiblesse de Méduse"), + CustomMessage("Medusa's weakness", /*german*/"Medusas Schwäche", /*french*/"la faiblesse de Méduse"), // /*spanish*/la debilidad de Medusa - CustomMessage("a silvered surface", /*german*/"", /*french*/"une surface argentée")}); + CustomMessage("a silvered surface", /*german*/"eine silberne Oberfläche", /*french*/"une surface argentée")}); // /*spanish*/una superficie plateada - hintTextTable[RHT_GORON_TUNIC] = HintText(CustomMessage("a Goron Tunic", /*german*/"", /*french*/"une Tunique Goron"), + hintTextTable[RHT_GORON_TUNIC] = HintText(CustomMessage("a Goron Tunic", /*german*/"eine Goronen-Tunika", /*french*/"une Tunique Goron"), // /*spanish*/un sayo goron { - CustomMessage("a tunic", /*german*/"", /*french*/"une tunique") + CustomMessage("a tunic", /*german*/"eine Tunika", /*french*/"une tunique") // /*spanish*/un sayo }, { - CustomMessage("ruby robes", /*german*/"", /*french*/"un pigment rouge"), + CustomMessage("ruby robes", /*german*/"Rubinroben", /*french*/"un pigment rouge"), // /*spanish*/una vestimenta rubí - CustomMessage("fireproof fabric", /*german*/"", /*french*/"un trésor anti-flamme"), + CustomMessage("fireproof fabric", /*german*/"feuerfestes Gewebe", /*french*/"un trésor anti-flamme"), // /*spanish*/una ignífuga prenda - CustomMessage("cooking clothes", /*german*/"", /*french*/"une tenue de cuisine")}); + CustomMessage("cooking clothes", /*german*/"Kochschürze", /*french*/"une tenue de cuisine")}); // /*spanish*/unos abrasantes ropajes - hintTextTable[RHT_ZORA_TUNIC] = HintText(CustomMessage("a Zora Tunic", /*german*/"", /*french*/"une Tunique Zora"), + hintTextTable[RHT_ZORA_TUNIC] = HintText(CustomMessage("a Zora Tunic", /*german*/"eine Zora-Tunika", /*french*/"une Tunique Zora"), // /*spanish*/un sayo zora { - CustomMessage("a tunic", /*german*/"", /*french*/"une tunique"), + CustomMessage("a tunic", /*german*/"eine Tunika", /*french*/"une tunique"), // /*spanish*/un sayo - CustomMessage("something expensive", /*german*/"", /*french*/"une chose dispendieuse") + CustomMessage("something expensive", /*german*/"etwas Teures", /*french*/"une chose dispendieuse") // /*spanish*/algo caro }, { - CustomMessage("a sapphire suit", /*german*/"", /*french*/"un pigment bleuté"), + CustomMessage("a sapphire suit", /*german*/"ein Saphiranzug", /*french*/"un pigment bleuté"), // /*spanish*/una vestidura zafiro - CustomMessage("scuba gear", /*german*/"", /*french*/"un habit de plongée"), + CustomMessage("scuba gear", /*german*/"eine Taucherausrüstung", /*french*/"un habit de plongée"), // /*spanish*/un traje impermeable - CustomMessage("a swimsuit", /*german*/"", /*french*/"un costume de baignade")}); + CustomMessage("a swimsuit", /*german*/"ein Badeanzug", /*french*/"un costume de baignade")}); // /*spanish*/unos ropajes sumergibles - hintTextTable[RHT_IRON_BOOTS] = HintText(CustomMessage("the Iron Boots", /*german*/"", /*french*/"une paire de Bottes de plomb"), + hintTextTable[RHT_IRON_BOOTS] = HintText(CustomMessage("the Iron Boots", /*german*/"die Eisenstiefel", /*french*/"une paire de Bottes de plomb"), // /*spanish*/las botas de hierro { - CustomMessage("some boots", /*german*/"", /*french*/"une paire de bottes"), + CustomMessage("some boots", /*german*/"ein paar Stiefel", /*french*/"une paire de bottes"), // /*spanish*/un par de botas - CustomMessage("a feature of the Water Temple", /*german*/"", /*french*/"une particularité du Temple de l'Eau"), + CustomMessage("a feature of the Water Temple", /*german*/"ein Merkmal des Wassertempels", /*french*/"une particularité du Temple de l'Eau"), // /*spanish*/algo particular del Templo del Agua - CustomMessage("something heavy", /*german*/"", /*french*/"une chose pesante") + CustomMessage("something heavy", /*german*/"etwas Schweres", /*french*/"une chose pesante") // /*spanish*/algo de lo más pesado }, { - CustomMessage("sink shoes", /*german*/"", /*french*/"un boulet de fer"), + CustomMessage("sink shoes", /*german*/"Sinkschuhe", /*french*/"un boulet de fer"), // /*spanish*/un calzado de las profundidades - CustomMessage("clank cleats", /*german*/"", /*french*/"une paire de talons bruyants")}); + CustomMessage("clank cleats", /*german*/"klirrende Knacken", /*french*/"une paire de talons bruyants")}); // /*spanish*/unas suelas férreas - hintTextTable[RHT_HOVER_BOOTS] = HintText(CustomMessage("the Hover Boots", /*german*/"", /*french*/"une paire de Bottes des airs"), + hintTextTable[RHT_HOVER_BOOTS] = HintText(CustomMessage("the Hover Boots", /*german*/"die Gleitstiefel", /*french*/"une paire de Bottes des airs"), // /*spanish*/las botas voladoras { - CustomMessage("some boots", /*german*/"", /*french*/"une paire de bottes") + CustomMessage("some boots", /*german*/"ein paar Stiefel", /*french*/"une paire de bottes") // /*spanish*/un par de botas }, { - CustomMessage("butter boots", /*german*/"", /*french*/"une paire de patins de beurre"), + CustomMessage("butter boots", /*german*/"Butterstiefel", /*french*/"une paire de patins de beurre"), // /*spanish*/unas suelas resvaladizas - CustomMessage("sacred slippers", /*german*/"", /*french*/"une paire de pantoufles sacrées"), + CustomMessage("sacred slippers", /*german*/"heilige Pantoffeln", /*french*/"une paire de pantoufles sacrées"), // /*spanish*/unos escurridizos botines - CustomMessage("spacewalkers", /*german*/"", /*french*/"une paire de bottes spatiales")}); + CustomMessage("spacewalkers", /*german*/"Weltraumstiefel", /*french*/"une paire de bottes spatiales")}); // /*spanish*/un calzado antigravitatorio - hintTextTable[RHT_ZELDAS_LETTER] = HintText(CustomMessage("Zelda's Letter", /*german*/"", /*french*/"la Lettre de Zelda"), + hintTextTable[RHT_ZELDAS_LETTER] = HintText(CustomMessage("Zelda's Letter", /*german*/"Zeldas Brief", /*french*/"la Lettre de Zelda"), // /*spanish*/la carta de Zelda {}, { - CustomMessage("an autograph", /*german*/"", /*french*/"un autographe"), + CustomMessage("an autograph", /*german*/"ein Autograph", /*french*/"un autographe"), // /*spanish*/un autógrafo - CustomMessage("royal stationery", /*german*/"", /*french*/"du papier royal"), + CustomMessage("royal stationery", /*german*/"royales Briefpapier", /*french*/"du papier royal"), // /*spanish*/un escrito real - CustomMessage("royal snail mail", /*german*/"", /*french*/"une enveloppe royale")}); + CustomMessage("royal snail mail", /*german*/"ein royaler Umschlag", /*french*/"une enveloppe royale")}); // /*spanish*/correo de la realeza - hintTextTable[RHT_WEIRD_EGG] = HintText(CustomMessage("the Weird Egg", /*german*/"", /*french*/"l'Oeuf Curieux"), + hintTextTable[RHT_WEIRD_EGG] = HintText(CustomMessage("the Weird Egg", /*german*/"ein seltsames Ei", /*french*/"l'Oeuf Curieux"), // /*spanish*/el huevo extraño { - CustomMessage("an egg", /*german*/"", /*french*/"un oeuf") + CustomMessage("an egg", /*german*/"ein Ei", /*french*/"un oeuf") // /*spanish*/un huevo }, { - CustomMessage("a chicken dilemma", /*german*/"", /*french*/"un drôle d'ovale")}); + CustomMessage("a chicken dilemma", /*german*/"ein Hühnerdilemma", /*french*/"un drôle d'ovale")}); // /*spanish*/el dilema de la gallina - hintTextTable[RHT_BOOMERANG] = HintText(CustomMessage("the Boomerang", /*german*/"", /*french*/"le Boomerang"), + hintTextTable[RHT_BOOMERANG] = HintText(CustomMessage("the Boomerang", /*german*/"ein Bumerang", /*french*/"le Boomerang"), // /*spanish*/el bumerán { - CustomMessage("something that can grab things", /*german*/"", /*french*/"une chose qui peut attraper"), + CustomMessage("something that can grab things", /*german*/"etwas, das Dinge greifen kann", /*french*/"une chose qui peut attraper"), // /*spanish*/algo que pueda agarrar cosas - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("a banana", /*german*/"", /*french*/"une banane"), + CustomMessage("a banana", /*german*/"eine Banane", /*french*/"une banane"), // /*spanish*/un plátano - CustomMessage("a stun stick", /*german*/"", /*french*/"un bâton étourdissant"), + CustomMessage("a stun stick", /*german*/"ein paralysierender Stab", /*french*/"un bâton étourdissant"), // /*spanish*/un palo aturdidor - CustomMessage("a yellow angle", /*german*/"", /*french*/"un angle jaune")}); + CustomMessage("a yellow angle", /*german*/"ein gelber Winkel", /*french*/"un angle jaune")}); // /*spanish*/un ángulo amarillo - hintTextTable[RHT_LENS_OF_TRUTH] = HintText(CustomMessage("the Lens of Truth", /*german*/"", /*french*/"le Monocle de Vérité"), + hintTextTable[RHT_LENS_OF_TRUTH] = HintText(CustomMessage("the Lens of Truth", /*german*/"das Auge der Wahrheit", /*french*/"le Monocle de Vérité"), // /*spanish*/la Lupa de la Verdad { - CustomMessage("a secret-finding tool", /*german*/"", /*french*/"un cherche-secrets") + CustomMessage("a secret-finding tool", /*german*/"ein geheimnisfindendes Werkzeug", /*french*/"un cherche-secrets") // /*spanish*/un instrumento para hallar objetos }, { - CustomMessage("a lie detector", /*german*/"", /*french*/"un détecteur de mensonges"), + CustomMessage("a lie detector", /*german*/"ein Lügendetektor", /*french*/"un détecteur de mensonges"), // /*spanish*/el detector de ilusiones - CustomMessage("a ghost tracker", /*german*/"", /*french*/"un trouve-fantôme"), + CustomMessage("a ghost tracker", /*german*/"ein Geisterfinder", /*french*/"un trouve-fantôme"), // /*spanish*/el rastreador paranormal - CustomMessage("true sight", /*german*/"", /*french*/"le troisième œil"), + CustomMessage("true sight", /*german*/"wahre Sicht", /*french*/"le troisième œil"), // /*spanish*/el ojo que todo ve - CustomMessage("a detective's tool", /*german*/"", /*french*/"un trésor Sheikah")}); + CustomMessage("a detective's tool", /*german*/"ein Detektivwerkzeug", /*french*/"un trésor Sheikah")}); // /*spanish*/la revelación verdadera - hintTextTable[RHT_MEGATON_HAMMER] = HintText(CustomMessage("the Megaton Hammer", /*german*/"", /*french*/"la Masse des Titans"), + hintTextTable[RHT_MEGATON_HAMMER] = HintText(CustomMessage("the Megaton Hammer", /*german*/"der Stahlhammer", /*french*/"la Masse des Titans"), // /*spanish*/el martillo Megatón { - CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + CustomMessage("something that can remove boulders", /*german*/"etwas, das Geröll entfernen kann", /*french*/"une chose qui enlève les rochers") // /*spanish*/algo que pueda quitar rocas }, { - CustomMessage("the dragon smasher", /*german*/"", /*french*/"le tueur de dragons"), + CustomMessage("the dragon smasher", /*german*/"ein Drachenschläger", /*french*/"le tueur de dragons"), // /*spanish*/un destructor de dragones - CustomMessage("the metal mallet", /*german*/"", /*french*/"un outil de construction"), + CustomMessage("the metal mallet", /*german*/"ein stählerner Schlägel", /*french*/"un outil de construction"), // /*spanish*/un mazo de metal - CustomMessage("the heavy hitter", /*german*/"", /*french*/"un poids lourd")}); + CustomMessage("the heavy hitter", /*german*/"ein schwerer Schläger", /*french*/"un poids lourd")}); // /*spanish*/un machacador - hintTextTable[RHT_STONE_OF_AGONY] = HintText(CustomMessage("the Stone of Agony", /*german*/"", /*french*/"la Pierre de Souffrance"), + hintTextTable[RHT_STONE_OF_AGONY] = HintText(CustomMessage("the Stone of Agony", /*german*/"der Stein des Wissens", /*french*/"la Pierre de Souffrance"), // /*spanish*/la Piedra de la Agonía { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas"), // /*spanish*/un obsequio de la Casa Skulltula - CustomMessage("a secret-finding tool", /*german*/"", /*french*/"un cherche-secrets") + CustomMessage("a secret-finding tool", /*german*/"ein geheimnisfindendes Werkzeug", /*french*/"un cherche-secrets") // /*spanish*/un instrumento para hallar objetos }, { - CustomMessage("the shake stone", /*german*/"", /*french*/"le fragment vibrant"), + CustomMessage("the shake stone", /*german*/"der Schüttelstein", /*french*/"le fragment vibrant"), // /*spanish*/el fragmento tintineante - CustomMessage("a gray alarm", /*german*/"", /*french*/"une alerte bleue")}); + CustomMessage("a gray alarm", /*german*/"der graue Alarm", /*french*/"une alerte bleue")}); // /*spanish*/una azul alarma - hintTextTable[RHT_DINS_FIRE] = HintText(CustomMessage("Din's Fire", /*german*/"", /*french*/"le Feu de Din"), + hintTextTable[RHT_DINS_FIRE] = HintText(CustomMessage("Din's Fire", /*german*/"Dins Feuerinferno", /*french*/"le Feu de Din"), // /*spanish*/el Fuego de Din { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée") // /*spanish*/el poder de una Gran Hada }, { - CustomMessage("an inferno", /*german*/"", /*french*/"un brasier"), + CustomMessage("an inferno", /*german*/"ein Inferno", /*french*/"un brasier"), // /*spanish*/un incendio - CustomMessage("a heat wave", /*german*/"", /*french*/"une vague de chaleur"), + CustomMessage("a heat wave", /*german*/"eine Hitzewelle", /*french*/"une vague de chaleur"), // /*spanish*/una onda de calor - CustomMessage("a red ball", /*german*/"", /*french*/"une explosion de flammes")}); + CustomMessage("a red ball", /*german*/"ein roter Ball", /*french*/"une explosion de flammes")}); // /*spanish*/una roja esfera - hintTextTable[RHT_FARORES_WIND] = HintText(CustomMessage("Farore's Wind", /*german*/"", /*french*/"le Vent de Farore"), + hintTextTable[RHT_FARORES_WIND] = HintText(CustomMessage("Farore's Wind", /*german*/"Farores Donnersturm", /*french*/"le Vent de Farore"), // /*spanish*/el Viento de Farore { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée") // /*spanish*/el poder de una Gran Hada }, { - CustomMessage("teleportation", /*german*/"", /*french*/"la téléportation"), + CustomMessage("teleportation", /*german*/"ein Teleportierer", /*french*/"la téléportation"), // /*spanish*/un teletransportador - CustomMessage("a relocation rune", /*german*/"", /*french*/"une rune de relocation"), + CustomMessage("a relocation rune", /*german*/"eine Umzugsrune", /*french*/"une rune de relocation"), // /*spanish*/una runa de transporte - CustomMessage("a green ball", /*german*/"", /*french*/"une boule verte")}); + CustomMessage("a green ball", /*german*/"ein grüner Ball", /*french*/"une boule verte")}); // /*spanish*/una verde esfera - hintTextTable[RHT_NAYRUS_LOVE] = HintText(CustomMessage("Nayru's Love", /*german*/"", /*french*/"l'Amour de Nayru"), + hintTextTable[RHT_NAYRUS_LOVE] = HintText(CustomMessage("Nayru's Love", /*german*/"Nayrus Umarmung", /*french*/"l'Amour de Nayru"), // /*spanish*/el Amor de Nayru { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée") // /*spanish*/el poder de una Gran Hada }, { - CustomMessage("a safe space", /*german*/"", /*french*/"une bulle de cristal"), + CustomMessage("a safe space", /*german*/"ein sicherer Raum", /*french*/"une bulle de cristal"), // /*spanish*/una seguridad temporal - CustomMessage("an impregnable aura", /*german*/"", /*french*/"un aura impénétrable"), + CustomMessage("an impregnable aura", /*german*/"eine undurchdringliche Aura", /*french*/"un aura impénétrable"), // /*spanish*/un aura impenetrable - CustomMessage("a blue barrier", /*german*/"", /*french*/"une toison bleu")}); + CustomMessage("a blue barrier", /*german*/"eine blaue Barriere", /*french*/"une toison bleu")}); // /*spanish*/una barrera azul - hintTextTable[RHT_FIRE_ARROWS] = HintText(CustomMessage("the Fire Arrows", /*german*/"", /*french*/"les Flèches de Feu"), + hintTextTable[RHT_FIRE_ARROWS] = HintText(CustomMessage("the Fire Arrows", /*german*/"die Feuerpfeile", /*french*/"les Flèches de Feu"), // /*spanish*/la flecha de fuego { - CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique") + CustomMessage("a magic arrow", /*german*/"ein magischer Pfeil", /*french*/"une flèche magique") // /*spanish*/una flecha mágica }, { - CustomMessage("the furnace firearm", /*german*/"", /*french*/"une fusée solaire"), + CustomMessage("the furnace firearm", /*german*/"die Ofenwaffe", /*french*/"une fusée solaire"), // /*spanish*/el ardiente aguijón - CustomMessage("the burning bolts", /*german*/"", /*french*/"un obus enflammé"), + CustomMessage("the burning bolts", /*german*/"die Brennstifte", /*french*/"un obus enflammé"), // /*spanish*/las puntas ígneas - CustomMessage("a magma missile", /*german*/"", /*french*/"un missile volcanique")}); + CustomMessage("a magma missile", /*german*/"eine vulkanische Rakete", /*french*/"un missile volcanique")}); // /*spanish*/el misil abrasador - hintTextTable[RHT_ICE_ARROWS] = HintText(CustomMessage("the Ice Arrows", /*german*/"", /*french*/"les Flèches de Glace"), + hintTextTable[RHT_ICE_ARROWS] = HintText(CustomMessage("the Ice Arrows", /*german*/"die Eispfeile", /*french*/"les Flèches de Glace"), // /*spanish*/la flecha de hielo { - CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique"), + CustomMessage("a magic arrow", /*german*/"ein magischer Pfeil", /*french*/"une flèche magique"), // /*spanish*/una flecha mágica - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("the refrigerator rocket", /*german*/"", /*french*/"un missile pétrifiant"), + CustomMessage("the refrigerator rocket", /*german*/"die Kühlschrankrakete", /*french*/"un missile pétrifiant"), // /*spanish*/el misil congelador - CustomMessage("the frostbite bolts", /*german*/"", /*french*/"un froid mordant"), + CustomMessage("the frostbite bolts", /*german*/"die Froststifte", /*french*/"un froid mordant"), // /*spanish*/las puntas gélidas - CustomMessage("an iceberg maker", /*german*/"", /*french*/"une aiguille glaciale")}); + CustomMessage("an iceberg maker", /*german*/"ein Eisbergmacher", /*french*/"une aiguille glaciale")}); // /*spanish*/el control de escarcha - hintTextTable[RHT_LIGHT_ARROWS] = HintText(CustomMessage("the Light Arrows", /*german*/"", /*french*/"les Flèches de Lumière"), + hintTextTable[RHT_LIGHT_ARROWS] = HintText(CustomMessage("the Light Arrows", /*german*/"die Lichtpfeile", /*french*/"les Flèches de Lumière"), // /*spanish*/la flecha de luz { - CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique") + CustomMessage("a magic arrow", /*german*/"ein magischer Pfeil", /*french*/"une flèche magique") // /*spanish*/una flecha mágica }, { - CustomMessage("the shining shot", /*german*/"", /*french*/"l'arme brillante"), + CustomMessage("the shining shot", /*german*/"der strahlende Schuss", /*french*/"l'arme brillante"), // /*spanish*/el haz de luz - CustomMessage("the luminous launcher", /*german*/"", /*french*/"un jet de lumière"), + CustomMessage("the luminous launcher", /*german*/"der leuchtende Werfer", /*french*/"un jet de lumière"), // /*spanish*/el disparo luminoso - CustomMessage("Ganondorf's bane", /*german*/"", /*french*/"le fléau de Ganondorf"), + CustomMessage("Ganondorf's bane", /*german*/"Ganondorfs Verderben", /*french*/"le fléau de Ganondorf"), // /*spanish*/la perdición de Ganondorf - CustomMessage("the lighting bolts", /*german*/"", /*french*/"l'éclair sacré")}); + CustomMessage("the lighting bolts", /*german*/"die Lichtstifte", /*french*/"l'éclair sacré")}); // /*spanish*/las puntas resplandecientes - hintTextTable[RHT_GERUDO_MEMBERSHIP_CARD] = HintText(CustomMessage("the Gerudo Membership Card", /*german*/"", /*french*/"la Carte Gerudo"), + hintTextTable[RHT_GERUDO_MEMBERSHIP_CARD] = HintText(CustomMessage("the Gerudo Membership Card", /*german*/"der Gerudo-Pass", /*french*/"la Carte Gerudo"), // /*spanish*/el pase de socio gerudo { - CustomMessage("a token of recognition", /*german*/"", /*french*/"une preuve de reconnaissance") + CustomMessage("a token of recognition", /*german*/"ein Zeichen der Anerkennung", /*french*/"une preuve de reconnaissance") // /*spanish*/una prueba de reconocimiento }, { - CustomMessage("a girl club membership", /*german*/"", /*french*/"une carte de membre"), + CustomMessage("a girl club membership", /*german*/"eine Mitgliedskarte", /*french*/"une carte de membre"), // /*spanish*/una fémina membresía - CustomMessage("a desert tribe's pass", /*german*/"", /*french*/"un laissez-passer")}); + CustomMessage("a desert tribe's pass", /*german*/"ein Pass eines Wüstenstammes", /*french*/"un laissez-passer")}); // /*spanish*/el vale del desierto - hintTextTable[RHT_MAGIC_BEAN] = HintText(CustomMessage("a Magic Bean", /*german*/"", /*french*/"un Haricot Magique"), + hintTextTable[RHT_MAGIC_BEAN] = HintText(CustomMessage("a Magic Bean", /*german*/"eine Wundererbse", /*french*/"un Haricot Magique"), // /*spanish*/una judía mágica { - CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + CustomMessage("something sometimes buried", /*german*/"etwas, das manchmal begraben ist", /*french*/"une chose parfois enterrée") // /*spanish*/algo a veces enterrado }, { - CustomMessage("a wizardly legume", /*german*/"", /*french*/"un légume ensorcelé")}); + CustomMessage("a wizardly legume", /*german*/"eine zauberhafte Hülse", /*french*/"un légume ensorcelé")}); // /*spanish*/una legumbre hechizada - hintTextTable[RHT_MAGIC_BEAN_PACK] = HintText(CustomMessage("Magic Beans", /*german*/"", /*french*/"un Paquet de Haricots Magiques"), + hintTextTable[RHT_MAGIC_BEAN_PACK] = HintText(CustomMessage("Magic Beans", /*german*/"Wundererbsen", /*french*/"un Paquet de Haricots Magiques"), // /*spanish*/unas judías mágicas { - CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + CustomMessage("something sometimes buried", /*german*/"etwas, das manchmal begraben ist", /*french*/"une chose parfois enterrée") // /*spanish*/algo a veces enterrado }, { - CustomMessage("wizardly legumes", /*german*/"", /*french*/"un paquet de légumes ensorcelés")}); + CustomMessage("wizardly legumes", /*german*/"zauberhafte Hülsen", /*french*/"un paquet de légumes ensorcelés")}); // /*spanish*/unas legumbres hechizadas - hintTextTable[RHT_DOUBLE_DEFENSE] = HintText(CustomMessage("Double Defense", /*german*/"", /*french*/"la Double Défence"), + hintTextTable[RHT_DOUBLE_DEFENSE] = HintText(CustomMessage("Double Defense", /*german*/"Doppelte Verteidigung", /*french*/"la Double Défence"), // /*spanish*/la doble defensa { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée"), + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée"), // /*spanish*/el poder de una Gran Hada - CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + CustomMessage("something heart-shaped", /*german*/"etwas Herzförmiges", /*french*/"une chose en forme de coeur") // /*spanish*/algo con forma de corazón }, { - CustomMessage("a white outline", /*german*/"", /*french*/"un rebord blanc"), + CustomMessage("a white outline", /*german*/"ein weißes Profil", /*french*/"un rebord blanc"), // /*spanish*/un contorno blanco - CustomMessage("damage decrease", /*german*/"", /*french*/"une protection supplémentaire"), + CustomMessage("damage decrease", /*german*/"Schadensverringerung", /*french*/"une protection supplémentaire"), // /*spanish*/una reducción de daño - CustomMessage("strengthened love", /*german*/"", /*french*/"un amour coriace")}); + CustomMessage("strengthened love", /*german*/"gestärkte Liebe", /*french*/"un amour coriace")}); // /*spanish*/un amor fortalecido - hintTextTable[RHT_GOLD_SKULLTULA_TOKEN] = HintText(CustomMessage("a Gold Skulltula Token", /*german*/"", /*french*/"un Symbole de Skulltula d'or"), + hintTextTable[RHT_GOLD_SKULLTULA_TOKEN] = HintText(CustomMessage("a Gold Skulltula Token", /*german*/"ein goldenes Skulltula-Symbol", /*french*/"un Symbole de Skulltula d'or"), // /*spanish*/un símbolo de skulltula dorada { - CustomMessage("a token of recognition", /*german*/"", /*french*/"une preuve de reconnaissance"), + CustomMessage("a token of recognition", /*german*/"ein Zeichen der Anerkennung", /*french*/"une preuve de reconnaissance"), // /*spanish*/una prueba de reconocimiento - CustomMessage("something sometimes buried", /*german*/"", /*french*/"une chose parfois enterrée") + CustomMessage("something sometimes buried", /*german*/"etwas, das manchmal begraben ist", /*french*/"une chose parfois enterrée") // /*spanish*/algo a veces enterrado }, { - CustomMessage("proof of destruction", /*german*/"", /*french*/"un certificat d'élimination"), + CustomMessage("proof of destruction", /*german*/"Nachweis der Zerstörung", /*french*/"un certificat d'élimination"), // /*spanish*/una prueba de la destrucción - CustomMessage("an arachnid chip", /*german*/"", /*french*/"un symbole cranien"), + CustomMessage("an arachnid chip", /*german*/"ein spinnenartiges Symbol", /*french*/"un symbole cranien"), // /*spanish*/una figura arácnida - CustomMessage("spider remains", /*german*/"", /*french*/"une dépouille dorée"), + CustomMessage("spider remains", /*german*/"Spinnenüberreste", /*french*/"une dépouille dorée"), // /*spanish*/unos restos dorados - CustomMessage("one percent of a curse", /*german*/"", /*french*/"un centième de malédiction")}); + CustomMessage("one percent of a curse", /*german*/"ein Prozent eines Fluchs", /*french*/"un centième de malédiction")}); // /*spanish*/una centésima de una maldición - hintTextTable[RHT_POCKET_EGG] = HintText(CustomMessage("the Pocket Egg", /*german*/"", /*french*/"l'Oeuf de Poche"), + hintTextTable[RHT_POCKET_EGG] = HintText(CustomMessage("the Pocket Egg", /*german*/"das Ei", /*french*/"l'Oeuf de Poche"), // /*spanish*/el huevo de bolsillo { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges"), + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges"), // /*spanish*/un objeto de una misión secundaria - CustomMessage("an egg", /*german*/"", /*french*/"un oeuf") + CustomMessage("an egg", /*german*/"ein Ei", /*french*/"un oeuf") // /*spanish*/un huevo }, { - CustomMessage("a Cucco container", /*german*/"", /*french*/"un réservoir à Cocotte"), + CustomMessage("a Cucco container", /*german*/"ein Hühnerbehälter", /*french*/"un réservoir à Cocotte"), // /*spanish*/cuco contenido - CustomMessage("a Cucco, eventually", /*german*/"", /*french*/"un poussin éventuel"), + CustomMessage("a Cucco, eventually", /*german*/"schlussendlich ein Huhn", /*french*/"un poussin éventuel"), // /*spanish*/un futuro cuco - CustomMessage("a fowl youth", /*german*/"", /*french*/"une omelette crue")}); + CustomMessage("a fowl youth", /*german*/"ein junges Geflügel", /*french*/"une omelette crue")}); // /*spanish*/una dulce juventud - hintTextTable[RHT_POCKET_CUCCO] = HintText(CustomMessage("the Pocket Cucco", /*german*/"", /*french*/"la Cocotte de Poche"), + hintTextTable[RHT_POCKET_CUCCO] = HintText(CustomMessage("the Pocket Cucco", /*german*/"Kiki", /*french*/"la Cocotte de Poche"), // /*spanish*/el cuco de bolsillo { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a little clucker", /*german*/"", /*french*/"un petit glousseur")}); + CustomMessage("a little clucker", /*german*/"ein kleiner Gackerer", /*french*/"un petit glousseur")}); // /*spanish*/un pollito chiquito - hintTextTable[RHT_COJIRO] = HintText(CustomMessage("Cojiro", /*german*/"", /*french*/"le p'tit poulet"), + hintTextTable[RHT_COJIRO] = HintText(CustomMessage("Cojiro", /*german*/"Henni", /*french*/"le p'tit poulet"), // /*spanish*/a Cojiro { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a cerulean capon", /*german*/"", /*french*/"un paon azur")}); + CustomMessage("a cerulean capon", /*german*/"ein coelinblaues Kapaun", /*french*/"un paon azur")}); // /*spanish*/un cerúleo capón - hintTextTable[RHT_ODD_MUSHROOM] = HintText(CustomMessage("an Odd Mushroom", /*german*/"", /*french*/"un Champignon Suspect"), + hintTextTable[RHT_ODD_MUSHROOM] = HintText(CustomMessage("an Odd Mushroom", /*german*/"ein Schimmelpilz", /*french*/"un Champignon Suspect"), // /*spanish*/un champiñón extraño { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a powder ingredient", /*german*/"", /*french*/"un ingrédient à poudre")}); + CustomMessage("a powder ingredient", /*german*/"eine Puderingredienz", /*french*/"un ingrédient à poudre")}); // /*spanish*/un oloroso ingrediente - hintTextTable[RHT_ODD_POTION] = HintText(CustomMessage("an Odd Potion", /*german*/"", /*french*/"une Mixture Suspecte"), + hintTextTable[RHT_ODD_POTION] = HintText(CustomMessage("an Odd Potion", /*german*/"ein Modertrank", /*french*/"une Mixture Suspecte"), // /*spanish*/una medicina rara { - CustomMessage("something that contains medicine", /*german*/"", /*french*/"une chose médicamenteuse"), + CustomMessage("something that contains medicine", /*german*/"etwas, das Medizin enthält", /*french*/"une chose médicamenteuse"), // /*spanish*/algo que contenga medicina - CustomMessage("something with a strange smell", /*german*/"", /*french*/"une chose qui sent bizarre"), + CustomMessage("something with a strange smell", /*german*/"etwas, das streng riecht", /*french*/"une chose qui sent bizarre"), // /*spanish*/algo con un olor extraño - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("Granny's goodies", /*german*/"", /*french*/"la confiserie de mamie")}); + CustomMessage("Granny's goodies", /*german*/"Omas Zuckerwerk", /*french*/"la confiserie de mamie")}); // /*spanish*/la especialidad de la abuela - hintTextTable[RHT_POACHERS_SAW] = HintText(CustomMessage("the Poacher's Saw", /*german*/"", /*french*/"la Scie du Chasseur"), + hintTextTable[RHT_POACHERS_SAW] = HintText(CustomMessage("the Poacher's Saw", /*german*/"eine Säge", /*french*/"la Scie du Chasseur"), // /*spanish*/la sierra del furtivo { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a tree killer", /*german*/"", /*french*/"un coupeur d'arbres")}); + CustomMessage("a tree killer", /*german*/"ein Baumtöter", /*french*/"un coupeur d'arbres")}); // /*spanish*/un destructor de árboles - hintTextTable[RHT_BROKEN_SWORD] = HintText(CustomMessage("the Broken Goron's Sword", /*german*/"", /*french*/"l'Épée Brisée de Goron"), + hintTextTable[RHT_BROKEN_SWORD] = HintText(CustomMessage("the Broken Goron's Sword", /*german*/"das zerbrochene Goronen-Schwert", /*french*/"l'Épée Brisée de Goron"), // /*spanish*/la espada goron rota { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges"), + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges"), // /*spanish*/un objeto de una misión secundaria - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("a shattered slicer", /*german*/"", /*french*/"une arme cassée")}); + CustomMessage("a shattered slicer", /*german*/"ein zersplitterter Schneider", /*french*/"une arme cassée")}); // /*spanish*/una rebanadora rota - hintTextTable[RHT_PRESCRIPTION] = HintText(CustomMessage("the Prescription", /*german*/"", /*french*/"une Ordonnance"), + hintTextTable[RHT_PRESCRIPTION] = HintText(CustomMessage("the Prescription", /*german*/"ein Rezept", /*french*/"une Ordonnance"), // /*spanish*/la receta { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a pill pamphlet", /*german*/"", /*french*/"un document urgent"), + CustomMessage("a pill pamphlet", /*german*/"ein Pillenpamphlet", /*french*/"un document urgent"), // /*spanish*/un instructivo medicinal - CustomMessage("a doctor's note", /*german*/"", /*french*/"un papier médical")}); + CustomMessage("a doctor's note", /*german*/"eine Notiz eines Doktors", /*french*/"un papier médical")}); // /*spanish*/unas notas del doctor - hintTextTable[RHT_EYEBALL_FROG] = HintText(CustomMessage("the Eyeball Frog", /*german*/"", /*french*/"le Crapaud-qui-louche"), + hintTextTable[RHT_EYEBALL_FROG] = HintText(CustomMessage("the Eyeball Frog", /*german*/"der Glotzfrosch", /*french*/"le Crapaud-qui-louche"), // /*spanish*/la rana de ojos saltones { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a perceiving polliwog", /*german*/"", /*french*/"un amphibien")}); + CustomMessage("a perceiving polliwog", /*german*/"eine wahrnehmende Kaulquappe", /*french*/"un amphibien")}); // /*spanish*/un variopinto batracio - hintTextTable[RHT_EYEDROPS] = HintText(CustomMessage("the Eyedrops", /*german*/"", /*french*/"une phiole de Super-Gouttes"), + hintTextTable[RHT_EYEDROPS] = HintText(CustomMessage("the Eyedrops", /*german*/"die Augentropfen", /*french*/"une phiole de Super-Gouttes"), // /*spanish*/las supergotas oculares { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a vision vial", /*german*/"", /*french*/"une solution oculaire")}); + CustomMessage("a vision vial", /*german*/"eine Sichtphiole", /*french*/"une solution oculaire")}); // /*spanish*/un remedio para la vista - hintTextTable[RHT_CLAIM_CHECK] = HintText(CustomMessage("the Claim Check", /*german*/"", /*french*/"un Certificat"), + hintTextTable[RHT_CLAIM_CHECK] = HintText(CustomMessage("the Claim Check", /*german*/"ein Zertifikat", /*french*/"un Certificat"), // /*spanish*/el recibo { - CustomMessage("a trade quest item", /*german*/"", /*french*/"un objet de quête d'échanges") + CustomMessage("a trade quest item", /*german*/"ein Gegenstand einer Handelsmission", /*french*/"un objet de quête d'échanges") // /*spanish*/un objeto de una misión secundaria }, { - CustomMessage("a three day wait", /*german*/"", /*french*/"un rendez-vous dans trois jours")}); + CustomMessage("a three day wait", /*german*/"eine dreitägige Erwartung", /*french*/"un rendez-vous dans trois jours")}); // /*spanish*/unos tres días de espera - hintTextTable[RHT_PROGRESSIVE_HOOKSHOT] = HintText(CustomMessage("a Hookshot", /*german*/"", /*french*/"un Grappin"), + hintTextTable[RHT_PROGRESSIVE_HOOKSHOT] = HintText(CustomMessage("a Hookshot", /*german*/"ein Enterhaken", /*french*/"un Grappin"), // /*spanish*/un gancho { - CustomMessage("something that can grab things", /*german*/"", /*french*/"une chose qui peut attraper"), + CustomMessage("something that can grab things", /*german*/"etwas, das Dinge greifen kann", /*french*/"une chose qui peut attraper"), // /*spanish*/algo que pueda agarrar cosas - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("Dampé's keepsake", /*german*/"", /*french*/"l'héritage d'Igor"), + CustomMessage("Dampé's keepsake", /*german*/"Dampés Andenken", /*french*/"l'héritage d'Igor"), // /*spanish*/un recuerdo de Dampé - CustomMessage("the Grapple Beam", /*german*/"", /*french*/"le rayon grippeur"), + CustomMessage("the Grapple Beam", /*german*/"der Greifstrahl", /*french*/"le rayon grippeur"), // /*spanish*/una garra metálica - CustomMessage("the RHT_BOING! chain", /*german*/"", /*french*/"la chaîne de RHT_BOING!")}); + CustomMessage("the RHT_BOING! chain", /*german*/"die Kette des RHT_BOING!", /*french*/"la chaîne de RHT_BOING!")}); // /*spanish*/una cadena retráctil - hintTextTable[RHT_PROGRESSIVE_STRENGTH] = HintText(CustomMessage("a Strength Upgrade", /*german*/"", /*french*/"une Amélioration de Force"), + hintTextTable[RHT_PROGRESSIVE_STRENGTH] = HintText(CustomMessage("a Strength Upgrade", /*german*/"eine Stärkeverbesserung", /*french*/"une Amélioration de Force"), // /*spanish*/un aumento de fuerza { - CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + CustomMessage("something that can remove boulders", /*german*/"etwas, das Geröll entfernen kann", /*french*/"une chose qui enlève les rochers") // /*spanish*/algo que pueda quitar rocas }, { - CustomMessage("power gloves", /*german*/"", /*french*/"une paire de gants de travail"), + CustomMessage("power gloves", /*german*/"Krafthandschuhe", /*french*/"une paire de gants de travail"), // /*spanish*/unos poderosos guanteletes - CustomMessage("metal mittens", /*german*/"", /*french*/"une paire de mitaines"), + CustomMessage("metal mittens", /*german*/"Metallfäustlinge", /*french*/"une paire de mitaines"), // /*spanish*/unas manoplas metálicas - CustomMessage("the heavy lifty", /*german*/"", /*french*/"la puissance de dix hommes")}); + CustomMessage("the heavy lifty", /*german*/"der Schwerlastheber", /*french*/"la puissance de dix hommes")}); // /*spanish*/un levantamiento pesado - hintTextTable[RHT_PROGRESSIVE_BOMB_BAG] = HintText(CustomMessage("a Bomb Bag", /*german*/"", /*french*/"un Sac de Bombes"), + hintTextTable[RHT_PROGRESSIVE_BOMB_BAG] = HintText(CustomMessage("a Bomb Bag", /*german*/"ein Bombenbeutel", /*french*/"un Sac de Bombes"), // /*spanish*/un saco de bombas { - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs"), + CustomMessage("explosives", /*german*/"ein Explosivpaket", /*french*/"un paquet d'explosifs"), // /*spanish*/un montón de explosivos - CustomMessage("something that can remove boulders", /*german*/"", /*french*/"une chose qui enlève les rochers") + CustomMessage("something that can remove boulders", /*german*/"etwas, das Geröll entfernen kann", /*french*/"une chose qui enlève les rochers") // /*spanish*/algo que pueda quitar rocas }, { - CustomMessage("an explosive container", /*german*/"", /*french*/"un porte-grenade"), + CustomMessage("an explosive container", /*german*/"ein Explosivbehälter", /*french*/"un porte-grenade"), // /*spanish*/un recipiente explosivo - CustomMessage("a blast bag", /*german*/"", /*french*/"un estomac de Dodongo")}); + CustomMessage("a blast bag", /*german*/"ein Dodongomagen", /*french*/"un estomac de Dodongo")}); // /*spanish*/un zurrón de estallidos - hintTextTable[RHT_PROGRESSIVE_BOW] = HintText(CustomMessage("a Bow", /*german*/"", /*french*/"l'Arc des Fées"), + hintTextTable[RHT_PROGRESSIVE_BOW] = HintText(CustomMessage("a Fairy Bow", /*german*/"ein Feen-Bogen", /*french*/"l'Arc des Fées"), // /*spanish*/un arco de las hadas { - CustomMessage("a projectile shooter", /*german*/"", /*french*/"un tire-projectile") + CustomMessage("a projectile shooter", /*german*/"ein Projektilwerfer", /*french*/"un tire-projectile") // /*spanish*/un arma de proyectil }, { - CustomMessage("an archery enabler", /*german*/"", /*french*/"un facilitateur de tir"), + CustomMessage("an archery enabler", /*german*/"ein Bogenschussermöglicher", /*french*/"un facilitateur de tir"), // /*spanish*/un tiro al blanco - CustomMessage("a danger dart launcher", /*german*/"", /*french*/"un tire-fléchette")}); + CustomMessage("a danger dart launcher", /*german*/"ein Pfeilwerfer", /*french*/"un tire-fléchette")}); // /*spanish*/un peligroso lanzadardos - hintTextTable[RHT_PROGRESSIVE_SLINGSHOT] = HintText(CustomMessage("a Slingshot", /*german*/"", /*french*/"un Lance-Pierre"), + hintTextTable[RHT_PROGRESSIVE_SLINGSHOT] = HintText(CustomMessage("a Slingshot", /*german*/"eine Schleuder", /*french*/"un Lance-Pierre"), // /*spanish*/una resortera de las hadas { - CustomMessage("a projectile shooter", /*german*/"", /*french*/"un tire-projectile") + CustomMessage("a projectile shooter", /*german*/"ein Projektilwerfer", /*french*/"un tire-projectile") // /*spanish*/un arma de proyectil }, { - CustomMessage("a seed shooter", /*german*/"", /*french*/"un lance-noix"), + CustomMessage("a seed shooter", /*german*/"ein Nusswerfer", /*french*/"un lance-noix"), // /*spanish*/un lanzasemillas - CustomMessage("a rubberband", /*german*/"", /*french*/"un élastique"), + CustomMessage("a rubberband", /*german*/"ein Gummiband", /*french*/"un élastique"), // /*spanish*/un tirachinas - CustomMessage("a child's catapult", /*german*/"", /*french*/"un jouet d'enfant")}); + CustomMessage("a child's catapult", /*german*/"ein Kinderkatapult", /*french*/"un jouet d'enfant")}); // /*spanish*/una catapulta infantil - hintTextTable[RHT_PROGRESSIVE_WALLET] = HintText(CustomMessage("a Wallet", /*german*/"", /*french*/"une Bourse"), + hintTextTable[RHT_PROGRESSIVE_WALLET] = HintText(CustomMessage("a Wallet", /*german*/"eine Börse", /*french*/"une Bourse"), // /*spanish*/una bolsa de rupias { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas") + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas") // /*spanish*/un obsequio de la Casa Skulltula }, { - CustomMessage("a mo' money holder", /*german*/"", /*french*/"un sac à sous"), + CustomMessage("a mo' money holder", /*german*/"ein Geldhalter", /*french*/"un sac à sous"), // /*spanish*/una cartera de dinero - CustomMessage("a gem purse", /*german*/"", /*french*/"une sacoche"), + CustomMessage("a gem purse", /*german*/"ein Edelsteinportemonnaie", /*french*/"une sacoche"), // /*spanish*/un zurrón de gemas - CustomMessage("a portable bank", /*german*/"", /*french*/"une petite banque")}); + CustomMessage("a portable bank", /*german*/"eine tragbare Bank", /*french*/"une petite banque")}); // /*spanish*/un banco portable - hintTextTable[RHT_PROGRESSIVE_SCALE] = HintText(CustomMessage("a Zora Scale", /*german*/"", /*french*/"une Écaille Zora"), + hintTextTable[RHT_PROGRESSIVE_SCALE] = HintText(CustomMessage("a Zora Scale", /*german*/"eine Zora-Schuppe", /*french*/"une Écaille Zora"), // /*spanish*/una escama Zora { - CustomMessage("a diving tool", /*german*/"", /*french*/"un outil de plongée") + CustomMessage("a diving tool", /*german*/"ein Tauchwerkzeug", /*french*/"un outil de plongée") // /*spanish*/un instrumento de buceo }, { - CustomMessage("a deeper dive", /*german*/"", /*french*/"une bulle de plongée"), + CustomMessage("a deeper dive", /*german*/"eine Tauchblase", /*french*/"une bulle de plongée"), // /*spanish*/un profundo buceo - CustomMessage("a piece of Zora", /*german*/"", /*french*/"un morceau de Zora")}); + CustomMessage("a piece of Zora", /*german*/"ein Zora-Fragment", /*french*/"un morceau de Zora")}); // /*spanish*/un fragmento de Zora - hintTextTable[RHT_PROGRESSIVE_NUT_UPGRADE] = HintText(CustomMessage("Deku Nut Capacity", /*german*/"", /*french*/"une Augmentation de Noix Mojo"), + hintTextTable[RHT_PROGRESSIVE_NUT_UPGRADE] = HintText(CustomMessage("Deku Nut Capacity", /*german*/"Deku-Nuß-Kapazität", /*french*/"une Augmentation de Noix Mojo"), // /*spanish*/un aumento de nueces deku { - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + CustomMessage("some Deku munitions", /*german*/"etwas Deku-Munition", /*french*/"un paquet de munitions Mojo"), // /*spanish*/un montón de municiones Deku - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("more nuts", /*german*/"", /*french*/"ecnore plus de noix"), + CustomMessage("more nuts", /*german*/"mehr Nüsse", /*french*/"encore plus de noix"), // /*spanish*/más semillas de nogal - CustomMessage("flashbang storage", /*german*/"", /*french*/"un sac à noix")}); + CustomMessage("flashbang storage", /*german*/"Blendgranatenvorrat", /*french*/"un sac à noix")}); // /*spanish*/más frutos aturdidores - hintTextTable[RHT_PROGRESSIVE_STICK_UPGRADE] = HintText(CustomMessage("Deku Stick Capacity", /*german*/"", /*french*/"une augmentation de bâtons Mojo"), + hintTextTable[RHT_PROGRESSIVE_STICK_UPGRADE] = HintText(CustomMessage("Deku Stick Capacity", /*german*/"Deku-Stab-Kapazität", /*french*/"une augmentation de bâtons Mojo"), // /*spanish*/un aumento de palos deku { - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + CustomMessage("some Deku munitions", /*german*/"etwas Deku-Munition", /*french*/"un paquet de munitions Mojo") // /*spanish*/un montón de municiones Deku }, { - CustomMessage("a lumber rack", /*german*/"", /*french*/"un paquet de bois"), + CustomMessage("lumber racks", /*german*/"Holzgestelle", /*french*/"un paquet de bois"), // /*spanish*/más bastones - CustomMessage("more flammable twigs", /*german*/"", /*french*/"beaucoup de branches")}); + CustomMessage("more flammable twigs", /*german*/"mehr entflammbare Zweige", /*french*/"beaucoup de branches")}); // /*spanish*/más varas - hintTextTable[RHT_PROGRESSIVE_MAGIC_METER] = HintText(CustomMessage("a Magic Meter", /*german*/"", /*french*/"une Jauge de Magie"), + hintTextTable[RHT_PROGRESSIVE_MAGIC_METER] = HintText(CustomMessage("a Magic Meter", /*german*/"ein Magieabmaß", /*french*/"une Jauge de Magie"), // /*spanish*/un aumento de poder mágico { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée") + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée") // /*spanish*/el poder de una Gran Hada }, { - CustomMessage("mystic training", /*german*/"", /*french*/"un potentiel magique"), + CustomMessage("mystic training", /*german*/"mystisches Training", /*french*/"un potentiel magique"), // /*spanish*/una maestría mística - CustomMessage("pixie dust", /*german*/"", /*french*/"de la poudre de fée"), + CustomMessage("pixie dust", /*german*/"Feenstaub", /*french*/"de la poudre de fée"), // /*spanish*/un polvo de hada - CustomMessage("a green rectangle", /*german*/"", /*french*/"un rectangle vert")}); + CustomMessage("a green rectangle", /*german*/"ein grünes Rechteck", /*french*/"un rectangle vert")}); // /*spanish*/una verduzca barra - hintTextTable[RHT_PROGRESSIVE_OCARINA] = HintText(CustomMessage("an Ocarina", /*german*/"", /*french*/"un ocarina"), + hintTextTable[RHT_PROGRESSIVE_OCARINA] = HintText(CustomMessage("an Ocarina", /*german*/"eine Okarina", /*french*/"un ocarina"), // /*spanish*/una ocarina { - CustomMessage("something given by Saria", /*german*/"", /*french*/"un cadeau de Saria"), + CustomMessage("something given by Saria", /*german*/"ein Geschenk von Salia", /*french*/"un cadeau de Saria"), // /*spanish*/un obsequio de Saria - CustomMessage("something kept by the royal family", /*german*/"", /*french*/"une chose qui paralyse") + CustomMessage("something kept by the royal family", /*german*/"etwas, das von der royalen Familie bewahrt wird", /*french*/"une chose qui paralyse") // /*spanish*/algo guardado por la familia real }, { - CustomMessage("a flute", /*german*/"", /*french*/"un bec musical"), + CustomMessage("a flute", /*german*/"eine Flöte", /*french*/"un bec musical"), // /*spanish*/un utensilio musical - CustomMessage("a music maker", /*german*/"", /*french*/"un porteur de chansons")}); + CustomMessage("a music maker", /*german*/"ein Musikmacher", /*french*/"un porteur de chansons")}); // /*spanish*/un instrumento - hintTextTable[RHT_PROGRESSIVE_BOMBCHUS] = HintText(CustomMessage("Bombchus", /*german*/"", /*french*/"un paquet de Missiles"), + hintTextTable[RHT_PROGRESSIVE_BOMBCHUS] = HintText(CustomMessage("Bombchus", /*german*/"Krabbelminen", /*french*/"un paquet de Missiles"), // /*spanish*/unos bombchus { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas"), // /*spanish*/un obsequio de la Casa Skulltula - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"ein Explosivpaket", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("mice bombs", /*german*/"", /*french*/"un adorable explosif"), + CustomMessage("mice bombs", /*german*/"Mäusebomben", /*french*/"un adorable explosif"), // /*spanish*/unas bombas roedoras - CustomMessage("proximity mice", /*german*/"", /*french*/"une mine anti-rongeur"), + CustomMessage("proximity mice", /*german*/"Näherungsmäuse", /*french*/"une mine anti-rongeur"), // /*spanish*/unos explosivos ratoncitos - CustomMessage("wall crawlers", /*german*/"", /*french*/"un rapide grimpeur"), + CustomMessage("wall crawlers", /*german*/"Wandkrabbler", /*french*/"un rapide grimpeur"), // /*spanish*/unos trepaparedes - CustomMessage("trail blazers", /*german*/"", /*french*/"un zigzag éclatant")}); + CustomMessage("trail blazers", /*german*/"Vorreiter", /*french*/"un zigzag éclatant")}); // /*spanish*/unas ratas propulsadas - hintTextTable[RHT_PROGRESSIVE_GORONSWORD] = HintText(CustomMessage("a Goron Sword", /*german*/"", /*french*/"une épée Goron"), + hintTextTable[RHT_PROGRESSIVE_GORONSWORD] = HintText(CustomMessage("a Goron Sword", /*german*/"ein Goronen-Schwert", /*french*/"une épée Goron"), // /*spanish*/una espada goron { - CustomMessage("a sword", /*german*/"", /*french*/"une épée") + CustomMessage("a sword", /*german*/"ein Schwert", /*french*/"une épée") // /*spanish*/una espada }, { - CustomMessage("a long blade", /*german*/"", /*french*/"une longue lame"), + CustomMessage("a long blade", /*german*/"eine lange Klinge", /*french*/"une longue lame"), // /*spanish*/una gran hoja - CustomMessage("a Goron weapon", /*german*/"", /*french*/"une arme Goron")}); + CustomMessage("a Goron weapon", /*german*/"eine Goronenwaffe", /*french*/"une arme Goron")}); // /*spanish*/un arma goron - hintTextTable[RHT_EMPTY_BOTTLE] = HintText(CustomMessage("a Bottle", /*german*/"", /*french*/"un flacon vide"), + hintTextTable[RHT_EMPTY_BOTTLE] = HintText(CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon vide"), // /*spanish*/una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a glass container", /*german*/"", /*french*/"un cylindre de cristal"), + CustomMessage("a glass container", /*german*/"ein Glasbehälter", /*french*/"un cylindre de cristal"), // /*spanish*/un recipiente de cristal - CustomMessage("an empty jar", /*german*/"", /*french*/"une jarre incassable"), + CustomMessage("an empty jar", /*german*/"ein leerer Krug", /*french*/"une jarre incassable"), // /*spanish*/un frasco vacío - CustomMessage("encased air", /*german*/"", /*french*/"un bocal d'air")}); + CustomMessage("encased air", /*german*/"eingeschlossene Luft", /*french*/"un bocal d'air")}); // /*spanish*/aire a presión - hintTextTable[RHT_BOTTLE_WITH_MILK] = HintText(CustomMessage("a Milk Bottle", /*german*/"", /*french*/"un flacon de lait"), + hintTextTable[RHT_BOTTLE_WITH_MILK] = HintText(CustomMessage("a Milk Bottle", /*german*/"eine Milchflasche", /*french*/"un flacon de lait"), // /*spanish*/una botella de leche { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("cow juice", /*german*/"", /*french*/"une source de calcium"), + CustomMessage("cow juice", /*german*/"Kuhsaft", /*french*/"une source de calcium"), // /*spanish*/una fuente de calcio - CustomMessage("a white liquid", /*german*/"", /*french*/"un liquide blanc"), + CustomMessage("a white liquid", /*german*/"eine weiße Flüssigkeit", /*french*/"un liquide blanc"), // /*spanish*/una bebida nutritiva - CustomMessage("a baby's breakfast", /*german*/"", /*french*/"du jus pour bébé")}); + CustomMessage("a baby's breakfast", /*german*/"ein Babyfrühstück", /*french*/"du jus pour bébé")}); // /*spanish*/un trago para bebés - hintTextTable[RHT_BOTTLE_WITH_RED_POTION] = HintText(CustomMessage("a Red Potion Bottle", /*german*/"", /*french*/"un flacon de potion rouge"), + hintTextTable[RHT_BOTTLE_WITH_RED_POTION] = HintText(CustomMessage("a Red Potion Bottle", /*german*/"eine Flasche mit rotem Elixier", /*french*/"un flacon de potion rouge"), // /*spanish*/una botella de poción roja { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a vitality vial", /*german*/"", /*french*/"un mélange de vitalité"), + CustomMessage("a vitality vial", /*german*/"eine Vitalitätsphiole", /*french*/"un mélange de vitalité"), // /*spanish*/una pócima vitalicia - CustomMessage("a red liquid", /*german*/"", /*french*/"un liquide rouge")}); + CustomMessage("a red liquid", /*german*/"eine rote Flüssigkeit", /*french*/"un liquide rouge")}); // /*spanish*/un remedio rojizo - hintTextTable[RHT_BOTTLE_WITH_GREEN_POTION] = HintText(CustomMessage("a Green Potion Bottle", /*german*/"", /*french*/"un flacon de potion verte"), + hintTextTable[RHT_BOTTLE_WITH_GREEN_POTION] = HintText(CustomMessage("a Green Potion Bottle", /*german*/"eine Flasche mit grünem Elixier", /*french*/"un flacon de potion verte"), // /*spanish*/una botella de poción verde { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a magic mixture", /*german*/"", /*french*/"une réserve magique"), + CustomMessage("a magic mixture", /*german*/"eine magische Mixtur", /*french*/"une réserve magique"), // /*spanish*/un potingue mágico - CustomMessage("a green liquid", /*german*/"", /*french*/"un liquide vert")}); + CustomMessage("a green liquid", /*german*/"eine grüne Flüssigkeit", /*french*/"un liquide vert")}); // /*spanish*/un remedio verduzco - hintTextTable[RHT_BOTTLE_WITH_BLUE_POTION] = HintText(CustomMessage("a Blue Potion Bottle", /*german*/"", /*french*/"un flacon de potion bleue"), + hintTextTable[RHT_BOTTLE_WITH_BLUE_POTION] = HintText(CustomMessage("a Blue Potion Bottle", /*german*/"eine Flasche mit blauem Elixier", /*french*/"un flacon de potion bleue"), // /*spanish*/una botella de poción azul { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("an ailment antidote", /*german*/"", /*french*/"l'élixir ultime"), + CustomMessage("an ailment antidote", /*german*/"ein Krankheitsantidot", /*french*/"l'élixir ultime"), // /*spanish*/un antídoto para el dolor - CustomMessage("a blue liquid", /*german*/"", /*french*/"un liquide bleu")}); + CustomMessage("a blue liquid", /*german*/"eine blaue Flüssigkeit", /*french*/"un liquide bleu")}); // /*spanish*/un remedio índigo - hintTextTable[RHT_BOTTLE_WITH_FAIRY] = HintText(CustomMessage("a Fairy Bottle", /*german*/"", /*french*/"une fée en flacon"), + hintTextTable[RHT_BOTTLE_WITH_FAIRY] = HintText(CustomMessage("a Fairy Bottle", /*german*/"eine Feenflasche", /*french*/"une fée en flacon"), // /*spanish*/un hada en una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("an imprisoned fairy", /*german*/"", /*french*/"une fée emprisonnée"), + CustomMessage("an imprisoned fairy", /*german*/"eine gefangene Fee", /*french*/"une fée emprisonnée"), // /*spanish*/un hada atrapada - CustomMessage("an extra life", /*german*/"", /*french*/"une vie de rechange"), + CustomMessage("an extra life", /*german*/"ein Extraleben", /*french*/"une vie de rechange"), // /*spanish*/una oportunidad más - CustomMessage("Navi's cousin", /*german*/"", /*french*/"le cousin de Navi")}); + CustomMessage("Navi's cousin", /*german*/"Navis Vetter", /*french*/"le cousin de Navi")}); // /*spanish*/una prima de Navi - hintTextTable[RHT_BOTTLE_WITH_FISH] = HintText(CustomMessage("a Fish Bottle", /*german*/"", /*french*/"un poisson en flacon"), + hintTextTable[RHT_BOTTLE_WITH_FISH] = HintText(CustomMessage("a Fish Bottle", /*german*/"eine Fischflasche", /*french*/"un poisson en flacon"), // /*spanish*/un pez en una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("an aquarium", /*german*/"", /*french*/"un aquarium"), + CustomMessage("an aquarium", /*german*/"ein Aquarium", /*french*/"un aquarium"), // /*spanish*/un escamado ser - CustomMessage("a deity's snack", /*german*/"", /*french*/"le repas d'un dieu marin")}); + CustomMessage("a deity's snack", /*german*/"ein Gottheitssnack", /*french*/"le repas d'un dieu marin")}); // /*spanish*/un tentempié de cierta deidad - hintTextTable[RHT_BOTTLE_WITH_BLUE_FIRE] = HintText(CustomMessage("a Blue Fire Bottle", /*german*/"", /*french*/"une flamme bleue en flacon"), + hintTextTable[RHT_BOTTLE_WITH_BLUE_FIRE] = HintText(CustomMessage("a Blue Fire Bottle", /*german*/"eine Flasche mit blauem Feuer", /*french*/"une flamme bleue en flacon"), // /*spanish*/una botella de fuego azul { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a conflagration canteen", /*german*/"", /*french*/"une mystérieuse flamme"), + CustomMessage("a conflagration canteen", /*german*/"eine Brandfeldflasche", /*french*/"une mystérieuse flamme"), // /*spanish*/un incendio retenido - CustomMessage("an icemelt jar", /*german*/"", /*french*/"un brasier glacial")}); + CustomMessage("an icemelt jar", /*german*/"ein eisschmelzender Krug", /*french*/"un brasier glacial")}); // /*spanish*/unas brasas enfrascadas - hintTextTable[RHT_BOTTLE_WITH_BUGS] = HintText(CustomMessage("a Bug Bottle", /*german*/"", /*french*/"un insecte en flacon"), + hintTextTable[RHT_BOTTLE_WITH_BUGS] = HintText(CustomMessage("a Bug Bottle", /*german*/"eine Wanzenflasche", /*french*/"un insecte en flacon"), // /*spanish*/unos insectos en una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("an insectarium", /*german*/"", /*french*/"un insectarium"), + CustomMessage("an insectarium", /*german*/"ein Insektarium", /*french*/"un insectarium"), // /*spanish*/unos invertebrados seres - CustomMessage("Skulltula finders", /*german*/"", /*french*/"une poignée de trouve-Skulltula")}); + CustomMessage("Skulltula finders", /*german*/"Skulltula-Finder", /*french*/"une poignée de trouve-Skulltula")}); // /*spanish*/unos rastreadores de skulltulas - hintTextTable[RHT_BOTTLE_WITH_POE] = HintText(CustomMessage("a Poe Bottle", /*german*/"", /*french*/"un Esprit en flacon"), + hintTextTable[RHT_BOTTLE_WITH_POE] = HintText(CustomMessage("a Poe Bottle", /*german*/"eine Irrlichtflasche", /*french*/"un Esprit en flacon"), // /*spanish*/un Poe en una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a spooky ghost", /*german*/"", /*french*/"un effroyable fantôme"), + CustomMessage("a spooky ghost", /*german*/"ein spukhafter Geist", /*french*/"un effroyable fantôme"), // /*spanish*/un espantoso espectro - CustomMessage("a face in the jar", /*german*/"", /*french*/"un visage dans un bocal")}); + CustomMessage("a face in the jar", /*german*/"ein Gesicht im Krug", /*french*/"un visage dans un bocal")}); // /*spanish*/una expresión enfrascada - hintTextTable[RHT_BOTTLE_WITH_BIG_POE] = HintText(CustomMessage("a Big Poe Bottle", /*german*/"", /*french*/"une Ame en flacon"), + hintTextTable[RHT_BOTTLE_WITH_BIG_POE] = HintText(CustomMessage("a Big Poe Bottle", /*german*/"eine Nachtschwärmerflasche", /*french*/"une Ame en flacon"), // /*spanish*/un Gran Poe en una botella { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("the spookiest ghost", /*german*/"", /*french*/"un épouvantable spectre"), + CustomMessage("the spookiest ghost", /*german*/"der spukhafteste Geist", /*french*/"un épouvantable spectre"), // /*spanish*/el espectro más espeluznante - CustomMessage("a sidequest spirit", /*german*/"", /*french*/"un précieux esprit")}); + CustomMessage("a sidequest spirit", /*german*/"ein Nebenmissionsgeist", /*french*/"un précieux esprit")}); // /*spanish*/un buen valorado espíritu - hintTextTable[RHT_RUTOS_LETTER] = HintText(CustomMessage("Ruto's Letter", /*german*/"", /*french*/"la lettre de Ruto"), + hintTextTable[RHT_RUTOS_LETTER] = HintText(CustomMessage("Ruto's Letter", /*german*/"Rutos Brief", /*french*/"la lettre de Ruto"), // /*spanish*/la carta de Ruto { - CustomMessage("a bottle", /*german*/"", /*french*/"un flacon") + CustomMessage("a bottle", /*german*/"eine Flasche", /*french*/"un flacon") // /*spanish*/una botella }, { - CustomMessage("a call for help", /*german*/"", /*french*/"un appel au secours"), + CustomMessage("a call for help", /*german*/"ein Hilferuf", /*french*/"un appel au secours"), // /*spanish*/una llamada de auxilio - CustomMessage("the note that Mweeps", /*german*/"", /*french*/"un message qui fait mwip"), + CustomMessage("the note that Mweeps", /*german*/"eine Notiz, die Mweeps", /*french*/"un message qui fait mwip"), // /*spanish*/un escrito mweep - CustomMessage("an RHT_SOS call", /*german*/"", /*french*/"un signal RHT_SOS"), + CustomMessage("an RHT_SOS call", /*german*/"ein RHT_SOS Signal", /*french*/"un signal RHT_SOS"), // /*spanish*/una nota de socorro - CustomMessage("a fishy stationery", /*german*/"", /*french*/"un papier mouillé")}); + CustomMessage("a fishy stationery", /*german*/"ein nasses Papier", /*french*/"un papier mouillé")}); // /*spanish*/un mensaje de ayuda - hintTextTable[RHT_ZELDAS_LULLABY] = HintText(CustomMessage("Zelda's Lullaby", /*german*/"", /*french*/"la berceuse de Zelda"), + hintTextTable[RHT_ZELDAS_LULLABY] = HintText(CustomMessage("Zelda's Lullaby", /*german*/"Zeldas Wiegenlied", /*french*/"la berceuse de Zelda"), // /*spanish*/la Nana de Zelda { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale"), // /*spanish*/una cancion normal - CustomMessage("something kept by the royal family", /*german*/"", /*french*/"une chose qui paralyse") + CustomMessage("something kept by the royal family", /*german*/"etwas, das von der royalen Familie bewahrt wird", /*french*/"une chose qui paralyse") // /*spanish*/algo guardado por la familia real }, { - CustomMessage("a song of royal slumber", /*german*/"", /*french*/"une chanson royale"), + CustomMessage("a song of royal slumber", /*german*/"ein royales Lied", /*french*/"une chanson royale"), // /*spanish*/la canción real - CustomMessage("a triforce tune", /*german*/"", /*french*/"la musique sacrée")}); + CustomMessage("a triforce tune", /*german*/"eine heilige Musik", /*french*/"la musique sacrée")}); // /*spanish*/la melodía de la trifuerza - hintTextTable[RHT_EPONAS_SONG] = HintText(CustomMessage("Epona's Song", /*german*/"", /*french*/"le chant d'Epona"), + hintTextTable[RHT_EPONAS_SONG] = HintText(CustomMessage("Epona's Song", /*german*/"Eponas Lied", /*french*/"le chant d'Epona"), // /*spanish*/la Canción de Epona { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale") // /*spanish*/una cancion normal }, { - CustomMessage("an equestrian etude", /*german*/"", /*french*/"une hymne équestre"), + CustomMessage("an equestrian etude", /*german*/"eine Reiterhymne", /*french*/"une hymne équestre"), // /*spanish*/una copla ecuestre - CustomMessage("Malon's melody", /*german*/"", /*french*/"la mélodie des vaches"), + CustomMessage("Malon's melody", /*german*/"Malons Melodie", /*french*/"la mélodie des vaches"), // /*spanish*/la sonata de Malon - CustomMessage("a ranch song", /*german*/"", /*french*/"le chant des champs")}); + CustomMessage("a ranch song", /*german*/"ein Lied des Ackers", /*french*/"le chant des champs")}); // /*spanish*/un canto rupestre - hintTextTable[RHT_SARIAS_SONG] = HintText(CustomMessage("Saria's Song", /*german*/"", /*french*/"le chant de Saria"), + hintTextTable[RHT_SARIAS_SONG] = HintText(CustomMessage("Saria's Song", /*german*/"Salias Lied", /*french*/"le chant de Saria"), // /*spanish*/la Canción de Saria { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale"), // /*spanish*/una cancion normal - CustomMessage("something given by Saria", /*german*/"", /*french*/"un cadeau de Saria") + CustomMessage("something given by Saria", /*german*/"ein Geschenk von Salia", /*french*/"un cadeau de Saria") // /*spanish*/un obsequio de Saria }, { - CustomMessage("a song of dancing Gorons", /*german*/"", /*french*/"une chanson danceuse"), + CustomMessage("a song of dancing Gorons", /*german*/"ein Lied der tanzenden Goronen", /*french*/"une chanson danceuse"), // /*spanish*/un pegadizo tono goron - CustomMessage("Saria's phone number", /*german*/"", /*french*/"le téléphone d'une amie")}); + CustomMessage("Saria's phone number", /*german*/"Salias Telefonnummer", /*french*/"le téléphone d'une amie")}); // /*spanish*/una consulta de asistencia - hintTextTable[RHT_SUNS_SONG] = HintText(CustomMessage("the Sun's Song", /*german*/"", /*french*/"le chant du soleil"), + hintTextTable[RHT_SUNS_SONG] = HintText(CustomMessage("the Sun's Song", /*german*/"Hymne der Sonne", /*french*/"le chant du soleil"), // /*spanish*/la Canción del Sol { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale"), + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale"), // /*spanish*/una cancion normal - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("Sunny Day", /*german*/"", /*french*/"Zénith"), + CustomMessage("Sunny Day", /*german*/"sonniger Tag", /*french*/"Zénith"), // /*spanish*/un día soleado - CustomMessage("the ReDead's bane", /*german*/"", /*french*/"le fléau des Éffrois"), + CustomMessage("the ReDead's bane", /*german*/"das Verderben der Remorts", /*french*/"le fléau des Éffrois"), // /*spanish*/la destructora de Redeads - CustomMessage("the Gibdo's bane", /*german*/"", /*french*/"le fléau des Gibdo")}); + CustomMessage("the Gibdo's bane", /*german*/"das Verderben der Gibdos", /*french*/"le fléau des Gibdo")}); // /*spanish*/la destructora de Gibdos - hintTextTable[RHT_SONG_OF_TIME] = HintText(CustomMessage("the Song of Time", /*german*/"", /*french*/"le chant du temps"), + hintTextTable[RHT_SONG_OF_TIME] = HintText(CustomMessage("the Song of Time", /*german*/"Hymne der Zeit", /*french*/"le chant du temps"), // /*spanish*/la Canción del tiempo { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale") // /*spanish*/una cancion normal }, { - CustomMessage("a song 7 years long", /*german*/"", /*french*/"le flot du temps"), + CustomMessage("a song 7 years long", /*german*/"ein sieben Jahre langes Lied", /*french*/"le flot du temps"), // /*spanish*/la setenada canción - CustomMessage("the tune of ages", /*german*/"", /*french*/"le Chant des Âges")}); + CustomMessage("the tune of ages", /*german*/"Hymne des Äons", /*french*/"le Chant des Âges")}); // /*spanish*/la melodía eónica - hintTextTable[RHT_SONG_OF_STORMS] = HintText(CustomMessage("the Song of Storms", /*german*/"", /*french*/"le chant des tempêtes"), + hintTextTable[RHT_SONG_OF_STORMS] = HintText(CustomMessage("the Song of Storms", /*german*/"Hymne des Sturms", /*french*/"le chant des tempêtes"), // /*spanish*/la Canción de la Tormenta { - CustomMessage("a regular song", /*german*/"", /*french*/"une chanson normale") + CustomMessage("a regular song", /*german*/"ein normales Lied", /*french*/"une chanson normale") // /*spanish*/una cancion normal }, { - CustomMessage("Rain Dance", /*german*/"", /*french*/"Danse Pluie"), + CustomMessage("Rain Dance", /*german*/"Regentanz", /*french*/"Danse Pluie"), // /*spanish*/la danza de la lluvia - CustomMessage("a thunderstorm tune", /*german*/"", /*french*/"une hymne foudroyante"), + CustomMessage("a thunderstorm tune", /*german*/"eine Gewitterhymne", /*french*/"une hymne foudroyante"), // /*spanish*/una sonata tormentosa - CustomMessage("windmill acceleration", /*german*/"", /*french*/"l'accélérateur de moulins")}); + CustomMessage("windmill acceleration", /*german*/"Windmühlenbeschleunigung", /*french*/"l'accélérateur de moulins")}); // /*spanish*/el arranque de molinos - hintTextTable[RHT_MINUET_OF_FOREST] = HintText(CustomMessage("the Minuet of Forest", /*german*/"", /*french*/"le menuet de la forêt"), + hintTextTable[RHT_MINUET_OF_FOREST] = HintText(CustomMessage("the Minuet of Forest", /*german*/"Menuett des Waldes", /*french*/"le menuet de la forêt"), // /*spanish*/el Minueto del bosque { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("the song of tall trees", /*german*/"", /*french*/"le bruit des arbres"), + CustomMessage("the song of tall trees", /*german*/"Lied der großen Bäume", /*french*/"le bruit des arbres"), // /*spanish*/la canción de las copas - CustomMessage("an arboreal anthem", /*german*/"", /*french*/"l'hymne sylvestre"), + CustomMessage("an arboreal anthem", /*german*/"eine baumartige Hymne", /*french*/"l'hymne sylvestre"), // /*spanish*/el himno forestal - CustomMessage("a green spark trail", /*german*/"", /*french*/"une comète verte")}); + CustomMessage("a green spark trail", /*german*/"ein grüner Komet", /*french*/"une comète verte")}); // /*spanish*/el sendero esmeralda - hintTextTable[RHT_BOLERO_OF_FIRE] = HintText(CustomMessage("the Bolero of Fire", /*german*/"", /*french*/"le boléro du feu"), + hintTextTable[RHT_BOLERO_OF_FIRE] = HintText(CustomMessage("the Bolero of Fire", /*german*/"Bolero des Feuers", /*french*/"le boléro du feu"), // /*spanish*/el Bolero del fuego { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("a song of lethal lava", /*german*/"", /*french*/"une musique enflammée"), + CustomMessage("a song of lethal lava", /*german*/"Lied der tödlichen Lava", /*french*/"une musique enflammée"), // /*spanish*/la canción de la lava - CustomMessage("a red spark trail", /*german*/"", /*french*/"une comète rouge"), + CustomMessage("a red spark trail", /*german*/"ein roter Komet", /*french*/"une comète rouge"), // /*spanish*/el sendero rubí - CustomMessage("a volcanic verse", /*german*/"", /*french*/"le souffle du volcan")}); + CustomMessage("a volcanic verse", /*german*/"ein vulkanischer Vers", /*french*/"le souffle du volcan")}); // /*spanish*/el verso volcánico - hintTextTable[RHT_SERENADE_OF_WATER] = HintText(CustomMessage("the Serenade of Water", /*german*/"", /*french*/"la sérénade de l'eau"), + hintTextTable[RHT_SERENADE_OF_WATER] = HintText(CustomMessage("the Serenade of Water", /*german*/"Serenade des Wassers", /*french*/"la sérénade de l'eau"), // /*spanish*/la Serenata del agua { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("a song of a damp ditch", /*german*/"", /*french*/"le calme de l'eau"), + CustomMessage("a song of a damp ditch", /*german*/"die Stille des Wassers", /*french*/"le calme de l'eau"), // /*spanish*/la canción del estanque - CustomMessage("a blue spark trail", /*german*/"", /*french*/"une comète bleue"), + CustomMessage("a blue spark trail", /*german*/"ein blauer Komet", /*french*/"une comète bleue"), // /*spanish*/el sendero zafiro - CustomMessage("the lake's lyric", /*german*/"", /*french*/"la voix du lac")}); + CustomMessage("the lake's lyric", /*german*/"die Lyrik des Sees", /*french*/"la voix du lac")}); // /*spanish*/la letra del lago - hintTextTable[RHT_REQUIEM_OF_SPIRIT] = HintText(CustomMessage("the Requiem of Spirit", /*german*/"", /*french*/"le requiem des esprits"), + hintTextTable[RHT_REQUIEM_OF_SPIRIT] = HintText(CustomMessage("the Requiem of Spirit", /*german*/"Requiem der Geister", /*french*/"le requiem des esprits"), // /*spanish*/el Réquiem del espíritu { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("a song of sandy statues", /*german*/"", /*french*/"la mélodie d'une grande statue"), + CustomMessage("a song of sandy statues", /*german*/"Lied der sandigen Statuen", /*french*/"la mélodie d'une grande statue"), // /*spanish*/la canción de la gran estatua - CustomMessage("an orange spark trail", /*german*/"", /*french*/"une comète orange"), + CustomMessage("an orange spark trail", /*german*/"ein oranger Komet", /*french*/"une comète orange"), // /*spanish*/el sendero ámbar - CustomMessage("the desert ditty", /*german*/"", /*french*/"le vent du désert")}); + CustomMessage("the desert ditty", /*german*/"der Wind der Wüste", /*french*/"le vent du désert")}); // /*spanish*/la estrofa del desierto - hintTextTable[RHT_NOCTURNE_OF_SHADOW] = HintText(CustomMessage("the Nocturne of Shadow", /*german*/"", /*french*/"le nocturne de l'ombre"), + hintTextTable[RHT_NOCTURNE_OF_SHADOW] = HintText(CustomMessage("the Nocturne of Shadow", /*german*/"Nocturne des Schattens", /*french*/"le nocturne de l'ombre"), // /*spanish*/el Nocturno de la sombra { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("a song of spooky spirits", /*german*/"", /*french*/"une hymne de chair de poule"), + CustomMessage("a song of spooky spirits", /*german*/"Lied der spukhaften Geister", /*french*/"une hymne de chair de poule"), // /*spanish*/la canción de los espectros - CustomMessage("a graveyard boogie", /*german*/"", /*french*/"un boogie de fantômes"), + CustomMessage("a graveyard boogie", /*german*/"ein Friedhofsboogie", /*french*/"un boogie de fantômes"), // /*spanish*/una honra fúnebre - CustomMessage("a haunted hymn", /*german*/"", /*french*/"une chanson lugubre"), + CustomMessage("a haunted hymn", /*german*/"eine Spukhymne", /*french*/"une chanson lugubre"), // /*spanish*/una estrofa encantada - CustomMessage("a purple spark trail", /*german*/"", /*french*/"une comète mauve")}); + CustomMessage("a purple spark trail", /*german*/"ein violetter Komet", /*french*/"une comète mauve")}); // /*spanish*/el sendero malva - hintTextTable[RHT_PRELUDE_OF_LIGHT] = HintText(CustomMessage("the Prelude of Light", /*german*/"", /*french*/"le prélude de la lumière"), + hintTextTable[RHT_PRELUDE_OF_LIGHT] = HintText(CustomMessage("the Prelude of Light", /*german*/"Kantate des Lichts", /*french*/"le prélude de la lumière"), // /*spanish*/el Preludio de la luz { - CustomMessage("a warp song", /*german*/"", /*french*/"une chanson de téléportation") + CustomMessage("a warp song", /*german*/"ein Teleportationslied", /*french*/"une chanson de téléportation") // /*spanish*/una canción de teletransportación }, { - CustomMessage("a luminous prologue melody", /*german*/"", /*french*/"une matine illuminée"), + CustomMessage("a luminous prologue melody", /*german*/"eine leuchtende Melodie", /*french*/"une matine illuminée"), // /*spanish*/la melodía refulgente - CustomMessage("a yellow spark trail", /*german*/"", /*french*/"une comète jaune"), + CustomMessage("a yellow spark trail", /*german*/"ein gelber Komet", /*french*/"une comète jaune"), // /*spanish*/el sendero resplandeciente - CustomMessage("the temple traveler", /*german*/"", /*french*/"un chant de sanctuaire")}); + CustomMessage("the temple traveler", /*german*/"ein Tempelreisender", /*french*/"un chant de sanctuaire")}); // /*spanish*/la ruta del templo - hintTextTable[RHT_DEKU_TREE_MAP] = HintText(CustomMessage("the Deku Tree Map", /*german*/"", /*french*/"la carte de l'Arbre Mojo"), + hintTextTable[RHT_DEKU_TREE_MAP] = HintText(CustomMessage("the Deku Tree Map", /*german*/"die Karte des Deku-Baums", /*french*/"la carte de l'Arbre Mojo"), // /*spanish*/el mapa del Gran Árbol Deku { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a mossy atlas", /*german*/"", /*french*/"un atlas boisé"), + CustomMessage("a mossy atlas", /*german*/"ein moosiger Atlas", /*french*/"un atlas boisé"), // /*spanish*/un atlas musgoso - CustomMessage("some mossy blueprints", /*german*/"", /*french*/"un plan boisé")}); + CustomMessage("some mossy blueprints", /*german*/"einige moosige Blaupausen", /*french*/"un plan boisé")}); // /*spanish*/unos planos musgosos - hintTextTable[RHT_DODONGOS_CAVERN_MAP] = HintText(CustomMessage("the Dodongo's Cavern Map", /*german*/"", /*french*/"la carte de la Caverne Dodongo"), + hintTextTable[RHT_DODONGOS_CAVERN_MAP] = HintText(CustomMessage("the Dodongo's Cavern Map", /*german*/"die Karte der Dodongo-Höhle", /*french*/"la carte de la Caverne Dodongo"), // /*spanish*/el mapa de la Cueva de los Dodongos { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a rocky atlas", /*german*/"", /*french*/"un atlas rocheux"), + CustomMessage("a rocky atlas", /*german*/"eine felsiger Atlas", /*french*/"un atlas rocheux"), // /*spanish*/un atlas rocoso - CustomMessage("some rocky blueprints", /*german*/"", /*french*/"un plan rocheux")}); + CustomMessage("some rocky blueprints", /*german*/"einige felsige Blaupausen", /*french*/"un plan rocheux")}); // /*spanish*/unos planos rocosos - hintTextTable[RHT_JABU_JABUS_BELLY_MAP] = HintText(CustomMessage("the Jabu-Jabu's Belly Map", /*german*/"", /*french*/"la carte de Jabu-Jabu"), + hintTextTable[RHT_JABU_JABUS_BELLY_MAP] = HintText(CustomMessage("the Jabu-Jabu's Belly Map", /*german*/"die Karte des Jabu-Jabu-Bauchs", /*french*/"la carte de Jabu-Jabu"), // /*spanish*/el mapa de la Tripa de Jabu-Jabu { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a fishy atlas", /*german*/"", /*french*/"un atlas digéré"), + CustomMessage("a fishy atlas", /*german*/"ein fischiger Atlas", /*french*/"un atlas digéré"), // /*spanish*/un atlas digesto - CustomMessage("some fishy blueprints", /*german*/"", /*french*/"un plan digéré")}); + CustomMessage("some fishy blueprints", /*german*/"einige fischige Blaupausen", /*french*/"un plan digéré")}); // /*spanish*/unos planos digestos - hintTextTable[RHT_FOREST_TEMPLE_MAP] = HintText(CustomMessage("the Forest Temple Map", /*german*/"", /*french*/"la carte du Temple de la Forêt"), + hintTextTable[RHT_FOREST_TEMPLE_MAP] = HintText(CustomMessage("the Forest Temple Map", /*german*/"die Karte des Waldtempels", /*french*/"la carte du Temple de la Forêt"), // /*spanish*/el mapa del Templo del Bosque { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a sylvan atlas", /*german*/"", /*french*/"un atlas sylvestre"), + CustomMessage("a sylvan atlas", /*german*/"ein waldiger Atlas", /*french*/"un atlas sylvestre"), // /*spanish*/un atlas enselvado - CustomMessage("some sylvan blueprints", /*german*/"", /*french*/"un plan sylvestre")}); + CustomMessage("some sylvan blueprints", /*german*/"einige waldige Blaupausen", /*french*/"un plan sylvestre")}); // /*spanish*/unos planos enselvados - hintTextTable[RHT_FIRE_TEMPLE_MAP] = HintText(CustomMessage("the Fire Temple Map", /*german*/"", /*french*/"la carte du Temple du Feu"), + hintTextTable[RHT_FIRE_TEMPLE_MAP] = HintText(CustomMessage("the Fire Temple Map", /*german*/"die Karte des Feuertempels", /*french*/"la carte du Temple du Feu"), // /*spanish*/el mapa del Templo del Fuego { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a molten atlas", /*german*/"", /*french*/"un atlas fondu"), + CustomMessage("a molten atlas", /*german*/"ein geschmolzener Atlas", /*french*/"un atlas fondu"), // /*spanish*/un atlas fundido - CustomMessage("some molten blueprints", /*german*/"", /*french*/"un plan fondu")}); + CustomMessage("some molten blueprints", /*german*/"einige geschmolzene Blaupausen", /*french*/"un plan fondu")}); // /*spanish*/unos planos fundidos - hintTextTable[RHT_WATER_TEMPLE_MAP] = HintText(CustomMessage("the Water Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Eau"), + hintTextTable[RHT_WATER_TEMPLE_MAP] = HintText(CustomMessage("the Water Temple Map", /*german*/"die Karte des Wassertempels", /*french*/"la carte du Temple de l'Eau"), // /*spanish*/el mapa del Templo del Agua { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a wet atlas", /*german*/"", /*french*/"un atlas humide"), + CustomMessage("a wet atlas", /*german*/"ein nasser Atlas", /*french*/"un atlas humide"), // /*spanish*/un atlas mojado - CustomMessage("some wet blueprints", /*german*/"", /*french*/"un plan humide")}); + CustomMessage("some wet blueprints", /*german*/"einige nasse Blaupausen", /*french*/"un plan humide")}); // /*spanish*/unos planos mojados - hintTextTable[RHT_SPIRIT_TEMPLE_MAP] = HintText(CustomMessage("the Spirit Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Esprit"), + hintTextTable[RHT_SPIRIT_TEMPLE_MAP] = HintText(CustomMessage("the Spirit Temple Map", /*german*/"die Karte des Geistertempels", /*french*/"la carte du Temple de l'Esprit"), // /*spanish*/el mapa del Templo del Espíritu { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a sandy atlas", /*german*/"", /*french*/"un atlas sableux"), + CustomMessage("a sandy atlas", /*german*/"ein sandiger Atlas", /*french*/"un atlas sableux"), // /*spanish*/un atlas arenoso - CustomMessage("some sandy blueprints", /*german*/"", /*french*/"un plan sableux")}); + CustomMessage("some sandy blueprints", /*german*/"einige sandige Blaupausen", /*french*/"un plan sableux")}); // /*spanish*/unos planos arenosos - hintTextTable[RHT_SHADOW_TEMPLE_MAP] = HintText(CustomMessage("the Shadow Temple Map", /*german*/"", /*french*/"la carte du Temple de l'Ombre"), + hintTextTable[RHT_SHADOW_TEMPLE_MAP] = HintText(CustomMessage("the Shadow Temple Map", /*german*/"die Karte des Schattentempels", /*french*/"la carte du Temple de l'Ombre"), // /*spanish*/el mapa del Templo de las Sombras { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a creepy atlas", /*german*/"", /*french*/"un atlas sinistre"), + CustomMessage("a creepy atlas", /*german*/"eine gruseliger Atlas", /*french*/"un atlas sinistre"), // /*spanish*/un atlas siniestra - CustomMessage("some creepy blueprints", /*german*/"", /*french*/"un plan sinistre")}); + CustomMessage("some creepy blueprints", /*german*/"einige gruselige Blaupausen", /*french*/"un plan sinistre")}); // /*spanish*/unos planos siniestras - hintTextTable[RHT_BOTTOM_OF_THE_WELL_MAP] = HintText(CustomMessage("the Bottom of the Well Map", /*german*/"", /*french*/"la carte du fond du Puits"), + hintTextTable[RHT_BOTTOM_OF_THE_WELL_MAP] = HintText(CustomMessage("the Bottom of the Well Map", /*german*/"die Karte des Grund des Brunnens", /*french*/"la carte du fond du Puits"), // /*spanish*/el mapa del Fondo del pozo { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a moldy atlas", /*german*/"", /*french*/"un atlas moisi"), + CustomMessage("a moldy atlas", /*german*/"ein schimmeliger Atlas", /*french*/"un atlas moisi"), // /*spanish*/un atlas mohoso - CustomMessage("some moldy blueprints", /*german*/"", /*french*/"un plan moisi")}); + CustomMessage("some moldy blueprints", /*german*/"einige schimmelige Blaupausen", /*french*/"un plan moisi")}); // /*spanish*/unos planos mohosos - hintTextTable[RHT_ICE_CAVERN_MAP] = HintText(CustomMessage("the Ice Cavern Map", /*german*/"", /*french*/"la carte de la Caverne Polaire"), + hintTextTable[RHT_ICE_CAVERN_MAP] = HintText(CustomMessage("the Ice Cavern Map", /*german*/"die Karte der Eishöhle", /*french*/"la carte de la Caverne Polaire"), // /*spanish*/el mapa de la Caverna de hielo { - CustomMessage("a dungeon map", /*german*/"", /*french*/"une carte") + CustomMessage("a dungeon map", /*german*/"eine Karte", /*french*/"une carte") // /*spanish*/un mapa }, { - CustomMessage("a polar atlas", /*german*/"", /*french*/"un atlas polaire"), + CustomMessage("a polar atlas", /*german*/"ein polarer Atlas", /*french*/"un atlas polaire"), // /*spanish*/un atlas polar - CustomMessage("some polar blueprints", /*german*/"", /*french*/"un plan polaire")}); + CustomMessage("some polar blueprints", /*german*/"einige polare Blaupausen", /*french*/"un plan polaire")}); // /*spanish*/unos planos polars - hintTextTable[RHT_DEKU_TREE_COMPASS] = HintText(CustomMessage("the Deku Tree Compass", /*german*/"", /*french*/"la boussole de l'Arbre Mojo"), + hintTextTable[RHT_DEKU_TREE_COMPASS] = HintText(CustomMessage("the Deku Tree Compass", /*german*/"der Kompaß des Deku-Baums", /*french*/"la boussole de l'Arbre Mojo"), // /*spanish*/la brújula del Gran Árbol Deku { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a mossy treasure tracker", /*german*/"", /*french*/"un cherche-trésor boisé"), + CustomMessage("a mossy treasure tracker", /*german*/"ein moosiger Schatzfinder", /*french*/"un cherche-trésor boisé"), // /*spanish*/un zahorí musgoso - CustomMessage("a mossy magnetic needle", /*german*/"", /*french*/"une aimant boisée")}); + CustomMessage("a mossy magnetic needle", /*german*/"eine moosige Magnetnadel", /*french*/"une aimant boisée")}); // /*spanish*/un imán musgoso - hintTextTable[RHT_DODONGOS_CAVERN_COMPASS] = HintText(CustomMessage("the Dodongo's Cavern Compass", /*german*/"", /*french*/"la boussole de la Caverne Dodongo"), + hintTextTable[RHT_DODONGOS_CAVERN_COMPASS] = HintText(CustomMessage("the Dodongo's Cavern Compass", /*german*/"der Kompaß der Dodongo-Höhle", /*french*/"la boussole de la Caverne Dodongo"), // /*spanish*/la brújula de la Cueva de los Dodongos { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a rocky treasure tracker", /*german*/"", /*french*/"un cherche-trésor rocheux"), + CustomMessage("a rocky treasure tracker", /*german*/"ein felsiger Schatzfinder", /*french*/"un cherche-trésor rocheux"), // /*spanish*/un zahorí rocoso - CustomMessage("a rocky magnetic needle", /*german*/"", /*french*/"une aimant rocheux")}); + CustomMessage("a rocky magnetic needle", /*german*/"eine felsige Magnetnadel", /*french*/"une aimant rocheux")}); // /*spanish*/un imán rocoso - hintTextTable[RHT_JABU_JABUS_BELLY_COMPASS] = HintText(CustomMessage("the Jabu-Jabu's Belly Compass", /*german*/"", /*french*/"la boussole de Jabu-Jabu"), + hintTextTable[RHT_JABU_JABUS_BELLY_COMPASS] = HintText(CustomMessage("the Jabu-Jabu's Belly Compass", /*german*/"der Kompaß des Jabu-Jabu-Bauchs", /*french*/"la boussole de Jabu-Jabu"), // /*spanish*/la brújula de la Tripa de Jabu-Jabu { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a fishy treasure tracker", /*german*/"", /*french*/"un cherche-trésor digéré"), + CustomMessage("a fishy treasure tracker", /*german*/"ein fischiger Schatzfinder", /*french*/"un cherche-trésor digéré"), // /*spanish*/un zahorí digesto - CustomMessage("a fishy magnetic needle", /*german*/"", /*french*/"une aimant digéré")}); + CustomMessage("a fishy magnetic needle", /*german*/"eine fischige Magnetnadel", /*french*/"une aimant digéré")}); // /*spanish*/un imán digesto - hintTextTable[RHT_FOREST_TEMPLE_COMPASS] = HintText(CustomMessage("the Forest Temple Compass", /*german*/"", /*french*/"la boussole du Temple de la Forêt"), + hintTextTable[RHT_FOREST_TEMPLE_COMPASS] = HintText(CustomMessage("the Forest Temple Compass", /*german*/"der Kompaß des Waldtempels", /*french*/"la boussole du Temple de la Forêt"), // /*spanish*/la brújula del Templo del Bosque { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a sylvan treasure tracker", /*german*/"", /*french*/"un cherche-trésor sylvestre"), + CustomMessage("a sylvan treasure tracker", /*german*/"ein waldiger Schatzfinder", /*french*/"un cherche-trésor sylvestre"), // /*spanish*/un zahorí enselvado - CustomMessage("a sylvan magnetic needle", /*german*/"", /*french*/"une aimant sylvestre")}); + CustomMessage("a sylvan magnetic needle", /*german*/"eine waldige Magnetnadel", /*french*/"une aimant sylvestre")}); // /*spanish*/un imán enselvado - hintTextTable[RHT_FIRE_TEMPLE_COMPASS] = HintText(CustomMessage("the Fire Temple Compass", /*german*/"", /*french*/"la boussole du Temple du Feu"), + hintTextTable[RHT_FIRE_TEMPLE_COMPASS] = HintText(CustomMessage("the Fire Temple Compass", /*german*/"der Kompaß des Feuertempels", /*french*/"la boussole du Temple du Feu"), // /*spanish*/la brújula del Templo del Fuego { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a molten treasure tracker", /*german*/"", /*french*/"un cherche-trésor fondu"), + CustomMessage("a molten treasure tracker", /*german*/"ein geschmolzener Schatzfinder", /*french*/"un cherche-trésor fondu"), // /*spanish*/un zahorí fundido - CustomMessage("a molten magnetic needle", /*german*/"", /*french*/"une aimant fondu")}); + CustomMessage("a molten magnetic needle", /*german*/"eine geschmolzene Magnetnadel", /*french*/"une aimant fondu")}); // /*spanish*/un imán fundido - hintTextTable[RHT_WATER_TEMPLE_COMPASS] = HintText(CustomMessage("the Water Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Eau"), + hintTextTable[RHT_WATER_TEMPLE_COMPASS] = HintText(CustomMessage("the Water Temple Compass", /*german*/"der Kompaß des Wassertempels", /*french*/"la boussole du Temple de l'Eau"), // /*spanish*/la brújula del Templo del Agua { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a wet treasure tracker", /*german*/"", /*french*/"un cherche-trésor humide"), + CustomMessage("a wet treasure tracker", /*german*/"ein nasser Schatzfinder", /*french*/"un cherche-trésor humide"), // /*spanish*/un zahorí mojado - CustomMessage("a wet magnetic needle", /*german*/"", /*french*/"une aimant humide")}); + CustomMessage("a wet magnetic needle", /*german*/"eine nasse Magnetnadel", /*french*/"une aimant humide")}); // /*spanish*/un imán mojado - hintTextTable[RHT_SPIRIT_TEMPLE_COMPASS] = HintText(CustomMessage("the Spirit Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Esprit"), + hintTextTable[RHT_SPIRIT_TEMPLE_COMPASS] = HintText(CustomMessage("the Spirit Temple Compass", /*german*/"der Kompaß des Geistertempels", /*french*/"la boussole du Temple de l'Esprit"), // /*spanish*/la brújula del Templo del Espíritu { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a sandy treasure tracker", /*german*/"", /*french*/"un cherche-trésor sableux"), + CustomMessage("a sandy treasure tracker", /*german*/"ein sandiger Schatzfinder", /*french*/"un cherche-trésor sableux"), // /*spanish*/un zahorí arenoso - CustomMessage("a sandy magnetic needle", /*german*/"", /*french*/"une aimant sableux")}); + CustomMessage("a sandy magnetic needle", /*german*/"eine sandige Magnetnadel", /*french*/"une aimant sableux")}); // /*spanish*/un imán arenoso - hintTextTable[RHT_SHADOW_TEMPLE_COMPASS] = HintText(CustomMessage("the Shadow Temple Compass", /*german*/"", /*french*/"la boussole du Temple de l'Ombre"), + hintTextTable[RHT_SHADOW_TEMPLE_COMPASS] = HintText(CustomMessage("the Shadow Temple Compass", /*german*/"der Kompaß des Schattentempels", /*french*/"la boussole du Temple de l'Ombre"), // /*spanish*/la brújula del Templo de las Sombras { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a creepy treasure tracker", /*german*/"", /*french*/"un cherche-trésor sinistre"), + CustomMessage("a creepy treasure tracker", /*german*/"ein gruseliger Schatzfinder", /*french*/"un cherche-trésor sinistre"), // /*spanish*/un zahorí siniestra - CustomMessage("a creepy magnetic needle", /*german*/"", /*french*/"une aimant sinistre")}); + CustomMessage("a creepy magnetic needle", /*german*/"eine gruselige Magnetnadel", /*french*/"une aimant sinistre")}); // /*spanish*/un imán siniestra - hintTextTable[RHT_BOTTOM_OF_THE_WELL_COMPASS] = HintText(CustomMessage("the Bottom of the Well Compass", /*german*/"", /*french*/"la boussole du fond du Puits"), + hintTextTable[RHT_BOTTOM_OF_THE_WELL_COMPASS] = HintText(CustomMessage("the Bottom of the Well Compass", /*german*/"der Kompaß des Grund des Brunnens", /*french*/"la boussole du fond du Puits"), // /*spanish*/la brújula del Fondo del pozo { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a dank treasure tracker", /*german*/"", /*french*/"un cherche-trésor moisi"), + CustomMessage("a dank treasure tracker", /*german*/"ein feuchter Schatzfinder", /*french*/"un cherche-trésor moisi"), // /*spanish*/un zahorí mohoso - CustomMessage("a dank magnetic needle", /*german*/"", /*french*/"une aimant moisi")}); + CustomMessage("a dank magnetic needle", /*german*/"eine feuchte Magnetnadel", /*french*/"une aimant moisi")}); // /*spanish*/un imán mohoso - hintTextTable[RHT_ICE_CAVERN_COMPASS] = HintText(CustomMessage("the Ice Cavern Compass", /*german*/"", /*french*/"la Boussole de la Caverne Polaire"), + hintTextTable[RHT_ICE_CAVERN_COMPASS] = HintText(CustomMessage("the Ice Cavern Compass", /*german*/"der Kompaß der Eishöhle", /*french*/"la Boussole de la Caverne Polaire"), // /*spanish*/la brújula de la Caverna de hielo { - CustomMessage("a compass", /*german*/"", /*french*/"une boussole") + CustomMessage("a compass", /*german*/"ein Kompaß", /*french*/"une boussole") // /*spanish*/una brújula }, { - CustomMessage("a polar treasure tracker", /*german*/"", /*french*/"un cherche-trésor polaire"), + CustomMessage("a polar treasure tracker", /*german*/"ein polarer Schatzfinder", /*french*/"un cherche-trésor polaire"), // /*spanish*/un zahorí polar - CustomMessage("a polar magnetic needle", /*german*/"", /*french*/"une aimant polaire")}); + CustomMessage("a polar magnetic needle", /*german*/"eine polare Magnetnadel", /*french*/"une aimant polaire")}); // /*spanish*/un imán polar - hintTextTable[RHT_FOREST_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Forest Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de la Forêt"), + hintTextTable[RHT_FOREST_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Forest Temple Boss Key", /*german*/"der Waldtempel-Master-Schlüssel", /*french*/"la Clé d'Or du Temple de la Forêt"), // /*spanish*/la gran llave del Templo del Bosque { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a sylvan master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sylvestre"), + CustomMessage("a sylvan master of unlocking", /*german*/"ein waldiger Meister des Entschlüsselns", /*french*/"un anti-grosse porte sylvestre"), // /*spanish*/la clave enselvada de un jefe - CustomMessage("a sylvan dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sylvestree")}); + CustomMessage("a sylvan dungeon's master pass", /*german*/"ein waldiger Dungeon-Meisterpass", /*french*/"une clé maléfique sylvestre")}); // /*spanish*/el pase maestro enselvado - hintTextTable[RHT_FIRE_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Fire Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple du Feu"), + hintTextTable[RHT_FIRE_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Fire Temple Boss Key", /*german*/"der Feuertempel-Master-Schlüssel", /*french*/"la Clé d'Or du Temple du Feu"), // /*spanish*/la gran llave del Templo del Fuego { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a molten master of unlocking", /*german*/"", /*french*/"un anti-grosse porte fondu"), + CustomMessage("a molten master of unlocking", /*german*/"ein geschmolzener Meister des Entschlüsselns", /*french*/"un anti-grosse porte fondu"), // /*spanish*/la clave fundido de un jefe - CustomMessage("a molten dungeon's master pass", /*german*/"", /*french*/"une clé maléfique fondu")}); + CustomMessage("a molten dungeon's master pass", /*german*/"ein geschmolzener Dungeon-Meisterpass", /*french*/"une clé maléfique fondu")}); // /*spanish*/el pase maestro fundido - hintTextTable[RHT_WATER_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Water Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Eau"), + hintTextTable[RHT_WATER_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Water Temple Boss Key", /*german*/"der Wassertempel-Master-Schlüssel", /*french*/"la Clé d'Or du Temple de l'Eau"), // /*spanish*/la gran llave del Templo del Agua { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a wet master of unlocking", /*german*/"", /*french*/"un anti-grosse porte humide"), + CustomMessage("a wet master of unlocking", /*german*/"ein nasser Meister des Entschlüsselns", /*french*/"un anti-grosse porte humide"), // /*spanish*/la clave mojado de un jefe - CustomMessage("a wet dungeon's master pass", /*german*/"", /*french*/"une clé maléfique humide")}); + CustomMessage("a wet dungeon's master pass", /*german*/"ein nasser Dungeon-Meisterpass", /*french*/"une clé maléfique humide")}); // /*spanish*/el pase maestro mojado - hintTextTable[RHT_SPIRIT_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Spirit Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Esprit"), + hintTextTable[RHT_SPIRIT_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Spirit Temple Boss Key", /*german*/"der Geistertempel-Master-Schlüssel", /*french*/"la Clé d'Or du Temple de l'Esprit"), // /*spanish*/la gran llave del Templo del Espíritu { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a sandy master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sableux"), + CustomMessage("a sandy master of unlocking", /*german*/"ein sandiger Meister des Entschlüsselns", /*french*/"un anti-grosse porte sableux"), // /*spanish*/la clave arenoso de un jefe - CustomMessage("a sandy dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sableux")}); + CustomMessage("a sandy dungeon's master pass", /*german*/"ein sandiger Dungeon-Meisterpass", /*french*/"une clé maléfique sableux")}); // /*spanish*/el pase maestro arenoso - hintTextTable[RHT_SHADOW_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Shadow Temple Boss Key", /*german*/"", /*french*/"la Clé d'Or du Temple de l'Ombre"), + hintTextTable[RHT_SHADOW_TEMPLE_BOSS_KEY] = HintText(CustomMessage("the Shadow Temple Boss Key", /*german*/"der Schattentempel-Master-Schlüssel", /*french*/"la Clé d'Or du Temple de l'Ombre"), // /*spanish*/la gran llave del Templo de las Sombras { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a creepy master of unlocking", /*german*/"", /*french*/"un anti-grosse porte sinistre"), + CustomMessage("a creepy master of unlocking", /*german*/"ein gruseliger Meister des Entschlüsselns", /*french*/"un anti-grosse porte sinistre"), // /*spanish*/la clave siniestra de un jefe - CustomMessage("a creepy dungeon's master pass", /*german*/"", /*french*/"une clé maléfique sinistre")}); + CustomMessage("a creepy dungeon's master pass", /*german*/"ein gruseliger Dungeon-Meisterpass", /*french*/"une clé maléfique sinistre")}); // /*spanish*/el pase maestro siniestra - hintTextTable[RHT_GANONS_CASTLE_BOSS_KEY] = HintText(CustomMessage("the Ganon's Castle Boss Key", /*german*/"", /*french*/"la Clé d'Or du Château de Ganon"), + hintTextTable[RHT_GANONS_CASTLE_BOSS_KEY] = HintText(CustomMessage("the Ganon's Castle Boss Key", /*german*/"der Master-Schlüssel für Ganons Schloß", /*french*/"la Clé d'Or du Château de Ganon"), // /*spanish*/la gran llave del Castillo de Ganon { - CustomMessage("a boss key", /*german*/"", /*french*/"une Clé d'Or") + CustomMessage("a boss key", /*german*/"ein Master-Schlüssel", /*french*/"une Clé d'Or") // /*spanish*/una gran llave }, { - CustomMessage("a final master of unlocking", /*german*/"", /*french*/"un anti-grosse porte final"), + CustomMessage("a final master of unlocking", /*german*/"ein finaler Meister des Entschlüsselns", /*french*/"un anti-grosse porte final"), // /*spanish*/la clave final de un jefe - CustomMessage("a final dungeon's master pass", /*german*/"", /*french*/"une clé maléfique final")}); + CustomMessage("a final dungeon's master pass", /*german*/"ein finaler Dungeon-Meisterpass", /*french*/"une clé maléfique final")}); // /*spanish*/el pase maestro final - hintTextTable[RHT_FOREST_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Forest Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de la Forêt"), + hintTextTable[RHT_FOREST_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Forest Temple Small Key", /*german*/"ein kleiner Waldtempel-Schlüssel", /*french*/"une petite clé du Temple de la Forêt"), // /*spanish*/una llave pequeña del Templo del Bosque { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a sylvan tool for unlocking", /*german*/"", /*french*/"un anti-porte sylvestre"), + CustomMessage("a sylvan tool for unlocking", /*german*/"ein waldiges Werkzeug zur Entschlüsselung", /*french*/"un anti-porte sylvestre"), // /*spanish*/una clave de una entrada enselvada - CustomMessage("a sylvan dungeon pass", /*german*/"", /*french*/"le rêve sylvestre d'un prisonnier"), + CustomMessage("a sylvan dungeon pass", /*german*/"ein waldiger Dungeon-Pass", /*french*/"le rêve sylvestre d'un prisonnier"), // /*spanish*/un pase de una mazmorra enselvada - CustomMessage("a sylvan lock remover", /*german*/"", /*french*/"un efface-serrure sylvestre"), + CustomMessage("a sylvan lock remover", /*german*/"ein waldiger Schlossentferner", /*french*/"un efface-serrure sylvestre"), // /*spanish*/un destructor de cerraduras enselvada - CustomMessage("a sylvan lockpick", /*german*/"", /*french*/"un crochet à porte sylvestre")}); + CustomMessage("a sylvan lockpick", /*german*/"ein waldiger Dietrich", /*french*/"un crochet à porte sylvestre")}); // /*spanish*/una apertura portentosa enselvada - hintTextTable[RHT_FIRE_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Fire Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple du Feu"), + hintTextTable[RHT_FIRE_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Fire Temple Small Key", /*german*/"ein kleiner Feuertempel-Schlüssel", /*french*/"une petite clé du Temple du Feu"), // /*spanish*/una llave pequeña del Templo del Fuego { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a molten tool for unlocking", /*german*/"", /*french*/"un anti-porte fondu"), + CustomMessage("a molten tool for unlocking", /*german*/"ein geschmolzenes Werkzeug zur Entschlüsselung", /*french*/"un anti-porte fondu"), // /*spanish*/una clave de una entrada fundida - CustomMessage("a molten dungeon pass", /*german*/"", /*french*/"le rêve fondu d'un prisonnier"), + CustomMessage("a molten dungeon pass", /*german*/"ein geschmolzener Dungeon-Pass", /*french*/"le rêve fondu d'un prisonnier"), // /*spanish*/un pase de una mazmorra fundida - CustomMessage("a molten lock remover", /*german*/"", /*french*/"un efface-serrure fondu"), + CustomMessage("a molten lock remover", /*german*/"ein geschmolzener Schlossentferner", /*french*/"un efface-serrure fondu"), // /*spanish*/un destructor de cerraduras fundida - CustomMessage("a molten lockpick", /*german*/"", /*french*/"un crochet à porte fondu")}); + CustomMessage("a molten lockpick", /*german*/"ein geschmolzener Dietrich", /*french*/"un crochet à porte fondu")}); // /*spanish*/una apertura portentosa fundida - hintTextTable[RHT_WATER_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Water Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Eau"), + hintTextTable[RHT_WATER_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Water Temple Small Key", /*german*/"ein kleiner Wassertempel-Schlüssel", /*french*/"une petite clé du Temple de l'Eau"), // /*spanish*/una llave pequeña del Templo del Agua { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a wet tool for unlocking", /*german*/"", /*french*/"un anti-porte humide"), + CustomMessage("a wet tool for unlocking", /*german*/"ein nasses Werkzeug zur Entschlüsselung", /*french*/"un anti-porte humide"), // /*spanish*/una clave de una entrada mojada - CustomMessage("a wet dungeon pass", /*german*/"", /*french*/"le rêve humide d'un prisonnier"), + CustomMessage("a wet dungeon pass", /*german*/"ein nasser Dungeon-Pass", /*french*/"le rêve humide d'un prisonnier"), // /*spanish*/un pase de una mazmorra mojada - CustomMessage("a wet lock remover", /*german*/"", /*french*/"un efface-serrure humide"), + CustomMessage("a wet lock remover", /*german*/"ein nasser Schlossentferner", /*french*/"un efface-serrure humide"), // /*spanish*/un destructor de cerraduras mojada - CustomMessage("a wet lockpick", /*german*/"", /*french*/"un crochet à porte humide")}); + CustomMessage("a wet lockpick", /*german*/"ein nasser Dietrich", /*french*/"un crochet à porte humide")}); // /*spanish*/una apertura portentosa mojada - hintTextTable[RHT_SPIRIT_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Spirit Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Esprit"), + hintTextTable[RHT_SPIRIT_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Spirit Temple Small Key", /*german*/"ein kleiner Geistertempel-Schlüssel", /*french*/"une petite clé du Temple de l'Esprit"), // /*spanish*/una llave pequeña del Templo del Espíritu { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a sandy tool for unlocking", /*german*/"", /*french*/"un anti-porte sableux"), + CustomMessage("a sandy tool for unlocking", /*german*/"ein sandiges Werkzeug zur Entschlüsselung", /*french*/"un anti-porte sableux"), // /*spanish*/una clave de una entrada arenosa - CustomMessage("a sandy dungeon pass", /*german*/"", /*french*/"le rêve sableux d'un prisonnier"), + CustomMessage("a sandy dungeon pass", /*german*/"ein sandiger Dungeon-Pass", /*french*/"le rêve sableux d'un prisonnier"), // /*spanish*/un pase de una mazmorra arenosa - CustomMessage("a sandy lock remover", /*german*/"", /*french*/"un efface-serrure sableux"), + CustomMessage("a sandy lock remover", /*german*/"ein sandiger Schlossentferner", /*french*/"un efface-serrure sableux"), // /*spanish*/un destructor de cerraduras arenosa - CustomMessage("a sandy lockpick", /*german*/"", /*french*/"un crochet à porte sableux")}); + CustomMessage("a sandy lockpick", /*german*/"ein sandiger Dietrich", /*french*/"un crochet à porte sableux")}); // /*spanish*/una apertura portentosa arenosa - hintTextTable[RHT_SHADOW_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Shadow Temple Small Key", /*german*/"", /*french*/"une petite clé du Temple de l'Ombre"), + hintTextTable[RHT_SHADOW_TEMPLE_SMALL_KEY] = HintText(CustomMessage("a Shadow Temple Small Key", /*german*/"ein kleiner Schattentempel-Schlüssel", /*french*/"une petite clé du Temple de l'Ombre"), // /*spanish*/una llave pequeña del Templo de las Sombras { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a creepy tool for unlocking", /*german*/"", /*french*/"un anti-porte sinistre"), + CustomMessage("a creepy tool for unlocking", /*german*/"ein gruseliges Werkzeug zur Entschlüsselung", /*french*/"un anti-porte sinistre"), // /*spanish*/una clave de una entrada siniestra:a - CustomMessage("a creepy dungeon pass", /*german*/"", /*french*/"le rêve sinistre d'un prisonnier"), + CustomMessage("a creepy dungeon pass", /*german*/"ein gruseliger Dungeon-Pass", /*french*/"le rêve sinistre d'un prisonnier"), // /*spanish*/un pase de una mazmorra siniestra:a - CustomMessage("a creepy lock remover", /*german*/"", /*french*/"un efface-serrure sinistre"), + CustomMessage("a creepy lock remover", /*german*/"ein gruseliger Schlossentferner", /*french*/"un efface-serrure sinistre"), // /*spanish*/un destructor de cerraduras siniestra:a - CustomMessage("a creepy lockpick", /*german*/"", /*french*/"un crochet à porte sinistre")}); + CustomMessage("a creepy lockpick", /*german*/"ein gruseliger Dietrich", /*french*/"un crochet à porte sinistre")}); // /*spanish*/una apertura portentosa siniestra:a - hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Training Ground Small Key", /*german*/"", /*french*/"une petite clé du Gymnase Gerudo"), + hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Training Ground Small Key", /*german*/"ein kleiner Schlüssel des Gerudo-Trainingsgeländes", /*french*/"une petite clé du Gymnase Gerudo"), // /*spanish*/una llave pequeña del Centro de Instrucción Gerudo { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a labyrinthian tool for unlocking", /*german*/"", /*french*/"un anti-porte labyrinthique"), + CustomMessage("a labyrinthian tool for unlocking", /*german*/"ein labyrinthisches Werkzeug zur Entschlüsselung", /*french*/"un anti-porte labyrinthique"), // /*spanish*/una clave de una entrada laberíntica - CustomMessage("a labyrinthian dungeon pass", /*german*/"", /*french*/"le rêve labyrinthique d'un prisonnier"), + CustomMessage("a labyrinthian dungeon pass", /*german*/"ein labyrinthischer Dungeon-Pass", /*french*/"le rêve labyrinthique d'un prisonnier"), // /*spanish*/un pase de una mazmorra laberíntica - CustomMessage("a labyrinthian lock remover", /*german*/"", /*french*/"un efface-serrure labyrinthique"), + CustomMessage("a labyrinthian lock remover", /*german*/"ein labyrinthischer Schlossentferner", /*french*/"un efface-serrure labyrinthique"), // /*spanish*/un destructor de cerraduras laberíntica - CustomMessage("a labyrinthian lockpick", /*german*/"", /*french*/"un crochet à porte labyrinthique")}); + CustomMessage("a labyrinthian lockpick", /*german*/"ein labyrinthischer Dietrich", /*french*/"un crochet à porte labyrinthique")}); // /*spanish*/una apertura portentosa laberíntica - hintTextTable[RHT_GERUDO_FORTRESS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Fortress Small Key", /*german*/"", /*french*/"une petite clé de la Repaire des Voleurs"), + hintTextTable[RHT_GERUDO_FORTRESS_SMALL_KEY] = HintText(CustomMessage("a Gerudo Fortress Small Key", /*german*/"ein kleiner Schlüssel für die Gerudo-Festung", /*french*/"une petite clé de la Repaire des Voleurs"), // /*spanish*/una llave pequeña de la Fortaleza Gerudo { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("an imprisoned tool for unlocking", /*german*/"", /*french*/"un anti-porte emprisonné"), + CustomMessage("an imprisoned tool for unlocking", /*german*/"ein gefangenes Werkzeug zur Entschlüsselung", /*french*/"un anti-porte emprisonné"), // /*spanish*/una clave de una entrada encarcelada - CustomMessage("an imprisoned dungeon pass", /*german*/"", /*french*/"le rêve emprisonné d'un prisonnier"), + CustomMessage("an imprisoned dungeon pass", /*german*/"ein gefangener Dungeon-Pass", /*french*/"le rêve emprisonné d'un prisonnier"), // /*spanish*/un pase de una mazmorra encarcelada - CustomMessage("an imprisoned lock remover", /*german*/"", /*french*/"un efface-serrure emprisonné"), + CustomMessage("an imprisoned lock remover", /*german*/"ein gefangener Schlossentferner", /*french*/"un efface-serrure emprisonné"), // /*spanish*/un destructor de cerraduras encarcelada - CustomMessage("an imprisoned lockpick", /*german*/"", /*french*/"un crochet à porte emprisonné")}); + CustomMessage("an imprisoned lockpick", /*german*/"ein gefangener Dietrich", /*french*/"un crochet à porte emprisonné")}); // /*spanish*/una apertura portentosa encarcelada - hintTextTable[RHT_BOTTOM_OF_THE_WELL_SMALL_KEY] = HintText(CustomMessage("a Bottom of the Well Small Key", /*german*/"", /*french*/"une petite clé du fond du Puits"), + hintTextTable[RHT_BOTTOM_OF_THE_WELL_SMALL_KEY] = HintText(CustomMessage("a Bottom of the Well Small Key", /*german*/"ein kleiner Schlüssel des Grund des Brunnens", /*french*/"une petite clé du fond du Puits"), // /*spanish*/una llave pequeña del Fondo del pozo { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a moldy tool for unlocking", /*german*/"", /*french*/"un anti-porte moisi"), + CustomMessage("a moldy tool for unlocking", /*german*/"ein schimmeliges Werkzeug zur Entschlüsselung", /*french*/"un anti-porte moisi"), // /*spanish*/una clave de una entrada mohosa - CustomMessage("a moldy dungeon pass", /*german*/"", /*french*/"le rêve moisi d'un prisonnier"), + CustomMessage("a moldy dungeon pass", /*german*/"ein schimmeliger Dungeon-Pass", /*french*/"le rêve moisi d'un prisonnier"), // /*spanish*/un pase de una mazmorra mohosa - CustomMessage("a moldy lock remover", /*german*/"", /*french*/"un efface-serrure moisi"), + CustomMessage("a moldy lock remover", /*german*/"ein schimmeliger Schlossentferner", /*french*/"un efface-serrure moisi"), // /*spanish*/un destructor de cerraduras mohosa - CustomMessage("a moldy lockpick", /*german*/"", /*french*/"un crochet à porte moisi")}); + CustomMessage("a moldy lockpick", /*german*/"ein schimmeliger Dietrich", /*french*/"un crochet à porte moisi")}); // /*spanish*/una apertura portentosa mohosa - hintTextTable[RHT_GANONS_CASTLE_SMALL_KEY] = HintText(CustomMessage("a Ganon's Castle Small Key", /*german*/"", /*french*/"une petite clé du Château de Ganon"), + hintTextTable[RHT_GANONS_CASTLE_SMALL_KEY] = HintText(CustomMessage("a Ganon's Castle Small Key", /*german*/"ein kleiner Schlüssel für Ganons Schloß", /*french*/"une petite clé du Château de Ganon"), // /*spanish*/una llave pequeña del Castillo de Ganon { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a final tool for unlocking", /*german*/"", /*french*/"un anti-porte final"), + CustomMessage("a final tool for unlocking", /*german*/"ein finales Werkzeug zur Entschlüsselung", /*french*/"un anti-porte final"), // /*spanish*/una clave de una entrada final - CustomMessage("a final dungeon pass", /*german*/"", /*french*/"le rêve final d'un prisonnier"), + CustomMessage("a final dungeon pass", /*german*/"ein finaler Dungeon-Pass", /*french*/"le rêve final d'un prisonnier"), // /*spanish*/un pase de una mazmorra final - CustomMessage("a final lock remover", /*german*/"", /*french*/"un efface-serrure final"), + CustomMessage("a final lock remover", /*german*/"ein finaler Schlossentferner", /*french*/"un efface-serrure final"), // /*spanish*/un destructor de cerraduras final - CustomMessage("a final lockpick", /*german*/"", /*french*/"un crochet à porte final")}); + CustomMessage("a final lockpick", /*german*/"ein finaler Dietrich", /*french*/"un crochet à porte final")}); // /*spanish*/una apertura portentosa final - hintTextTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText(CustomMessage("a Forest Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de la Forêt"), + hintTextTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText(CustomMessage("a Forest Temple Key Ring", /*german*/"ein Schlüsselbund des Waldtempels", /*french*/"un trousseau de clés du Temple de la Forêt"), // /*spanish*/un llavero del Templo del Bosque { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a sylvan toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sylvestres"), + CustomMessage("a sylvan toolbox for unlocking", /*german*/"eine waldige Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes sylvestres"), // /*spanish*/un conjunto silvestre de cerrajero - CustomMessage("a sylvan dungeon season pass", /*german*/"", /*french*/"les rêves sylvestres d'un prisonnier"), + CustomMessage("a sylvan dungeon season pass", /*german*/"ein waldiger Dungeon-Season-Pass", /*french*/"les rêves sylvestres d'un prisonnier"), // /*spanish*/un pase vip de mazmorras silvestre - CustomMessage("a sylvan jingling ring", /*german*/"", /*french*/"des efface-serrures sylvestres"), + CustomMessage("a sylvan jingling ring", /*german*/"ein waldiger Multifunktionsschlüssel", /*french*/"des efface-serrures sylvestres"), // /*spanish*/una cadena multiusos silvestre - CustomMessage("a sylvan skeleton key", /*german*/"", /*french*/"des crochets à porte sylvestres")}); + CustomMessage("a sylvan skeleton key", /*german*/"ein waldiger Skelettschlüssel", /*french*/"des crochets à porte sylvestres")}); // /*spanish*/un anillo silvestre contra cerrojos - hintTextTable[RHT_FIRE_TEMPLE_KEY_RING] = HintText(CustomMessage("a Fire Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple du Feu"), + hintTextTable[RHT_FIRE_TEMPLE_KEY_RING] = HintText(CustomMessage("a Fire Temple Key Ring", /*german*/"ein Schlüsselbund des Feuertempels", /*french*/"un trousseau de clés du Temple du Feu"), // /*spanish*/un llavero del Templo del Fuego { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a molten toolbox for unlocking", /*german*/"", /*french*/"des anti-portes fondus"), + CustomMessage("a molten toolbox for unlocking", /*german*/"eine geschmolzene Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes fondus"), // /*spanish*/un conjunto fundido de cerrajero - CustomMessage("a molten dungeon season pass", /*german*/"", /*french*/"les rêves fondus d'un prisonnier"), + CustomMessage("a molten dungeon season pass", /*german*/"ein geschmolzener Dungeon-Season-Pass", /*french*/"les rêves fondus d'un prisonnier"), // /*spanish*/un pase vip de mazmorras fundido - CustomMessage("a molten jingling ring", /*german*/"", /*french*/"des efface-serrures fondus"), + CustomMessage("a molten jingling ring", /*german*/"ein geschmolzener Multifunktionsschlüssel", /*french*/"des efface-serrures fondus"), // /*spanish*/una cadena multiusos fundida - CustomMessage("a molten skeleton key", /*german*/"", /*french*/"des crochets à porte fondus")}); + CustomMessage("a molten skeleton key", /*german*/"ein geschmolzener Skelettschlüssel", /*french*/"des crochets à porte fondus")}); // /*spanish*/un anillo fundido contra cerrojos - hintTextTable[RHT_WATER_TEMPLE_KEY_RING] = HintText(CustomMessage("a Water Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Eau"), + hintTextTable[RHT_WATER_TEMPLE_KEY_RING] = HintText(CustomMessage("a Water Temple Key Ring", /*german*/"ein Schlüsselbund des Wassertempels", /*french*/"un trousseau de clés du Temple de l'Eau"), // /*spanish*/un llavero del Templo del Agua { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a wet toolbox for unlocking", /*german*/"", /*french*/"des anti-portes humides"), + CustomMessage("a wet toolbox for unlocking", /*german*/"eine nasse Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes humides"), // /*spanish*/un conjunto abisal de cerrajero - CustomMessage("a wet dungeon season pass", /*german*/"", /*french*/"les rêves humides d'un prisonnier"), + CustomMessage("a wet dungeon season pass", /*german*/"ein nasser Dungeon-Season-Pass", /*french*/"les rêves humides d'un prisonnier"), // /*spanish*/un pase vip de mazmorras abisal - CustomMessage("a wet jingling ring", /*german*/"", /*french*/"des efface-serrures humides"), + CustomMessage("a wet jingling ring", /*german*/"ein nasser Multifunktionsschlüssel", /*french*/"des efface-serrures humides"), // /*spanish*/una cadena multiusos abisal - CustomMessage("a wet skeleton key", /*german*/"", /*french*/"des crochets à porte humides")}); + CustomMessage("a wet skeleton key", /*german*/"ein nasser Skelettschlüssel", /*french*/"des crochets à porte humides")}); // /*spanish*/un anillo abisal contra cerrojos - hintTextTable[RHT_SPIRIT_TEMPLE_KEY_RING] = HintText(CustomMessage("a Spirit Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Esprit"), + hintTextTable[RHT_SPIRIT_TEMPLE_KEY_RING] = HintText(CustomMessage("a Spirit Temple Key Ring", /*german*/"ein Schlüsselbund des Geistertempels", /*french*/"un trousseau de clés du Temple de l'Esprit"), // /*spanish*/un llavero del Templo del Espíritu { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a sandy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sableux"), + CustomMessage("a sandy toolbox for unlocking", /*german*/"eine sandige Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes sableux"), // /*spanish*/un conjunto arenoso de cerrajero - CustomMessage("a sandy dungeon season pass", /*german*/"", /*french*/"les rêves sableux d'un prisonnier"), + CustomMessage("a sandy dungeon season pass", /*german*/"ein sandiger Dungeon-Season-Pass", /*french*/"les rêves sableux d'un prisonnier"), // /*spanish*/un pase vip de mazmorras arenoso - CustomMessage("a sandy jingling ring", /*german*/"", /*french*/"des efface-serrures sableux"), + CustomMessage("a sandy jingling ring", /*german*/"ein sandiger Multifunktionsschlüssel", /*french*/"des efface-serrures sableux"), // /*spanish*/una cadena multiusos arenosa - CustomMessage("a sandy skeleton key", /*german*/"", /*french*/"des crochets à porte sableux")}); + CustomMessage("a sandy skeleton key", /*german*/"ein sandiger Skelettschlüssel", /*french*/"des crochets à porte sableux")}); // /*spanish*/un anillo arenoso contra cerrojos - hintTextTable[RHT_SHADOW_TEMPLE_KEY_RING] = HintText(CustomMessage("a Shadow Temple Key Ring", /*german*/"", /*french*/"un trousseau de clés du Temple de l'Ombre"), + hintTextTable[RHT_SHADOW_TEMPLE_KEY_RING] = HintText(CustomMessage("a Shadow Temple Key Ring", /*german*/"ein Schlüsselbund des Schattentempels", /*french*/"un trousseau de clés du Temple de l'Ombre"), // /*spanish*/un llavero del Templo de las Sombras { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a creepy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes sinistres"), + CustomMessage("a creepy toolbox for unlocking", /*german*/"eine gruselige Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes sinistres"), // /*spanish*/un conjunto tenebroso de cerrajero - CustomMessage("a creepy dungeon season pass", /*german*/"", /*french*/"les rêves sinistres d'un prisonnier"), + CustomMessage("a creepy dungeon season pass", /*german*/"ein gruseliger Dungeon-Season-Pass", /*french*/"les rêves sinistres d'un prisonnier"), // /*spanish*/un pase vip de mazmorras tenebroso - CustomMessage("a creepy jingling ring", /*german*/"", /*french*/"des efface-serrures sinistres"), + CustomMessage("a creepy jingling ring", /*german*/"ein gruseliger Multifunktionsschlüssel", /*french*/"des efface-serrures sinistres"), // /*spanish*/una cadena multiusos tenebrosa - CustomMessage("a creepy skeleton key", /*german*/"", /*french*/"des crochets à porte sinistres")}); + CustomMessage("a creepy skeleton key", /*german*/"ein gruseliger Skelettschlüssel", /*french*/"des crochets à porte sinistres")}); // /*spanish*/un anillo tenebroso contra cerrojos - hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_KEY_RING] = HintText(CustomMessage("a Gerudo Training Ground Key Ring", /*german*/"", /*french*/"un trousseau de clés du Gymnase Gerudo"), + hintTextTable[RHT_GERUDO_TRAINING_GROUNDS_KEY_RING] = HintText(CustomMessage("a Gerudo Training Ground Key Ring", /*german*/"ein Schlüsselbund des Gerudo-Trainingsgeländes", /*french*/"un trousseau de clés du Gymnase Gerudo"), // /*spanish*/un llavero del Centro de Instrucción Gerudo { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a labyrinthian toolbox for unlocking", /*german*/"", /*french*/"des anti-portes labyrinthiques"), + CustomMessage("a labyrinthian toolbox for unlocking", /*german*/"eine labyrinthische Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes labyrinthiques"), // /*spanish*/un conjunto laberíntico de cerrajero - CustomMessage("a labyrinthian dungeon season pass", /*german*/"", /*french*/"les rêves labyrinthiques d'un prisonnier"), + CustomMessage("a labyrinthian dungeon season pass", /*german*/"ein labyrinthischer Dungeon-Season-Pass", /*french*/"les rêves labyrinthiques d'un prisonnier"), // /*spanish*/un pase vip de mazmorras laberíntico - CustomMessage("a labyrinthian jingling ring", /*german*/"", /*french*/"des efface-serrures labyrinthiques"), + CustomMessage("a labyrinthian jingling ring", /*german*/"ein labyrinthischer Multifunktionsschlüssel", /*french*/"des efface-serrures labyrinthiques"), // /*spanish*/una cadena multiusos laberíntica - CustomMessage("a labyrinthian skeleton key", /*german*/"", /*french*/"des crochets à porte labyrinthiques")}); + CustomMessage("a labyrinthian skeleton key", /*german*/"ein labyrinthischer Skelettschlüssel", /*french*/"des crochets à porte labyrinthiques")}); // /*spanish*/un anillo laberíntico contra cerrojos - hintTextTable[RHT_GERUDO_FORTRESS_KEY_RING] = HintText(CustomMessage("a Gerudo Fortress Key Ring", /*german*/"", /*french*/"un trousseau de clés de la Repaire des Voleurs"), + hintTextTable[RHT_GERUDO_FORTRESS_KEY_RING] = HintText(CustomMessage("a Gerudo Fortress Key Ring", /*german*/"ein Schlüsselbund der Gerudo-Festung", /*french*/"un trousseau de clés de la Repaire des Voleurs"), // /*spanish*/un llavero de la Fortaleza Gerudo { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("an imprisoned toolbox for unlocking", /*german*/"", /*french*/"des anti-portes emprisonnés"), + CustomMessage("an imprisoned toolbox for unlocking", /*german*/"eine gefangene Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes emprisonnés"), // /*spanish*/un conjunto enjaulado de cerrajero - CustomMessage("an imprisoned dungeon season pass", /*german*/"", /*french*/"les rêves emprisonnés d'un prisonnier"), + CustomMessage("an imprisoned dungeon season pass", /*german*/"ein gefangener Dungeon-Season-Pass", /*french*/"les rêves emprisonnés d'un prisonnier"), // /*spanish*/un pase vip de una mazmorra enjaulado - CustomMessage("an imprisoned jingling ring", /*german*/"", /*french*/"des efface-serrures emprisonnés"), + CustomMessage("an imprisoned jingling ring", /*german*/"ein gefangener Multifunktionsschlüssel", /*french*/"des efface-serrures emprisonnés"), // /*spanish*/una cadena multiusos enjaulada - CustomMessage("an imprisoned skeleton key", /*german*/"", /*french*/"des crochets à porte emprisonnés")}); + CustomMessage("an imprisoned skeleton key", /*german*/"ein gefangener Skelettschlüssel", /*french*/"des crochets à porte emprisonnés")}); // /*spanish*/un anillo enjaulado contra cerrojos - hintTextTable[RHT_BOTTOM_OF_THE_WELL_KEY_RING] = HintText(CustomMessage("a Bottom of the Well Key Ring", /*german*/"", /*french*/"un trousseau de clés du fond du Puits"), + hintTextTable[RHT_BOTTOM_OF_THE_WELL_KEY_RING] = HintText(CustomMessage("a Bottom of the Well Key Ring", /*german*/"ein Schlüsselbund des Grund des Brunnens", /*french*/"un trousseau de clés du fond du Puits"), // /*spanish*/un llavero del Fondo del pozo { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a moldy toolbox for unlocking", /*german*/"", /*french*/"des anti-portes moisis"), + CustomMessage("a moldy toolbox for unlocking", /*german*/"eine schimmelige Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes moisis"), // /*spanish*/un conjunto subterráneo de cerrajero - CustomMessage("a moldy dungeon season pass", /*german*/"", /*french*/"les rêves moisis d'un prisonnier"), + CustomMessage("a moldy dungeon season pass", /*german*/"ein schimmeliger Dungeon-Season-Pass", /*french*/"les rêves moisis d'un prisonnier"), // /*spanish*/un pase vip de una mazmorra subterráneo - CustomMessage("a moldy jingling ring", /*german*/"", /*french*/"des efface-serrures moisis"), + CustomMessage("a moldy jingling ring", /*german*/"ein schimmeliger Multifunktionsschlüssel", /*french*/"des efface-serrures moisis"), // /*spanish*/una cadena multiusos subterránea - CustomMessage("a moldy skeleton key", /*german*/"", /*french*/"des crochets à porte moisis")}); + CustomMessage("a moldy skeleton key", /*german*/"ein schimmeliger Skelettschlüssel", /*french*/"des crochets à porte moisis")}); // /*spanish*/un anillo subterráneo contra cerrojos - hintTextTable[RHT_GANONS_CASTLE_KEY_RING] = HintText(CustomMessage("a Ganon's Castle Key Ring", /*german*/"", /*french*/"un trousseau de clés du Château de Ganon"), + hintTextTable[RHT_GANONS_CASTLE_KEY_RING] = HintText(CustomMessage("a Ganon's Castle Key Ring", /*german*/"ein Schlüsselbund von Ganons Schloß", /*french*/"un trousseau de clés du Château de Ganon"), // /*spanish*/un llavero del Castillo de Ganon { - CustomMessage("a key ring", /*german*/"", /*french*/"un trousseau de clés") + CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés") // /*spanish*/un llavero }, { - CustomMessage("a final toolbox for unlocking", /*german*/"", /*french*/"des anti-portes finaux"), + CustomMessage("a final toolbox for unlocking", /*german*/"eine finale Werkzeugkiste zur Entschlüsselung", /*french*/"des anti-portes finaux"), // /*spanish*/un conjunto decisivo de cerrajero - CustomMessage("a final dungeon season pass", /*german*/"", /*french*/"les rêves finaux d'un prisonnier"), + CustomMessage("a final dungeon season pass", /*german*/"ein finaler Dungeon-Season-Pass", /*french*/"les rêves finaux d'un prisonnier"), // /*spanish*/un pase vip de una mazmorra decisivo - CustomMessage("a final jingling ring", /*german*/"", /*french*/"des efface-serrures finaux"), + CustomMessage("a final jingling ring", /*german*/"ein finaler Multifunktionsschlüssel", /*french*/"des efface-serrures finaux"), // /*spanish*/una cadena multiusos decisiva - CustomMessage("a final skeleton key", /*german*/"", /*french*/"des crochets à porte finaux")}); + CustomMessage("a final skeleton key", /*german*/"ein finaler Skelettschlüssel", /*french*/"des crochets à porte finaux")}); // /*spanish*/un anillo decisivo multiusos - hintTextTable[RHT_TREASURE_GAME_SMALL_KEY] = HintText(CustomMessage("a Treasure Chest Shop Small Key", /*german*/"", /*french*/"une petite clé de la chasse aux trésors"), + hintTextTable[RHT_TREASURE_GAME_SMALL_KEY] = HintText(CustomMessage("a Treasure Chest Shop Small Key", /*german*/"ein kleiner Schlüssel des Schatztruhenladens", /*french*/"une petite clé de la chasse aux trésors"), // /*spanish*/una llave pequeña del Cofre del Tesoro { - CustomMessage("a small key", /*german*/"", /*french*/"une petite clé") + CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé") // /*spanish*/una llave pequeña }, { - CustomMessage("a gambler's tool for unlocking", /*german*/"", /*french*/"un anti-porte de parieur"), + CustomMessage("a gambler's tool for unlocking", /*german*/"ein Spieler-Werkzeug zur Entschlüsselung", /*french*/"un anti-porte de parieur"), // /*spanish*/una clave de un juego de azar - CustomMessage("a gambler's dungeon pass", /*german*/"", /*french*/"le rêve d'un prisonnier parieur"), + CustomMessage("a gambler's dungeon pass", /*german*/"ein Spieler-Dungeon-Pass", /*french*/"le rêve d'un prisonnier parieur"), // /*spanish*/un pase de un juego de azar - CustomMessage("a gambler's lock remover", /*german*/"", /*french*/"un efface-serrure de parieur"), + CustomMessage("a gambler's lock remover", /*german*/"ein Spieler-Schlossentferner", /*french*/"un efface-serrure de parieur"), // /*spanish*/un destructor de cerraduras del juego de azar - CustomMessage("a gambler's lockpick", /*german*/"", /*french*/"un crochet à serrure de parieur")}); + CustomMessage("a gambler's lockpick", /*german*/"ein Spieler-Dietrich", /*french*/"un crochet à serrure de parieur")}); // /*spanish*/una apertura portentosa del juego de azar - hintTextTable[RHT_KOKIRI_EMERALD] = HintText(CustomMessage("the Kokiri Emerald", /*german*/"", /*french*/"l'Émeraude Kokiri"), + hintTextTable[RHT_KOKIRI_EMERALD] = HintText(CustomMessage("the Kokiri Emerald", /*german*/"der Kokiri-Smaragd", /*french*/"l'Émeraude Kokiri"), // /*spanish*/la Esmeralda de los Kokiri { - CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + CustomMessage("a spiritual stone", /*german*/"ein spiritueller Stein", /*french*/"une Pierre Ancestrale") // /*spanish*/una piedra espiritual }, { - CustomMessage("a green stone", /*german*/"", /*french*/"une pierre verte"), + CustomMessage("a green stone", /*german*/"ein grüner Stein", /*french*/"une pierre verte"), // /*spanish*/una piedra verde - CustomMessage("a gift before death", /*german*/"", /*french*/"le dernier souffle d'un arbre")}); + CustomMessage("a gift before death", /*german*/"ein Geschenk vor dem Tod", /*french*/"le dernier souffle d'un arbre")}); // /*spanish*/un obsequio testamentario - hintTextTable[RHT_GORON_RUBY] = HintText(CustomMessage("the Goron Ruby", /*german*/"", /*french*/"le Rubis Goron"), + hintTextTable[RHT_GORON_RUBY] = HintText(CustomMessage("the Goron Ruby", /*german*/"der Goronen-Rubin", /*french*/"le Rubis Goron"), // /*spanish*/el Rubí de los Goron { - CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + CustomMessage("a spiritual stone", /*german*/"ein spiritueller Stein", /*french*/"une Pierre Ancestrale") // /*spanish*/una piedra espiritual }, { - CustomMessage("a red stone", /*german*/"", /*french*/"une pierre rouge"), + CustomMessage("a red stone", /*german*/"ein roter Stein", /*french*/"une pierre rouge"), // /*spanish*/una piedra carmín - CustomMessage("sworn brotherhood", /*german*/"", /*french*/"un serment de fraternité")}); + CustomMessage("sworn brotherhood", /*german*/"verschworene Bruderschaft", /*french*/"un serment de fraternité")}); // /*spanish*/el juramento de hermanos de sangre - hintTextTable[RHT_ZORA_SAPPHIRE] = HintText(CustomMessage("the Zora Sapphire", /*german*/"", /*french*/"le Saphir Zora"), + hintTextTable[RHT_ZORA_SAPPHIRE] = HintText(CustomMessage("the Zora Sapphire", /*german*/"der Zora-Saphir", /*french*/"le Saphir Zora"), // /*spanish*/el Zafiro de los Zora { - CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale") + CustomMessage("a spiritual stone", /*german*/"ein spiritueller Stein", /*french*/"une Pierre Ancestrale") // /*spanish*/una piedra espiritual }, { - CustomMessage("a blue stone", /*german*/"", /*french*/"une pierre bleue"), + CustomMessage("a blue stone", /*german*/"ein blauer Stein", /*french*/"une pierre bleue"), // /*spanish*/una piedra celeste - CustomMessage("an engagement gift", /*german*/"", /*french*/"un cadeau de mariage")}); + CustomMessage("an engagement gift", /*german*/"ein Verlobungsgeschenk", /*french*/"un cadeau de mariage")}); // /*spanish*/un regalo de compromiso - hintTextTable[RHT_FOREST_MEDALLION] = HintText(CustomMessage("the Forest Medallion", /*german*/"", /*french*/"le Médaillon de la Forêt"), + hintTextTable[RHT_FOREST_MEDALLION] = HintText(CustomMessage("the Forest Medallion", /*german*/"Amulett des Waldes", /*french*/"le Médaillon de la Forêt"), // /*spanish*/el Medallón del Bosque { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("a green coin", /*german*/"", /*french*/"une pièce verte"), + CustomMessage("a green coin", /*german*/"eine grüne Münze", /*french*/"une pièce verte"), // /*spanish*/una moneda esmeralda - CustomMessage("Saria's friendship", /*german*/"", /*french*/"l'amitié de Saria")}); + CustomMessage("Saria's friendship", /*german*/"Salias Freundschaft", /*french*/"l'amitié de Saria")}); // /*spanish*/la amistad de Saria - hintTextTable[RHT_FIRE_MEDALLION] = HintText(CustomMessage("the Fire Medallion", /*german*/"", /*french*/"le Médaillon du Feu"), + hintTextTable[RHT_FIRE_MEDALLION] = HintText(CustomMessage("the Fire Medallion", /*german*/"Amulett des Feuers", /*french*/"le Médaillon du Feu"), // /*spanish*/el Medallón del Fuego { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("a red coin", /*german*/"", /*french*/"une pièce rouge"), + CustomMessage("a red coin", /*german*/"eine rote Münze", /*french*/"une pièce rouge"), // /*spanish*/una moneda rubí - CustomMessage("Darunia's power", /*german*/"", /*french*/"la fraternité de Darunia")}); + CustomMessage("Darunia's power", /*german*/"Darunias Kraft", /*french*/"la fraternité de Darunia")}); // /*spanish*/la fraternidad de Darunia - hintTextTable[RHT_WATER_MEDALLION] = HintText(CustomMessage("the Water Medallion", /*german*/"", /*french*/"le Médaillon de l'Eau"), + hintTextTable[RHT_WATER_MEDALLION] = HintText(CustomMessage("the Water Medallion", /*german*/"Amulett des Wassers", /*french*/"le Médaillon de l'Eau"), // /*spanish*/el Medallón del Agua { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("a blue coin", /*german*/"", /*french*/"une pièce bleue"), + CustomMessage("a blue coin", /*german*/"eine blaue Münze", /*french*/"une pièce bleue"), // /*spanish*/una moneda zafiro - CustomMessage("Ruto's power", /*german*/"", /*french*/"l'amour de Ruto")}); + CustomMessage("Ruto's power", /*german*/"Rutos Macht", /*french*/"l'amour de Ruto")}); // /*spanish*/el amor de Ruto - hintTextTable[RHT_SPIRIT_MEDALLION] = HintText(CustomMessage("the Spirit Medallion", /*german*/"", /*french*/"le Médaillon de l'Esprit"), + hintTextTable[RHT_SPIRIT_MEDALLION] = HintText(CustomMessage("the Spirit Medallion", /*german*/"Amulett der Geister", /*french*/"le Médaillon de l'Esprit"), // /*spanish*/el Medallón del Espíritu { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("an orange coin", /*german*/"", /*french*/"une pièce orange"), + CustomMessage("an orange coin", /*german*/"eine orange Münze", /*french*/"une pièce orange"), // /*spanish*/una moneda ámbar - CustomMessage("Nabooru's power", /*german*/"", /*french*/"le respect de Nabooru")}); + CustomMessage("Nabooru's power", /*german*/"Naborus Macht", /*french*/"le respect de Nabooru")}); // /*spanish*/el respeto de Nabooru - hintTextTable[RHT_SHADOW_MEDALLION] = HintText(CustomMessage("the Shadow Medallion", /*german*/"", /*french*/"le Médaillon de l'Ombre"), + hintTextTable[RHT_SHADOW_MEDALLION] = HintText(CustomMessage("the Shadow Medallion", /*german*/"Amulett des Schattens", /*french*/"le Médaillon de l'Ombre"), // /*spanish*/el Medallón de la Sombra { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("a purple coin", /*german*/"", /*french*/"une pièce pourpre"), + CustomMessage("a purple coin", /*german*/"eine violette Münze", /*french*/"une pièce pourpre"), // /*spanish*/una moneda malva - CustomMessage("Impa's power", /*german*/"", /*french*/"la confiance d'Impa")}); + CustomMessage("Impa's power", /*german*/"Impas Macht", /*french*/"la confiance d'Impa")}); // /*spanish*/la confianza de Impa - hintTextTable[RHT_LIGHT_MEDALLION] = HintText(CustomMessage("the Light Medallion", /*german*/"", /*french*/"le Médaillon de la Lumière"), + hintTextTable[RHT_LIGHT_MEDALLION] = HintText(CustomMessage("the Light Medallion", /*german*/"Amulett des Lichts", /*french*/"le Médaillon de la Lumière"), // /*spanish*/el Medallón de la Luz { - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon") + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon") // /*spanish*/un medallón }, { - CustomMessage("a yellow coin", /*german*/"", /*french*/"une pièce jaune"), + CustomMessage("a yellow coin", /*german*/"eine gelbe Münze", /*french*/"une pièce jaune"), // /*spanish*/una moneda resplandeciente - CustomMessage("Rauru's power", /*german*/"", /*french*/"la foi de Rauru")}); + CustomMessage("Rauru's power", /*german*/"Raurus Macht", /*french*/"la foi de Rauru")}); // /*spanish*/la fe de Rauru - hintTextTable[RHT_RECOVERY_HEART] = HintText(CustomMessage("a Recovery Heart", /*german*/"", /*french*/"un coeur de vie"), + hintTextTable[RHT_RECOVERY_HEART] = HintText(CustomMessage("a Recovery Heart", /*german*/"ein Herz", /*french*/"un coeur de vie"), // /*spanish*/un corazón { - CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + CustomMessage("something heart-shaped", /*german*/"etwas Herzförmiges", /*french*/"une chose en forme de coeur") // /*spanish*/algo con forma de corazón }, { - CustomMessage("a free heal", /*german*/"", /*french*/"un bec-au-bobo"), + CustomMessage("a free heal", /*german*/"eine kostenlose Heilung", /*french*/"un bec-au-bobo"), // /*spanish*/una cura de regalo - CustomMessage("a hearty meal", /*german*/"", /*french*/"un petit amour"), + CustomMessage("a hearty meal", /*german*/"ein herzhaftes Mahl", /*french*/"un petit amour"), // /*spanish*/una sanación romántica - CustomMessage("a Band-Aid", /*german*/"", /*french*/"un diachylon")}); + CustomMessage("a Band-Aid", /*german*/"ein Wundpflaster", /*french*/"un diachylon")}); // /*spanish*/un corazoncito sanador - hintTextTable[RHT_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert"), + hintTextTable[RHT_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"ein grüner Rubin", /*french*/"un rubis vert"), // /*spanish*/una rupia verde { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("a unique coin", /*german*/"", /*french*/"un rubis bien mérité"), + CustomMessage("a unique coin", /*german*/"eine einzigartige Münze", /*french*/"un rubis bien mérité"), // /*spanish*/una singular moneda - CustomMessage("a penny", /*german*/"", /*french*/"un sou"), + CustomMessage("a penny", /*german*/"ein Pfennig", /*french*/"un sou"), // /*spanish*/un peso hyliano - CustomMessage("a green gem", /*german*/"", /*french*/"un joyau vert")}); + CustomMessage("a green gem", /*german*/"ein grüner Edelstein", /*french*/"un joyau vert")}); // /*spanish*/una gema verde - hintTextTable[RHT_GREG_RUPEE] = HintText(CustomMessage("Greg", /*german*/"", /*french*/"Greg"), + hintTextTable[RHT_GREG_RUPEE] = HintText(CustomMessage("Greg", /*german*/"Greg", /*french*/"Greg"), // /*spanish*/Greg { - CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert") + CustomMessage("a Green Rupee", /*german*/"ein grüner Rubin", /*french*/"un rubis vert") // /*spanish*/una rupia verde }, { - CustomMessage("an old friend", /*german*/"", /*french*/"Greg"), + CustomMessage("an old friend", /*german*/"ein alter Freund", /*french*/"Greg"), // /*spanish*/Greg - CustomMessage("a glorious gem", /*german*/"", /*french*/"Greg")}); + CustomMessage("a glorious gem", /*german*/"ein glorioser Edelstein", /*french*/"Greg")}); // /*spanish*/Greg - hintTextTable[RHT_BLUE_RUPEE] = HintText(CustomMessage("a Blue Rupee", /*german*/"", /*french*/"un rubis bleu"), + hintTextTable[RHT_BLUE_RUPEE] = HintText(CustomMessage("a Blue Rupee", /*german*/"ein blauer Rubin", /*french*/"un rubis bleu"), // /*spanish*/una rupia azul { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("a common coin", /*german*/"", /*french*/"quelques sous"), + CustomMessage("a common coin", /*german*/"eine gewöhnliche Münze", /*french*/"quelques sous"), // /*spanish*/una moneda usual - CustomMessage("a blue gem", /*german*/"", /*french*/"un joyau bleu")}); + CustomMessage("a blue gem", /*german*/"ein blauer Edelstein", /*french*/"un joyau bleu")}); // /*spanish*/una gema azul - hintTextTable[RHT_RED_RUPEE] = HintText(CustomMessage("a Red Rupee", /*german*/"", /*french*/"un rubis rouge"), + hintTextTable[RHT_RED_RUPEE] = HintText(CustomMessage("a Red Rupee", /*german*/"ein roter Rubin", /*french*/"un rubis rouge"), // /*spanish*/una rupia roja { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("couch cash", /*german*/"", /*french*/"un peu de fric"), + CustomMessage("couch cash", /*german*/"ein wenig Zaster", /*french*/"un peu de fric"), // /*spanish*/una buena moneda - CustomMessage("a red gem", /*german*/"", /*french*/"un joyau rouge")}); + CustomMessage("a red gem", /*german*/"ein roter Edelstein", /*french*/"un joyau rouge")}); // /*spanish*/una gema roja - hintTextTable[RHT_PURPLE_RUPEE] = HintText(CustomMessage("a Purple Rupee", /*german*/"", /*french*/"un rubis pourpre"), + hintTextTable[RHT_PURPLE_RUPEE] = HintText(CustomMessage("a Purple Rupee", /*german*/"ein violetter Rubin", /*french*/"un rubis pourpre"), // /*spanish*/una rupia morada { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("big bucks", /*german*/"", /*french*/"plein de fric"), + CustomMessage("big bucks", /*german*/"ordentlich Zaster", /*french*/"plein de fric"), // /*spanish*/plata de calidad - CustomMessage("a purple gem", /*german*/"", /*french*/"un joyau mauve"), + CustomMessage("a purple gem", /*german*/"ein violetter Edelstein", /*french*/"un joyau mauve"), // /*spanish*/una gema morada - CustomMessage("wealth", /*german*/"", /*french*/"la richesse")}); + CustomMessage("wealth", /*german*/"Wohlstand", /*french*/"la richesse")}); // /*spanish*/una buena riqueza - hintTextTable[RHT_HUGE_RUPEE] = HintText(CustomMessage("a Huge Rupee", /*german*/"", /*french*/"un énorme rubis"), + hintTextTable[RHT_HUGE_RUPEE] = HintText(CustomMessage("a Huge Rupee", /*german*/"ein riesiger Rubin", /*french*/"un énorme rubis"), // /*spanish*/una rupia gigante { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("a juicy jackpot", /*german*/"", /*french*/"le jackpot"), + CustomMessage("a juicy jackpot", /*german*/"ein saftiger Jackpot", /*french*/"le jackpot"), // /*spanish*/el premio gordo - CustomMessage("a yellow gem", /*german*/"", /*french*/"un joyau doré"), + CustomMessage("a yellow gem", /*german*/"ein gelber Edelstein", /*french*/"un joyau doré"), // /*spanish*/una gema amarilla - CustomMessage("a giant gem", /*german*/"", /*french*/"un gros joyau"), + CustomMessage("a giant gem", /*german*/"ein riesiger Edelstein", /*french*/"un gros joyau"), // /*spanish*/una gema descomunal - CustomMessage("great wealth", /*german*/"", /*french*/"l'aisance financière")}); + CustomMessage("great wealth", /*german*/"großer Wohlstand", /*french*/"l'aisance financière")}); // /*spanish*/dinero a caudales - hintTextTable[RHT_PIECE_OF_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"", /*french*/"un Quart de Coeur"), + hintTextTable[RHT_PIECE_OF_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"ein Herzteil", /*french*/"un Quart de Coeur"), // /*spanish*/una pieza de corazón { - CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + CustomMessage("something heart-shaped", /*german*/"etwas Herzförmiges", /*french*/"une chose en forme de coeur") // /*spanish*/algo con forma de corazón }, { - CustomMessage("a little love", /*german*/"", /*french*/"un peu plus d'amour"), + CustomMessage("a little love", /*german*/"ein wenig Liebe", /*french*/"un peu plus d'amour"), // /*spanish*/un cuarto de amor - CustomMessage("a broken heart", /*german*/"", /*french*/"un coeur brisé")}); + CustomMessage("a broken heart", /*german*/"ein gebrochenes Herz", /*french*/"un coeur brisé")}); // /*spanish*/un corazón roto - hintTextTable[RHT_HEART_CONTAINER] = HintText(CustomMessage("a Heart Container", /*german*/"", /*french*/"un Réceptacle de Coeur"), + hintTextTable[RHT_HEART_CONTAINER] = HintText(CustomMessage("a Heart Container", /*german*/"ein Herzcontainer", /*french*/"un Réceptacle de Coeur"), // /*spanish*/un contenedor de corazón { - CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + CustomMessage("something heart-shaped", /*german*/"etwas Herzförmiges", /*french*/"une chose en forme de coeur") // /*spanish*/algo con forma de corazón }, { - CustomMessage("a lot of love", /*german*/"", /*french*/"le grand amour"), + CustomMessage("a lot of love", /*german*/"eine Menge Liebe", /*french*/"le grand amour"), // /*spanish*/amor por doquier - CustomMessage("a Valentine's gift", /*german*/"", /*french*/"un cadeau de Saint-Valentin"), + CustomMessage("a Valentine's gift", /*german*/"ein Valentinsgeschenk", /*french*/"un cadeau de Saint-Valentin"), // /*spanish*/un contenedor de afección - CustomMessage("a boss's organ", /*german*/"", /*french*/"un organe de monstre")}); + CustomMessage("a boss's organ", /*german*/"ein monströses Organ", /*french*/"un organe de monstre")}); // /*spanish*/los órganos de un jefe - hintTextTable[RHT_ICE_TRAP] = HintText(CustomMessage("an Ice Trap", /*german*/"", /*french*/"un Piège de Glace"), + hintTextTable[RHT_ICE_TRAP] = HintText(CustomMessage("an Ice Trap", /*german*/"eine Eisfalle", /*french*/"un Piège de Glace"), // /*spanish*/una trampa de hielo { - CustomMessage("a Great Fairy's power", /*german*/"", /*french*/"le pouvoir d'une grande fée"), + CustomMessage("a Great Fairy's power", /*german*/"eine Kraft einer großen Fee", /*french*/"le pouvoir d'une grande fée"), // /*spanish*/el poder de una Gran Hada - CustomMessage("a magic arrow", /*german*/"", /*french*/"une flèche magique"), + CustomMessage("a magic arrow", /*german*/"ein magischer Pfeil", /*french*/"une flèche magique"), // /*spanish*/una flecha mágica - CustomMessage("a medallion", /*german*/"", /*french*/"un médaillon"), + CustomMessage("a medallion", /*german*/"ein Amulett", /*french*/"un médaillon"), // /*spanish*/un medallón - CustomMessage("a spiritual stone", /*german*/"", /*french*/"une Pierre Ancestrale"), + CustomMessage("a spiritual stone", /*german*/"ein spiritueller Stein", /*french*/"une Pierre Ancestrale"), // /*spanish*/una piedra espiritual - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("a gift from Ganon", /*german*/"", /*french*/"un cadeau de Ganon"), + CustomMessage("a gift from Ganon", /*german*/"ein Geschenk von Ganon", /*french*/"un cadeau de Ganon"), // /*spanish*/un regalo de Ganon - CustomMessage("a chilling discovery", /*german*/"", /*french*/"une frissonante découverte"), + CustomMessage("a chilling discovery", /*german*/"eine fröstelnde Entdeckung", /*french*/"une frissonante découverte"), // /*spanish*/un escalofriante hallazgo - CustomMessage("frosty fun", /*german*/"", /*french*/"une engelure")}); + CustomMessage("frosty fun", /*german*/"frostiger Spaß", /*french*/"une engelure")}); // /*spanish*/una gélida diversión - hintTextTable[RHT_BOMBS_5] = HintText(CustomMessage("Bombs (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de bombes"), + hintTextTable[RHT_BOMBS_5] = HintText(CustomMessage("Bombs (5 pieces)", /*german*/"Bomben (5 Stück)", /*french*/"une demi-dizaine de bombes"), // /*spanish*/unas (5) bombas { - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("a few explosives", /*german*/"", /*french*/"une poignée de pétards"), + CustomMessage("a few explosives", /*german*/"ein paar Explosivbehälter", /*french*/"une poignée de pétards"), // /*spanish*/un par de explosivos - CustomMessage("a few blast balls", /*german*/"", /*french*/"une poignée de boules bleues")}); + CustomMessage("a few blast balls", /*german*/"ein paar Explosionsbälle", /*french*/"une poignée de boules bleues")}); // /*spanish*/un par de estallidos - hintTextTable[RHT_BOMBS_10] = HintText(CustomMessage("Bombs (10 pieces)", /*german*/"", /*french*/"une dizaine de bombes"), + hintTextTable[RHT_BOMBS_10] = HintText(CustomMessage("Bombs (10 pieces)", /*german*/"Bomben (10 Stück)", /*french*/"une dizaine de bombes"), // /*spanish*/unas (10) bombas { - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("some explosives", /*german*/"", /*french*/"un paquet de pétards"), + CustomMessage("some explosives", /*german*/"einige Explosivbehälter", /*french*/"un paquet de pétards"), // /*spanish*/unos cuantos explosivos - CustomMessage("some blast balls", /*german*/"", /*french*/"un paquet de boules bleues")}); + CustomMessage("some blast balls", /*german*/"einige Explosionsbälle", /*french*/"un paquet de boules bleues")}); // /*spanish*/unos cuantos estallidos - hintTextTable[RHT_BOMBS_20] = HintText(CustomMessage("Bombs (20 pieces)", /*german*/"", /*french*/"une vingtaine de bombes"), + hintTextTable[RHT_BOMBS_20] = HintText(CustomMessage("Bombs (20 pieces)", /*german*/"Bomben (20 Stück)", /*french*/"une vingtaine de bombes"), // /*spanish*/unas (20) bombas { - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("lots-o-explosives", /*german*/"", /*french*/"une abondance de pétards"), + CustomMessage("lots-o-explosives", /*german*/"viele Explosivbehälter", /*french*/"une abondance de pétards"), // /*spanish*/un puñado de explosivos - CustomMessage("plenty of blast balls", /*german*/"", /*french*/"une abondance de boules bleues")}); + CustomMessage("plenty of blast balls", /*german*/"viele Explosionsbälle", /*french*/"une abondance de boules bleues")}); // /*spanish*/bastantes estallidos - hintTextTable[RHT_BOMBCHU_5] = HintText(CustomMessage("Bombchus (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de Missiles"), + hintTextTable[RHT_BOMBCHU_5] = HintText(CustomMessage("Bombchus (5 pieces)", /*german*/"Krabbelminen (5 Stück)", /*french*/"une demi-dizaine de Missiles"), // /*spanish*/unos (5) bombchus { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas"), // /*spanish*/un obsequio de la Casa Skulltula - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("a few mice bombs", /*german*/"", /*french*/"une poignée de mignons explosifs"), + CustomMessage("a few mice bombs", /*german*/"ein paar Mäusebomben", /*french*/"une poignée de mignons explosifs"), // /*spanish*/un par de bombas roedoras - CustomMessage("a few proximity mice", /*german*/"", /*french*/"une poignée de jouets à remonter"), + CustomMessage("a few proximity mice", /*german*/"ein paar Näherungsmäuse", /*french*/"une poignée de jouets à remonter"), // /*spanish*/un par de explosivos ratoncitos - CustomMessage("a few wall crawlers", /*german*/"", /*french*/"une poignée de rapides grimpeurs"), + CustomMessage("a few wall crawlers", /*german*/"ein paar Wandkrabbler", /*french*/"une poignée de rapides grimpeurs"), // /*spanish*/un par de trepaparedes - CustomMessage("a few trail blazers", /*german*/"", /*french*/"une poignée de zigzags éclatants")}); + CustomMessage("a few trail blazers", /*german*/"ein paar Vorreiter", /*french*/"une poignée de zigzags éclatants")}); // /*spanish*/un par de ratas propulsadas - hintTextTable[RHT_BOMBCHU_10] = HintText(CustomMessage("Bombchus (10 pieces)", /*german*/"", /*french*/"une dizaine de Missiles"), + hintTextTable[RHT_BOMBCHU_10] = HintText(CustomMessage("Bombchus (10 pieces)", /*german*/"Krabbelminen (10 Stück)", /*french*/"une dizaine de Missiles"), // /*spanish*/unos (10) bombchus { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas"), // /*spanish*/un obsequio de la Casa Skulltula - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("some mice bombs", /*german*/"", /*french*/"un paquet de mignons explosifs"), + CustomMessage("some mice bombs", /*german*/"einige Mäusebomben", /*french*/"un paquet de mignons explosifs"), // /*spanish*/unas cuantas bombas roedoras - CustomMessage("some proximity mice", /*german*/"", /*french*/"un paquet de jouets à remonter"), + CustomMessage("some proximity mice", /*german*/"einige Näherungsmäuse", /*french*/"un paquet de jouets à remonter"), // /*spanish*/unos cuantos explosivos ratoncitos - CustomMessage("some wall crawlers", /*german*/"", /*french*/"un paquet de rapides grimpeurs"), + CustomMessage("some wall crawlers", /*german*/"einige Wandkrabbler", /*french*/"un paquet de rapides grimpeurs"), // /*spanish*/unos cuantos trepaparedes - CustomMessage("some trail blazers", /*german*/"", /*french*/"un paquet de zigzags éclatants")}); + CustomMessage("some trail blazers", /*german*/"einige Vorreiter", /*french*/"un paquet de zigzags éclatants")}); // /*spanish*/unas cuantas ratas propulsadas - hintTextTable[RHT_BOMBCHU_20] = HintText(CustomMessage("Bombchus (20 pieces)", /*german*/"", /*french*/"une vingtaine de Missiles"), + hintTextTable[RHT_BOMBCHU_20] = HintText(CustomMessage("Bombchus (20 pieces)", /*german*/"Krabbelminen (20 Stück)", /*french*/"une vingtaine de Missiles"), // /*spanish*/unos (20) bombchus { - CustomMessage("a prize of the House of Skulltulas", /*german*/"", /*french*/"un prix de la maison des Skulltulas"), + CustomMessage("a prize of the House of Skulltulas", /*german*/"ein Preis des Skulltula-Hauses", /*french*/"un prix de la maison des Skulltulas"), // /*spanish*/un obsequio de la Casa Skulltula - CustomMessage("explosives", /*german*/"", /*french*/"un paquet d'explosifs") + CustomMessage("explosives", /*german*/"Explosivpakete", /*french*/"un paquet d'explosifs") // /*spanish*/un montón de explosivos }, { - CustomMessage("plenty of mice bombs", /*german*/"", /*french*/"une abondance de mignons explosifs"), + CustomMessage("plenty of mice bombs", /*german*/"viele Mäusebomben", /*french*/"une abondance de mignons explosifs"), // /*spanish*/bastantes bombas roedoras - CustomMessage("plenty of proximity mice", /*german*/"", /*french*/"une abondance de jouets à remonter"), + CustomMessage("plenty of proximity mice", /*german*/"viele Näherungsmäuse", /*french*/"une abondance de jouets à remonter"), // /*spanish*/bastantes explosivos ratoncitos - CustomMessage("plenty of wall crawlers", /*german*/"", /*french*/"une abondance de rapides grimpeurs"), + CustomMessage("plenty of wall crawlers", /*german*/"viele Wandkrabbler", /*french*/"une abondance de rapides grimpeurs"), // /*spanish*/bastantes trepaparedes - CustomMessage("plenty of trail blazers", /*german*/"", /*french*/"une abondance de zigzags éclatants")}); + CustomMessage("plenty of trail blazers", /*german*/"viele Vorreiter", /*french*/"une abondance de zigzags éclatants")}); // /*spanish*/bastantes ratas propulsadas - hintTextTable[RHT_ARROWS_5] = HintText(CustomMessage("Arrows (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de flèches"), + hintTextTable[RHT_ARROWS_5] = HintText(CustomMessage("Arrows (5 pieces)", /*german*/"Pfeile (5 Stück)", /*french*/"une demi-dizaine de flèches"), // /*spanish*/unas (5) flechas { - CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + CustomMessage("a projectile", /*german*/"ein Projektil", /*french*/"un projectile") // /*spanish*/un proyectil }, { - CustomMessage("a few danger darts", /*german*/"", /*french*/"une poignée d'obus"), + CustomMessage("a few danger darts", /*german*/"ein paar gefährliche Spitzen", /*french*/"une poignée d'obus"), // /*spanish*/un par de peligrosos dardos - CustomMessage("a few sharp shafts", /*german*/"", /*french*/"une poignée de piquets")}); + CustomMessage("a few sharp shafts", /*german*/"ein paar scharfe Stifte", /*french*/"une poignée de piquets")}); // /*spanish*/un par de puntas afiladas - hintTextTable[RHT_ARROWS_10] = HintText(CustomMessage("Arrows (10 pieces)", /*german*/"", /*french*/"une dizaine de flèches"), + hintTextTable[RHT_ARROWS_10] = HintText(CustomMessage("Arrows (10 pieces)", /*german*/"Pfeile (10 Stück)", /*french*/"une dizaine de flèches"), // /*spanish*/unas (10) flechas { - CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + CustomMessage("a projectile", /*german*/"ein Projektil", /*french*/"un projectile") // /*spanish*/un proyectil }, { - CustomMessage("some danger darts", /*german*/"", /*french*/"un paquet d'obus"), + CustomMessage("some danger darts", /*german*/"einige gefährliche Spitzen", /*french*/"un paquet d'obus"), // /*spanish*/unos cuantos peligrosos dardos - CustomMessage("some sharp shafts", /*german*/"", /*french*/"un paquet de piquets")}); + CustomMessage("some sharp shafts", /*german*/"einige scharfe Stifte", /*french*/"un paquet de piquets")}); // /*spanish*/unas cuantas puntas afiladas - hintTextTable[RHT_ARROWS_30] = HintText(CustomMessage("Arrows (30 pieces)", /*german*/"", /*french*/"une trentaine de flèches"), + hintTextTable[RHT_ARROWS_30] = HintText(CustomMessage("Arrows (30 pieces)", /*german*/"Pfeile (30 Stück)", /*french*/"une trentaine de flèches"), // /*spanish*/unas (30) flechas { - CustomMessage("a projectile", /*german*/"", /*french*/"un projectile") + CustomMessage("a projectile", /*german*/"ein Projektil", /*french*/"un projectile") // /*spanish*/un proyectil }, { - CustomMessage("plenty of danger darts", /*german*/"", /*french*/"une abondance d'obus"), + CustomMessage("plenty of danger darts", /*german*/"viele gefährliche Spitzen", /*french*/"une abondance d'obus"), // /*spanish*/bastantes peligrosos dardos - CustomMessage("plenty of sharp shafts", /*german*/"", /*french*/"une abondance de piquets")}); + CustomMessage("plenty of sharp shafts", /*german*/"viele scharfe Stifte", /*french*/"une abondance de piquets")}); // /*spanish*/bastantes puntas afiladas - hintTextTable[RHT_DEKU_NUTS_5] = HintText(CustomMessage("Deku Nuts (5 pieces)", /*german*/"", /*french*/"une demi-dizaine de noix Mojo"), + hintTextTable[RHT_DEKU_NUTS_5] = HintText(CustomMessage("Deku Nuts (5 pieces)", /*german*/"Deku-Nüsse (5 Stück)", /*french*/"une demi-dizaine de noix Mojo"), // /*spanish*/unas (5) nueces deku { - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + CustomMessage("some Deku munitions", /*german*/"ein wenig Deku-Munition", /*french*/"un paquet de munitions Mojo"), // /*spanish*/un montón de municiones Deku - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("some nuts", /*german*/"", /*french*/"une poignée de noisettes"), + CustomMessage("some nuts", /*german*/"ein paar Nüsse", /*french*/"une poignée de noisettes"), // /*spanish*/un par de nueces - CustomMessage("some flashbangs", /*german*/"", /*french*/"une poignée d'éclats"), + CustomMessage("some flashbangs", /*german*/"ein paar Blendgranaten", /*french*/"une poignée d'éclats"), // /*spanish*/un par de semillas aturdidoras - CustomMessage("some scrub spit", /*german*/"", /*french*/"une poignée de crachats Mojo")}); + CustomMessage("some scrub spit", /*german*/"ein wenig Buschspucke", /*french*/"une poignée de crachats Mojo")}); // /*spanish*/un par de escupitajos deku - hintTextTable[RHT_DEKU_NUTS_10] = HintText(CustomMessage("Deku Nuts (10 pieces)", /*german*/"", /*french*/"une dizaine de noix Mojo"), + hintTextTable[RHT_DEKU_NUTS_10] = HintText(CustomMessage("Deku Nuts (10 pieces)", /*german*/"Deku-Nüsse (10 Stück)", /*french*/"une dizaine de noix Mojo"), // /*spanish*/unas (10) nueces deku { - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo"), + CustomMessage("some Deku munitions", /*german*/"etwas Deku-Munition", /*french*/"un paquet de munitions Mojo"), // /*spanish*/un montón de municiones Deku - CustomMessage("something that can stun", /*german*/"", /*french*/"une chose qui peut paralyser") + CustomMessage("something that can stun", /*german*/"etwas, das paralysieren kann", /*french*/"une chose qui peut paralyser") // /*spanish*/algo que pueda paralizar }, { - CustomMessage("lots-o-nuts", /*german*/"", /*french*/"un paquet de noisettes"), + CustomMessage("lots-o-nuts", /*german*/"einige Nüsse", /*french*/"un paquet de noisettes"), // /*spanish*/un puñado de nueces - CustomMessage("plenty of flashbangs", /*german*/"", /*french*/"un paquet d'éclats"), + CustomMessage("plenty of flashbangs", /*german*/"einige Blendgranaten", /*french*/"un paquet d'éclats"), // /*spanish*/unas cuantas semillas aturdidoras - CustomMessage("plenty of scrub spit", /*german*/"", /*french*/"un paquet de crachats Mojo")}); + CustomMessage("plenty of scrub spit", /*german*/"einige Buschspucke", /*french*/"un paquet de crachats Mojo")}); // /*spanish*/unos cuantos escupitajos deku - hintTextTable[RHT_DEKU_SEEDS_30] = HintText(CustomMessage("Deku Seeds (30 pieces)", /*german*/"", /*french*/"une trentaine de graines Mojo"), + hintTextTable[RHT_DEKU_SEEDS_30] = HintText(CustomMessage("Deku Seeds (30 pieces)", /*german*/"Deku-Samen (30 Stück)", /*french*/"une trentaine de graines Mojo"), // /*spanish*/unas (30) semillas deku { - CustomMessage("a projectile", /*german*/"", /*french*/"un projectile"), + CustomMessage("a projectile", /*german*/"ein Projektil", /*french*/"un projectile"), // /*spanish*/un proyectil - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + CustomMessage("some Deku munitions", /*german*/"viel Deku-Munition", /*french*/"un paquet de munitions Mojo") // /*spanish*/un montón de municiones Deku }, { - CustomMessage("catapult ammo", /*german*/"", /*french*/"un paquet de délicieuses munitions"), + CustomMessage("catapult ammo", /*german*/"Katapultmunition", /*french*/"un paquet de délicieuses munitions"), // /*spanish*/un par de munición infantil - CustomMessage("lots-o-seeds", /*german*/"", /*french*/"un paquet de germes séchés")}); + CustomMessage("lots-o-seeds", /*german*/"viele Samen", /*french*/"un paquet de germes séchés")}); // /*spanish*/un puñado de semillas - hintTextTable[RHT_DEKU_STICK_1] = HintText(CustomMessage("a Deku Stick", /*german*/"", /*french*/"un bâton Mojo"), + hintTextTable[RHT_DEKU_STICK_1] = HintText(CustomMessage("a Deku Stick", /*german*/"ein Deku-Stab", /*french*/"un bâton Mojo"), // /*spanish*/un palo deku { - CustomMessage("some Deku munitions", /*german*/"", /*french*/"un paquet de munitions Mojo") + CustomMessage("some Deku munitions", /*german*/"ein wenig Deku-Munition", /*french*/"un paquet de munitions Mojo") // /*spanish*/un montón de municiones Deku }, { - CustomMessage("a breakable branch", /*german*/"", /*french*/"un bout de bois")}); + CustomMessage("a breakable branch", /*german*/"ein brüchiger Zweig", /*french*/"un bout de bois")}); // /*spanish*/un pequeño báculo - hintTextTable[RHT_TREASURE_GAME_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"", /*french*/"un Quart de Coeur"), + hintTextTable[RHT_TREASURE_GAME_HEART] = HintText(CustomMessage("a Piece of Heart", /*german*/"ein Herzteil", /*french*/"un Quart de Coeur"), // /*spanish*/el amor de la victoria { - CustomMessage("something heart-shaped", /*german*/"", /*french*/"une chose en forme de coeur") + CustomMessage("something heart-shaped", /*german*/"etwas Herzförmiges", /*french*/"une chose en forme de coeur") // /*spanish*/algo con forma de corazón }, { - CustomMessage("a victory valentine", /*german*/"", /*french*/"un amour gagnant")}); + CustomMessage("a victory valentine", /*german*/"ein siegreicher Valentin", /*french*/"un amour gagnant")}); // /*spanish*/el amor victorioso - hintTextTable[RHT_TREASURE_GAME_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"", /*french*/"un rubis vert"), + hintTextTable[RHT_TREASURE_GAME_GREEN_RUPEE] = HintText(CustomMessage("a Green Rupee", /*german*/"ein grüner Rubin", /*french*/"un rubis vert"), // /*spanish*/una rupia verde { - CustomMessage("some rupees", /*german*/"", /*french*/"une quantité de rubis") + CustomMessage("some rupees", /*german*/"einige Rubine", /*french*/"une quantité de rubis") // /*spanish*/una cantidad de rupias }, { - CustomMessage("the dollar of defeat", /*german*/"", /*french*/"le rubis de la défaite")}); + CustomMessage("the dollar of defeat", /*german*/"der Rubin der Niederlage", /*french*/"le rubis de la défaite")}); // /*spanish*/el peso de la derrota - hintTextTable[RHT_TRIFORCE_PIECE] = HintText(CustomMessage("a Piece of the Triforce", /*german*/"", /*french*/"un fragment de la Triforce"), + hintTextTable[RHT_TRIFORCE_PIECE] = HintText(CustomMessage("a Piece of the Triforce", /*german*/"ein Triforce-Fragment", /*french*/"un fragment de la Triforce"), // /*spanish*/un fragmento de la Trifuerza {}, { - CustomMessage("a triumph fork", /*german*/"", /*french*/"la Tribosse"), + CustomMessage("a triumph fork", /*german*/"ein Dreieck des Triumphs", /*french*/"la Tribosse"), // /*spanish*/un trígono del triunfo - CustomMessage("cheese", /*german*/"", /*french*/"du fromage"), + CustomMessage("cheese", /*german*/"Käse", /*french*/"du fromage"), // /*spanish*/un porción de queso - CustomMessage("a gold fragment", /*german*/"", /*french*/"un fragment d'or")}); + CustomMessage("a gold fragment", /*german*/"ein goldenes Fragment", /*french*/"un fragment d'or")}); // /*spanish*/un fragmento dorado - hintTextTable[RHT_GOHMA_SOUL] = HintText(CustomMessage("the soul of Gohma", /*german*/"", /*french*/""), + hintTextTable[RHT_GOHMA_SOUL] = HintText(CustomMessage("the soul of Gohma", /*german*/"die Seele Gohmas", /*french*/""), { - CustomMessage("something webbed", /*german*/"", /*french*/"") + CustomMessage("something webbed", /*german*/"etwas Verwobenes", /*french*/"") }, { - CustomMessage("an invasive soul", /*german*/"", /*french*/""), - CustomMessage("some spider essence", /*german*/"", /*french*/"")}); + CustomMessage("an invasive soul", /*german*/"eine invasive Seele", /*french*/""), + CustomMessage("some spider essence", /*german*/"etwas spinnenartige Essenz", /*french*/"")}); - hintTextTable[RHT_KING_DODONGO_SOUL] = HintText(CustomMessage("the soul of King Dodongo", /*german*/"", /*french*/""), + hintTextTable[RHT_KING_DODONGO_SOUL] = HintText(CustomMessage("the soul of King Dodongo", /*german*/"die Seele König Dodongos", /*french*/""), { - CustomMessage("something explosive", /*german*/"", /*french*/"") + CustomMessage("something explosive", /*german*/"etwas Explosives", /*french*/"") }, { - CustomMessage("a royal soul", /*german*/"", /*french*/""), - CustomMessage("some reptile essence", /*german*/"", /*french*/"")}); + CustomMessage("a royal soul", /*german*/"eine royale Seele", /*french*/""), + CustomMessage("some reptile essence", /*german*/"etwas reptilienartige Essenz", /*french*/"")}); - hintTextTable[RHT_BARINADE_SOUL] = HintText(CustomMessage("the soul of Barinade", /*german*/"", /*french*/""), + hintTextTable[RHT_BARINADE_SOUL] = HintText(CustomMessage("the soul of Barinade", /*german*/"die Seele Barinades", /*french*/""), { - CustomMessage("something fishy", /*german*/"", /*french*/"") + CustomMessage("something fishy", /*german*/"etwas Fischiges", /*french*/"") }, { - CustomMessage("an infectuous soul", /*german*/"", /*french*/""), - CustomMessage("some parasitic essence", /*german*/"", /*french*/"")}); + CustomMessage("an infectuous soul", /*german*/"eine infektiöse Seele", /*french*/""), + CustomMessage("some parasitic essence", /*german*/"etwas parasitäre Essenz", /*french*/"")}); - hintTextTable[RHT_PHANTOM_GANON_SOUL] = HintText(CustomMessage("the soul of Phantom Ganon", /*german*/"", /*french*/""), + hintTextTable[RHT_PHANTOM_GANON_SOUL] = HintText(CustomMessage("the soul of Phantom Ganon", /*german*/"die Seele Phantom-Ganons", /*french*/""), { - CustomMessage("something spectral", /*german*/"", /*french*/"") + CustomMessage("something spectral", /*german*/"etwas Spektrales", /*french*/"") }, { - CustomMessage("a duplicate soul", /*german*/"", /*french*/""), + CustomMessage("a duplicate soul", /*german*/"eine duplizierte Seele", /*french*/""), - CustomMessage("some illusionary essence", /*german*/"", /*french*/"")}); + CustomMessage("some illusionary essence", /*german*/"etwas illusionäre Essenz", /*french*/"")}); - hintTextTable[RHT_VOLVAGIA_SOUL] = HintText(CustomMessage("the soul of Volvagia", /*german*/"", /*french*/""), + hintTextTable[RHT_VOLVAGIA_SOUL] = HintText(CustomMessage("the soul of Volvagia", /*german*/"die Seele Volvagias", /*french*/""), { - CustomMessage("something hot", /*german*/"", /*french*/"") + CustomMessage("something hot", /*german*/"etwas Heißes", /*french*/"") }, { - CustomMessage("a draconic soul", /*german*/"", /*french*/""), - CustomMessage("some magmatic essence", /*german*/"", /*french*/"")}); + CustomMessage("a draconic soul", /*german*/"eine drakonische Seele", /*french*/""), + CustomMessage("some magmatic essence", /*german*/"etwas magmatische Essenz", /*french*/"")}); - hintTextTable[RHT_MORPHA_SOUL] = HintText(CustomMessage("the soul of Barinade", /*german*/"", /*french*/""), + hintTextTable[RHT_MORPHA_SOUL] = HintText(CustomMessage("the soul of Morpha", /*german*/"die Seele Morphas", /*french*/""), { - CustomMessage("something wet", /*german*/"", /*french*/"") + CustomMessage("something wet", /*german*/"etwas Nasses", /*french*/"") }, { - CustomMessage("an aquatic soul", /*german*/"", /*french*/""), - CustomMessage("some liquid essence", /*german*/"", /*french*/"")}); + CustomMessage("an aquatic soul", /*german*/"eine aquatische Seele", /*french*/""), + CustomMessage("some liquid essence", /*german*/"etwas flüssige Essenz", /*french*/"")}); - hintTextTable[RHT_BONGO_BONGO_SOUL] = HintText(CustomMessage("the soul of Bongo Bongo", /*german*/"", /*french*/""), + hintTextTable[RHT_BONGO_BONGO_SOUL] = HintText(CustomMessage("the soul of Bongo Bongo", /*german*/"die Seele Bongo Bongos", /*french*/""), { - CustomMessage("something dark", /*german*/"", /*french*/"") + CustomMessage("something dark", /*german*/"etwas Dunkles", /*french*/"") }, { - CustomMessage("a shadowy soul", /*german*/"", /*french*/""), - CustomMessage("some handy essence", /*german*/"", /*french*/"")}); + CustomMessage("a shadowy soul", /*german*/"eine schattige Seele", /*french*/""), + CustomMessage("some handy essence", /*german*/"etwas praktische Essenz", /*french*/"")}); - hintTextTable[RHT_TWINROVA_SOUL] = HintText(CustomMessage("the soul of Twinrova", /*german*/"", /*french*/""), + hintTextTable[RHT_TWINROVA_SOUL] = HintText(CustomMessage("the soul of Twinrova", /*german*/"die Seele Twinrovas", /*french*/""), { - CustomMessage("something spiritual", /*german*/"", /*french*/"") + CustomMessage("something spiritual", /*german*/"etwas Spirituelles", /*french*/"") }, { - CustomMessage("old souls", /*german*/"", /*french*/""), - CustomMessage("twin essences", /*german*/"", /*french*/"")}); + CustomMessage("old souls", /*german*/"alte Seelen", /*french*/""), + CustomMessage("twin essences", /*german*/"Zwillingsessenzen", /*french*/"")}); - hintTextTable[RHT_GANON_SOUL] = HintText(CustomMessage("the soul of Ganon", /*german*/"", /*french*/""), + hintTextTable[RHT_GANON_SOUL] = HintText(CustomMessage("the soul of Ganon", /*german*/"die Seele Ganons", /*french*/""), { - CustomMessage("something strong", /*german*/"", /*french*/"") + CustomMessage("something strong", /*german*/"etwas Starkes", /*french*/"") }, { - CustomMessage("an evil soul", /*german*/"", /*french*/""), - CustomMessage("some powerful essence", /*german*/"", /*french*/"")}); + CustomMessage("an evil soul", /*german*/"eine böse Seele", /*french*/""), + CustomMessage("some powerful essence", /*german*/"etwas mächtige Essenz", /*french*/"")}); - hintTextTable[RHT_OCARINA_A_BUTTON] = HintText(CustomMessage("an Ocarina A Button", /*german*/"", /*french*/"la Touche A de l'Ocarina"), + hintTextTable[RHT_OCARINA_A_BUTTON] = HintText(CustomMessage("an Ocarina A Button", /*german*/"eine Okarina A Taste", /*french*/"la Touche A de l'Ocarina"), // /*spanish*/un botón A de Ocarina { - CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + CustomMessage("something melodic", /*german*/"etwas Melodisches", /*french*/"quelque chose de mélodieux") // /*spanish*/algo melódico }, { - CustomMessage("a musical letter", /*german*/"", /*french*/"une lettre musicale")}); + CustomMessage("a musical letter", /*german*/"ein musikalischer Brief", /*french*/"une lettre musicale")}); // /*spanish*/una letra musical - hintTextTable[RHT_OCARINA_C_UP_BUTTON] = HintText(CustomMessage("an Ocarina C Up Button", /*german*/"", /*french*/"la Touche C-Haut de l'Ocarina"), + hintTextTable[RHT_OCARINA_C_UP_BUTTON] = HintText(CustomMessage("an Ocarina C Up Button", /*german*/"eine Okarina C-Oben Taste", /*french*/"la Touche C-Haut de l'Ocarina"), // /*spanish*/un botón C superior de Ocarina { - CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + CustomMessage("something melodic", /*german*/"etwas Melodisches", /*french*/"quelque chose de mélodieux") // /*spanish*/algo melódico }, { - CustomMessage("a high tone", /*german*/"", /*french*/"une tonalité élevée")}); + CustomMessage("a high tone", /*german*/"ein hoher Ton", /*french*/"une tonalité élevée")}); // /*spanish*/un tono alto - hintTextTable[RHT_OCARINA_C_DOWN_BUTTON] = HintText(CustomMessage("an Ocarina C Down Button", /*german*/"", /*french*/"la Touche C-Bas de l'Ocarina"), + hintTextTable[RHT_OCARINA_C_DOWN_BUTTON] = HintText(CustomMessage("an Ocarina C Down Button", /*german*/"eine Okarina C-Unten Taste", /*french*/"la Touche C-Bas de l'Ocarina"), // /*spanish*/un botón C inferior de Ocarina { - CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + CustomMessage("something melodic", /*german*/"etwas Melodisches", /*french*/"quelque chose de mélodieux") // /*spanish*/algo melódico }, { - CustomMessage("a low tone", /*german*/"", /*french*/"une tonalité basse")}); + CustomMessage("a low tone", /*german*/"ein tiefer Ton", /*french*/"une tonalité basse")}); // /*spanish*/un tono bajo - hintTextTable[RHT_OCARINA_C_LEFT_BUTTON] = HintText(CustomMessage("an Ocarina C Left Button", /*german*/"", /*french*/"la Touche C-Gauche de l'Ocarina"), + hintTextTable[RHT_OCARINA_C_LEFT_BUTTON] = HintText(CustomMessage("an Ocarina C Left Button", /*german*/"eine Okarina C-Links Taste", /*french*/"la Touche C-Gauche de l'Ocarina"), // /*spanish*/un botón C izquierdo de Ocarina { - CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + CustomMessage("something melodic", /*german*/"etwas Melodisches", /*french*/"quelque chose de mélodieux") // /*spanish*/algo melódico }, { - CustomMessage("a leftward tone", /*german*/"", /*french*/"une tonalité vers la gauche")}); + CustomMessage("a leftward tone", /*german*/"ein linksseitiger Ton", /*french*/"une tonalité vers la gauche")}); // /*spanish*/un tono hacia la izquierda - hintTextTable[RHT_OCARINA_C_RIGHT_BUTTON] = HintText(CustomMessage("an Ocarina C Right Button", /*german*/"", /*french*/"la Touche C-Droit de l'Ocarina"), + hintTextTable[RHT_OCARINA_C_RIGHT_BUTTON] = HintText(CustomMessage("an Ocarina C Right Button", /*german*/"eine Okarina C-Rechts Taste", /*french*/"la Touche C-Droit de l'Ocarina"), // /*spanish*/un botón C derecho de Ocarina { - CustomMessage("something melodic", /*german*/"", /*french*/"quelque chose de mélodieux") + CustomMessage("something melodic", /*german*/"etwas Melodisches", /*french*/"quelque chose de mélodieux") // /*spanish*/algo melódico }, { - CustomMessage("a rightward tone", /*german*/"", /*french*/"une tonalité vers la droite")}); + CustomMessage("a rightward tone", /*german*/"ein rechtsseitiger Ton", /*french*/"une tonalité vers la droite")}); // /*spanish*/un tono hacia la derecha - hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"", /*french*/"canne à pêche"), + hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"eine Angelrute", /*french*/"canne à pêche"), // /*spanish*/caña de pescar { - CustomMessage("the pond owner's property", /*german*/"", /*french*/"(canne à pêche)") + CustomMessage("the pond owner's property", /*german*/"der Besitz des Teicheigners", /*french*/"(canne à pêche)") // /*spanish*/(caña de pescar) }, { - CustomMessage("a fish-puller", /*german*/"", /*french*/"(canne à pêche)")}); + CustomMessage("a fish-puller", /*german*/"ein Fischzieher", /*french*/"(canne à pêche)")}); // /*spanish*/(caña de pescar) - + hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), { CustomMessage("", /*german*/"!!!", /*french*/"!!!"), @@ -2106,27 +2106,27 @@ void StaticData::HintTable_Init_Item() { }, { CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); - hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"", /*french*/"Epona"), + hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"Epona", /*french*/"Epona"), // /*spanish*/a Epona { - CustomMessage("something from Malon", /*german*/"", /*french*/"un cadeau de Malon"), + CustomMessage("something from Malon", /*german*/"ein Geschenk von Malon", /*french*/"un cadeau de Malon"), // /*spanish*/un obsequio de Malon - CustomMessage("a song sung by frogs", /*german*/"", /*french*/"une chanson aimée des grenouilles"), + CustomMessage("a song sung by frogs", /*german*/"ein von Fröschen gesungenes Lied", /*french*/"une chanson aimée des grenouilles"), // /*spanish*/una melodía de ranas - CustomMessage("something to cross a broken bridge", /*german*/"", /*french*/"une chose pour traverser un pont brisé") + CustomMessage("something to cross a broken bridge", /*german*/"etwas, um eine kaputte Brücke zu überqueren", /*french*/"une chose pour traverser un pont brisé") // /*spanish*/algo para cruzar un puente roto }, { - CustomMessage("a horse", /*german*/"", /*french*/"un fidèle destrier"), + CustomMessage("a horse", /*german*/"ein Pferd", /*french*/"un fidèle destrier"), // /*spanish*/una yegua - CustomMessage("a four legged friend", /*german*/"", /*french*/"un puissant animal")}); + CustomMessage("a four legged friend", /*german*/"ein vierbeiniger Freund", /*french*/"un puissant animal")}); // /*spanish*/una amiga cuadrúpeda //What is this used for? - hintTextTable[RHT_HINT_MYSTERIOUS] = HintText(CustomMessage("something mysterious", /*german*/"etwas Unvorhergesehenes", /*french*/"un sacré mystère")); + hintTextTable[RHT_HINT_MYSTERIOUS] = HintText(CustomMessage("something mysterious", /*german*/"etwas Mysteriöses", /*french*/"un sacré mystère")); // /*spanish*/algo misterioso - hintTextTable[RHT_MYSTERIOUS_ITEM] = HintText(CustomMessage("mysterious item", /*german*/"mysteriösen Gegenstand", /*french*/"objet mystérieux")); + hintTextTable[RHT_MYSTERIOUS_ITEM] = HintText(CustomMessage("mysterious item", /*german*/"mysteriöser Gegenstand", /*french*/"objet mystérieux")); // /*spanish*/algo misterioso } -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 526c7b3ae..e465d2575 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -12,331 +12,331 @@ std::unordered_map Rando::StaticData::itemNameToEnum void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); - itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); - // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Value Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index - itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Espada Master"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); + // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Value Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index + itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Master-Schwert"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MASTER_SWORD].SetCustomDrawFunc(Randomizer_DrawMasterSword); - itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Messer des Riesen" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegel-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein der Qualen" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo Karte" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Langschwert" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeil" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DOUBLE_DEFENSE].SetCustomDrawFunc(Randomizer_DrawDoubleDefense); // Trade Quest Items - itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Taschenei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Cojiro" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Seltsamer Pilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Seltsamer Trank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Wilderer-Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Schwert des gebrochenen Goronen" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Verschreibung" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Augapfel-Frosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Supertropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Quittung" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Henni" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbrochenes Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Zertifikat" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Skulltula Token - itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); + itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Brieftasche" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Skala" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Kriechgrube" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronenschwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true); // Bottles - itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER,GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); // Songs - itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Sarias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Das Lied der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Das Lied der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Lied der Stürme" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Wald-Minuett" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne der Schatten " }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem des Geistes" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Präludium des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Feuertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Wassertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Geistertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Schlüssel für den Boss des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Ganons Schloss-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Waldtempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Feuertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Wassertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Geisttempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Schattentempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Boden des Brunnens Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, Text{ "Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Trainingsgelände Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, Text{ "Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Gerudo-Festung Kleiner Schlüssel" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Ganons Schloss Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); - itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); + itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Waldtempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Feuertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Wassertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Geisttempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schattentempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Boden des Brunnens Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, Text{ "Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Trainingsgelände Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, Text{ "Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUNDS_KEYS, RHT_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Gerudo Festung Schlüsselanhänger" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Ganons Schloss Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Wald Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST,0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Feuer Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Wasser Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER,0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Geist Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT,0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Schatten Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW,0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Licht Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT,0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Generic Items - itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüne Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blaue Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Rote Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Lila Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesige Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herz-Container" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, LOGIC_NONE, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Pez" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, LOGIC_NONE, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Fisch" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); // Refills - itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, LOGIC_NONE, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, LOGIC_NONE, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBS_20] = Item(RG_BOMBS_20, Text{ "Bombs (20)", "Bombes (20)", "Bomben (20)" }, ITEMTYPE_REFILL, GI_BOMBS_20, false, LOGIC_NONE, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Bombchus (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, LOGIC_BOMBCHUS_5, RHT_BOMBCHU_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Bombchus (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, LOGIC_BOMBCHUS_10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Bombchus (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, LOGIC_BOMBCHUS_20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BOMBCHU_DROP] = Item(RG_BOMBCHU_DROP, Text{ "Bombchu Drop", "Drop Missiles", "Bombchus" }, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, LOGIC_BOMBCHU_DROP, RHT_NONE, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, LOGIC_NONE, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, LOGIC_NONE, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, LOGIC_NONE, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, LOGIC_NONE, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stick (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Rotes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Grünes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Blaues Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, LOGIC_NONE, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, LOGIC_NONE, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBS_20] = Item(RG_BOMBS_20, Text{ "Bombs (20)", "Bombes (20)", "Bomben (20)" }, ITEMTYPE_REFILL, GI_BOMBS_20, false, LOGIC_NONE, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Krabbelminen (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, LOGIC_BOMBCHUS_5, RHT_BOMBCHU_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Krabbelminen (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, LOGIC_BOMBCHUS_10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Krabbelminen (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, LOGIC_BOMBCHUS_20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BOMBCHU_DROP] = Item(RG_BOMBCHU_DROP, Text{ "Bombchu Drop", "Drop Missiles", "Krabbelminen" }, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, LOGIC_BOMBCHU_DROP, RHT_NONE, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, LOGIC_NONE, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, LOGIC_NONE, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, LOGIC_NONE, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, LOGIC_NONE, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); // Treasure Game - itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhen-Minispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüne Rupie (Schatztruhe-Minispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE,ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); // Shop - itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuss kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15); - itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60); - itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90); - itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25); - itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuss kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stick kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200); - itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100); - itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylianischer Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80); - itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40); - itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200); - itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300); - itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBCHU_10] = Item(RG_BUY_BOMBCHU_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Bomchu kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); - itemTable[RG_BUY_BOMBCHU_20] = Item(RG_BUY_BOMBCHU_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Bomchu kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); - itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, false, 0); - itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); - itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20); - itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80); - itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120); - itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35); - itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); - itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15); + itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60); + itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90); + itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25); + itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuß kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stab kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); + itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200); + itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100); + itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylia-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80); + itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40); + itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200); + itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300); + itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); + itemTable[RG_BUY_BOMBCHU_10] = Item(RG_BUY_BOMBCHU_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); + itemTable[RG_BUY_BOMBCHU_20] = Item(RG_BUY_BOMBCHU_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); + itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, false, 0); + itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); + itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); + itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20); + itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80); + itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120); + itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35); + itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); + itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); // Misc. - itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "", "" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "", "Gohmas Seele" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "", "König Dodongos Seele" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_KING_DODONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "", "" }, ITEMTYPE_ITEM, 0xE2, true, LOGIC_CAN_SUMMON_BARINADE, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "", "Barinades Seele" }, ITEMTYPE_ITEM, 0xE2, true, LOGIC_CAN_SUMMON_BARINADE, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BARINADE_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE3, true, LOGIC_CAN_SUMMON_PHANTOMGANON, RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "", "Phantom-Ganons Seele" }, ITEMTYPE_ITEM, 0xE3, true, LOGIC_CAN_SUMMON_PHANTOMGANON, RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_PHANTOM_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "", "" }, ITEMTYPE_ITEM, 0xE4, true, LOGIC_CAN_SUMMON_VOLVAGIA, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "", "Volvagias Seele" }, ITEMTYPE_ITEM, 0xE4, true, LOGIC_CAN_SUMMON_VOLVAGIA, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_VOLVAGIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "", "" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "", "Morphas Seele" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MORPHA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE6, true, LOGIC_CAN_SUMMON_BONGOBONGO, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "", "Bongo Bongos Seele" }, ITEMTYPE_ITEM, 0xE6, true, LOGIC_CAN_SUMMON_BONGOBONGO, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BONGO_BONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "", "" }, ITEMTYPE_ITEM, 0xE7, true, LOGIC_CAN_SUMMON_TWINROVA, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "", "Twinrovas Seele" }, ITEMTYPE_ITEM, 0xE7, true, LOGIC_CAN_SUMMON_TWINROVA, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "Ganons Seele" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Caña de Pescar" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI); - itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Botón A de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Taste A der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_A_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Botón C superior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Taste C-Oben der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_UP_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Botón C inferior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Taste C-Unten der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_DOWN_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Botón C izquierdo de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Taste C-Links der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_LEFT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Botón C derecho de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Taste C-Rechts der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "!!!", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "Unendliche Stab-Kapazität" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "!!!", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "!!!", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); - itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "!!!", "Deku-Stab-Tasche" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "!!!", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE); - itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE); + itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) - itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Großer Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberne Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldene Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Skala" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Skala" }, ITEMTYPE_ITEM, GI_SCALE_GOLD, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsene Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Reiche Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Bourse de Magnat", "Reiche Geldbörse" },/*FIXME: still says tycoon in french & german*/ ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Große Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLD, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsenengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Bourse d'Enfant", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku-Nuß-Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku-Nuß-Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku-Stab-Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku-Stab-Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); // Init itemNameToEnum for (auto& item : itemTable) { @@ -371,4 +371,4 @@ Item& Rando::StaticData::ItemFromGIID(const int giid) { std::array& Rando::StaticData::GetItemTable() { return itemTable; -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 01b3f49c9..e87e08229 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -111,7 +111,7 @@ static const char* englishRupeeNames[171] = { static const char* germanRupeeNames[41] = { "Rubine", "Mäuse", "Kröten", "Münzen", "Euro", "Mark", "Bananen", "Gummibären", "Bonbons", "Diamanten", "Bratwürste", "Bitcoin", "Dogecoin", "Monde", - "Sterne", "Brause UFOs", "Taler", "Sternis", "Schillinge", "Freunde", "Seelen", + "Sterne", "Brause UFOs", "Taler", "Sternis", "Schilling", "Freunde", "Seelen", "Gil", "Zenny", "Pfandflaschen", "Knochen", "Pilze", "Smaragde", "Kronkorken", "Pokédollar", "Brötchen", "EXP", "Wagenchips", "Moos", "Knete", "Kohle", "Kies", "Radieschen", "Diridari", "Steine", "Kartoffeln", "Penunze" @@ -235,13 +235,13 @@ void Randomizer::LoadHintMessages() { // Bow Shooting Gallery reminder CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, CustomMessage("Come back when you have your own&bow and you'll get a %rdifferent prize%w!", - "Komm wieder sobald du deinen eigenen&Bogen hast, um einen %rspeziellen Preis%w zu&erhalten!", + "Komm wieder sobald Du Deinen eigenen&Bogen hast, um einen %rspeziellen Preis%w zu&erhalten!", "J'aurai %rune autre récompense%w pour toi&lorsque tu auras ton propre arc.")); // Warp Song Mysterious text CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST, CustomMessage("Warp to&#a mysterious place?#&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", - "Zu&#ein mysteriöser Ort#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", + "Zu&#einem mysteriösen Ort#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", "Se téléporter vers&#un endroit mystérieux#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK!&Non#", {QM_RED, QM_GREEN})); @@ -297,11 +297,11 @@ void Randomizer::LoadMerchantMessages() { // Prices have a chance of being 0, and the "sell" message below doesn't really make sense for a free item, so adding a "free" variation here CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE, CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will give you a&%g[[item]]%w!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen &%g[[item]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch&dafür, dass Du mich verschont hast,&werde ich Dir einen &%g[[item]]%w geben!\x07\x10\xA3", "\x12\x38\x82" "J'me rends! Laisse-moi partir et en&échange, je te donne un &%g[[item]]%w! Vas-y prends le!\x07\x10\xA3")); CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM, CustomMessage("\x12\x38\x82" "All right! You win! In return for&sparing me, I will sell you a&%g[[item]]%w!&%r[[price]] Rupees%w it is!\x07\x10\xA3", - "\x12\x38\x82" "Aufgeben! Ich verkaufe dir einen&%g[[item]]%w&für %r[[price]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen&%g[[item]]%w&für %r[[price]] Rubine%w!\x07\x10\xA3", "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter&un %g[[item]]%w?&Ça fera %r[[price]] Rubis%w!\x07\x10\xA3")); //Carpet Salesman @@ -326,7 +326,7 @@ void Randomizer::LoadMerchantMessages() { CustomMessageManager::Instance->CreateMessage( Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, CustomMessage("I never thought I'd say this, but I'm &selling the last %rMagic Bean%w. %r99%w Rupees...\x1B&%gYes&No%w", - "\x1B&%gJa&Nein%w", + "Ich hätte nie gedacht, daß ich das&sage, aber ich verkaufe die letzte^%rWundererbse%w für %r99%w Rubine.&\x1B&%gJa&Nein%w", "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); } @@ -2480,7 +2480,7 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { messageEntry = CustomMessage( "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", - "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verließ%w hast.", + "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la Mrclé de son repaire%w."); } else { messageEntry = CustomMessage( @@ -2497,13 +2497,14 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { messageEntry = CustomMessage("You are still ill-equipped to face %rGanondorf%w." "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" - "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um deine Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", + "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){ messageEntry = CustomMessage( - "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it." - ); + "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", + "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", + ""); } else { messageEntry = CustomMessage( "If you're ready, then proceed.^Good luck.", @@ -2520,7 +2521,7 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { auto ctx = Rando::Context::GetInstance(); CustomMessage messageEntry = CustomMessage( "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", - "", + "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", "" ); @@ -2532,7 +2533,7 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { if (originalTextId == TEXT_FISHING_POND_START_MET) { messageEntry = CustomMessage( "Hey, mister! I remember you!&It's been a long time!^", - "", + "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", "" ) + messageEntry; } @@ -2552,7 +2553,7 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te if (randomizerInf >= RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1 && randomizerInf <= RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8) { shopItemName = { "Mysterious Item", - "Mysteriösen Gegenstand", + "Mysteriöser Gegenstand", "Objet Mystérieux" }; } else { @@ -2742,61 +2743,61 @@ void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", - "%cFehlt dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", + "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", - "%cManchmal kannst du den %rStahlhammer&%cstatt Bomben verwenden!", + "%cManchmal kannst Du den %rStahlhammer&%cstatt Bomben verwenden!", "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, { "%cThere are three %gbusiness scrubs %cin &Hyrule who sell %wmysterious items%c. Do&you know where they are?", - "%cEs gibt drei %gDeku-Händler %cin Hyrule&die mysteriöse Gegenstände&verkaufen. Weißt du wo Sie sind?", + "%cEs gibt drei %gDeku-Händler %cin Hyrule&die mysteriöse Gegenstände&verkaufen. Weißt Du wo sie sind?", "%cIl y a trois %gPestes Marchandes%c en&Hyrule qui vendent des %wobjets&mystérieux%c. Tu sais où elles " "sont?" }, { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", - "%cHängst du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", + "%cHängst Du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", - "%cWußtest du, daß du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", + "%cWußtest Du, daß Du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables " "mouvants%c?" }, { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", - "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem du von&der Baustelle aus mit einem " + "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem Du von&der Baustelle aus mit einem " "%rHuhn&%cspringst!", "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec " "une&%rcocotte%c!" }, { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", - "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?", + "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt Du schon&wo?", "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu " "le savais&déjà?" }, { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is " "junk!", - "%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört daß sich nur &%wzwei der Preise%c lohnen. Der " + "%cKennst Du die %wMinenbowlingbahn%c?&Ich habe gehört, daß sich nur &%wzwei der Preise%c lohnen. Der " "Rest&ist Krimskrams!", "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont " "intéréssant?" }, { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", - "%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen daß&man damit %rKrabbelminen " - "%cdetonieren&kann!", + "%cBenutzt Du auch genügend %wDeku-Nüsse%c?&Ich habe mal gesehen, daß&man damit %rKrabbelminen " + "%cdetonieren&lassen kann!", "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your " "safety!", - "%cVielleicht verbleibt dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " - "Dies&ist zu deiner Sicherheit!", + "%cVielleicht verbleibt Dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " + "Dies&ist zu Deiner Sicherheit!", "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. " "C'est pour ta&propre sécurité!" }, { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with " "%warrows%c!", - "%cNur weil du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&du sie immernoch mit %rFeuer " - "%coder&%wPfeilen %cdetonieren!", + "%cNur weil Du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&Du sie noch immer mit %rFeuer " + "%coder&%wPfeilen %cdetonieren lassen!", "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du " "%rFeu %cou avec des %wflèches%c!" }, @@ -2805,43 +2806,43 @@ void CreateNaviRandoMessages() { "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", - "%cIch habe gehört daß der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es " - "schonmal versucht einzusetzen?", + "%cIch habe gehört, daß der&%rFlammenderwisch %ceine Schwäche für&das %wMaster-Schwert %caufweist. Hast Du&es " + "schon einmal versucht einzusetzen?", "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as " "essayé?" }, { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", - "%cFehlt dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuch&Sie mit einem %wKrug %cabzuwerfen!", + "%cFehlt Dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuche&sie mit einem %wKrug %cabzuwerfen!", "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une " "%wjarre&%cà la figure?" }, { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", - "%cIch habe gehört daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " + "%cIch habe gehört, daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " "%cbeherbergt.", "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne " "contienne pas&d'%raraignée%c." }, { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a " "mask%c!", - "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür dich, aber Sie mögen&es nicht wenn du %wMasken " + "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür Dich, aber sie mögen&es nicht, wenn Du %wMasken " "trägst%c!", "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas " "trop apprécier&le fait que tu %wportes un masque%c!" }, { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", - "%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund %wneustarten%c!", + "%cSolltest Du irgendwo eingeschlossen&sein, mußt Du vielleicht Dein %wSpiel&speichern %cund %wneu starten%c!", "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater " "%cMedallions!", - "%cShiek wird dich in einem %rbrennenden&Dorf %ctreffen sobald du das Amulett&des %gWaldes%c, %rFeuers %cund " + "%cShiek wird Dich in einem %rbrennenden&Dorf %ctreffen, sobald Du das Amulett&des %gWaldes%c, %rFeuers %cund " "%bWassers&%cbesitzt.", "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du " "%rFeu&%cet de l'%bEau%c!" }, { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your " "foes!", - "%cSolltest du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku Stäbe&%czu kaufen! Diese sind " + "%cSolltest Du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku-Stäbe&%czu kaufen! Diese sind " "effektiv gegen&Widersacher!", "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? " "Ils&sont efficaces contre tes ennemis!" } @@ -2865,7 +2866,7 @@ void CreateIceTrapRandoMessages() { { "You just got %bPUNKED%w!", "Du wurdest %beiskalt%w erwischt!", "Ça me %bglace%w le sang!" }, - { "Stay %bfrosty%w, @.", "Es läuft dir %beiskalt%w den Rücken&hinunter, @.", "%bReste au frais%w, @." }, + { "Stay %bfrosty%w, @.", "Es läuft Dir %beiskalt%w den Rücken&hinunter, @.", "%bReste au frais%w, @." }, { "Take a %bchill pill%w, @.", "Bleib %bcool%w, @.", "Et c'est la douche %bfroide%w!" }, @@ -2879,7 +2880,7 @@ void CreateIceTrapRandoMessages() { { "It's a %bcold day%w in the Evil Realm.", "Es ist ein %kalter%w Tag im Herzen&von Hyrule.", "Est-ce que tu as déjà eu des sueurs&%bfroides%w?" }, - { "Getting %bcold feet%w?", "Bekommst du etwa %bkalte%w Füße?", + { "Getting %bcold feet%w?", "Bekommst Du etwa %bkalte%w Füße?", "La vengeance est un plat qui se mange&%bfroid%w!" }, { "Say hello to the %bZoras%w for me!", "Sag den %bZoras%w viele Grüße von mir!", @@ -2898,7 +2899,7 @@ void CreateIceTrapRandoMessages() { { "%bCold pun%w.", "%bEiskalt%w lässt du meine Seele&erfrier'n.", "Balance man...,&Cadence man...,&Trace la %bglace%w...,&c'est le Cooooolllll Rasta!" }, - { "The %bTitanic%w would be scared of you,&@.", "Die %bTitanic%w hätte Angst vor dir,&@.", + { "The %bTitanic%w would be scared of you,&@.", "Die %bTitanic%w hätte Angst vor Dir,&@.", "Le %bTitanic%w aurait peur de toi,&@." }, { "Oh no!", "Oh nein!", "Oh non!" }, @@ -2915,7 +2916,7 @@ void CreateIceTrapRandoMessages() { "Never gonna %bgive you up%w. Never&gonna %blet you down%w. Never gonna&run around and %bdesert you%w." }, { "Thank you %b@%w!&But your item is in another castle!", - "Danke %b@%w!&Aber der Gegenstand ist in&einem anderem Schloss!", + "Danke %b@%w!&Aber der Gegenstand ist in&einem anderem Schloß!", "Merci %b@%w!&Mais ton objet est dans un autre&château!" }, { "%bFREEZE%w! Don't move!", " Kalt. Kalt. Kälter. %bEISKALT%w!", @@ -2943,7 +2944,7 @@ void CreateFireTempleGoronMessages() { CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { { "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", - "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst du&%rDarunias Kind.%w Bist du " + "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " "adoptiert?", "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", }, @@ -2951,14 +2952,14 @@ void CreateFireTempleGoronMessages() { "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home " "and see my parents.", "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich " - "nicht,&weißt du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", + "nicht,&weißt Du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que " "je&ressemble à n'importe quel Goron?", }, { "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " "cake!!", - "Weißt du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " + "Weißt Du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " "Ich&muss dringend nach meinem Kuchen&sehen!!!", "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", @@ -2983,8 +2984,8 @@ void CreateFireTempleGoronMessages() { }, { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " "pressed it %b[[a_btn]]%w times.^Wow.", - "Weißt du über %b\x9f%w bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " - "erschienen sind...^Es scheint, dass du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", + "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " + "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." }, { @@ -2992,8 +2993,8 @@ void CreateFireTempleGoronMessages() { "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " "rupees!", "\x13\x1A" - "Hey, ist dir nicht zu warm?&Besorg dir doch eine Flasche&%rLon Lon-Milch%w, um dich&abzukühlen.^Kostet " - "dich auch nur %g30%w Rubine!", + "Hey, ist Dir nicht zu warm?&Besorge Dir doch eine Flasche&%rLon Lon-Milch%w, um Dich&abzukühlen.^Kostet " + "Dich auch nur %g30%w Rubine!", "\x13\x1A" "Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 " "rubis%w?^Il n'y a rien de mieux pour s'hydrater!", @@ -3001,7 +3002,7 @@ void CreateFireTempleGoronMessages() { { "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g " "when&you're not looking for it.%w^Hope that helps!", - "Pass auf, ich geb dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " + "Pass auf, ich gebe Dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " "%gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps " "aufsuchen!", "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le " @@ -3038,7 +3039,7 @@ void Randomizer::CreateCustomMessages() { "Félicitation! Vous avez trouvé %gGreg%w!"), GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", - "Du erhältst dem %gMaster-Schwert%w!", + "Du erhältst das %gMaster-Schwert%w!", "Vous obtenez %gl'Épée de Légende%w!"), GIMESSAGE(RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", @@ -3050,7 +3051,7 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"), GIMESSAGE(RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, "You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", - "Du erhältst ein %rBlaues Elexier%w!&Nutze es, um deine %rMagie- und&Energieleiste%w komplett&aufzufüllen!", + "Du erhältst ein %rBlaues Elixier%w!&Nutze es, um Deine %rMagie- und&Energieleiste%w komplett&aufzufüllen!", "Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre %rénergie vitale%w&ainsi que votre %gmagie%w!"), GIMESSAGE(RG_BOTTLE_WITH_FISH, ITEM_FISH, "You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", @@ -3066,11 +3067,11 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"), GIMESSAGE(RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, "You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!", - "Du erhältst ein %rRotes Elexier%w!&Nutze es, um deine %rEnergieleiste&%weinmalig komplett aufzufüllen!", + "Du erhältst ein %rRotes Elixier%w!&Nutze es, um Deine %rEnergieleiste&%weinmalig komplett aufzufüllen!", "Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"), GIMESSAGE(RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!", - "Du erhältst ein %rGrünes Elexier%w!&Nutze es, um deine %bMagieleiste&%weinmalig komplett aufzufüllen!", + "Du erhältst ein %rGrünes Elixier%w!&Nutze es, um Deine %bMagieleiste&%weinmalig komplett aufzufüllen!", "Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"), GIMESSAGE(RG_BOTTLE_WITH_POE, ITEM_POE, "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...", @@ -3107,11 +3108,11 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez une %rPetite Clé %w&du %pPuits%w!"), GIMESSAGE(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training &Grounds %wSmall Key!", - "Du erhältst einen %rKleinen&Schlüssel%w für die %yGerudo&Trainingsarena%w!", + "Du erhältst einen %rKleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!", "Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"), GIMESSAGE(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!", - "Du erhältst einen %rKleinen&Schlüssel%w für die %rGanons Schloß%w!", + "Du erhältst einen %rKleinen&Schlüssel%w für %rGanons Schloß%w!", "Vous obtenez une %rPetite Clé %w&du %rChâteau de Ganon%w!"), GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL, @@ -3144,7 +3145,7 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez un trousseau de&clés du %pPuits%w!"), GIMESSAGE(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, ITEM_KEY_SMALL, "You found a %yGerudo Training &Grounds %wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für die %yGerudo Trainingsarena%w!", + "Du erhältst ein %rSchlüsselbund%w&für die %yGerudo-Trainingsarena%w!", "Vous obtenez un trousseau de&clés du %yGymnase Gerudo%w!"), GIMESSAGE(RG_GANONS_CASTLE_KEY_RING, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wKeyring!", @@ -3264,12 +3265,12 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez un %rPaquet de&Haricots Magiques%w! Trouvez&un endroit approprié pour un&jardin et plantez-les.^Attendez ensuite que quelque&chose d'amusant se produise!"), GIMESSAGE(RG_TYCOON_WALLET, ITEM_WALLET_GIANT, "You got a %rTycoon's Wallet%w!&It's gigantic! Now you can carry&up to %y999 rupees%w!", - "Du erhältst die %rGoldene&Geldbörse%w! Die größte aller&Geldbörsen! Jetzt kannst Du bis&zu %y999 Rubine%w mit dir führen!", + "Du erhältst die %rGoldene&Geldbörse%w! Die größte aller&Geldbörsen! Jetzt kannst Du bis&zu %y999 Rubine%w mit Dir führen!", "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y999 rubis%w!&C'est gigantesque!"), GIMESSAGE(RG_CHILD_WALLET, ITEM_WALLET_ADULT, "You got a %rChild's Wallet%w!&Now you can carry&up to %y99 rupees%w!", - "Du erhältst die %rGoldene&Geldbörse%w! Jetzt kannst Du bis&zu %y99 Rubine%w mit dir führen!",//FIXME: still says tycoon - "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y99 rubis%w!"),//FIXME: still says tycoon + "Du erhältst die %rKindergeldbörse%w!&Jetzt kannst Du bis&zu %y99 Rubine%w mit Dir führen!", + "Vous obtenez la %rBourse d'Enfant%w!&Elle peut contenir jusqu'à %y99 rubis%w!"), GIMESSAGE_UNTRANSLATED(RG_GOHMA_SOUL, ITEM_BIG_POE, "You found the soul for %gGohma%w!"), GIMESSAGE_UNTRANSLATED(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, "You found the soul for %rKing&Dodongo%w!"), diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 2d281d7a8..addfc703a 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -153,7 +153,7 @@ extern "C" void OTRMessage_Init() TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHU_10_DESC, - CustomMessage("\x08%rBombchu (10 pieces) 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " + CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " "self-propelled time&bomb!\x09\x0A", "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " "Distanzwaffe&einsetzen kannst!\x09\x0A", @@ -174,17 +174,17 @@ extern "C" void OTRMessage_Init() CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", - "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herteile gesammelt!", + "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", - "Du siehst gelangweilt aus.&Willst du einen Spaziergang machen?\x1B&%gJa&Nein%w", + "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w")); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_FISHERMAN_LEAVE, CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", - "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest du aufhören?&\x1B&%gJa&Nein%w", //TODO Used AI translation as placeholder + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder } From 16aaf2f93995d421d3a17a77106811f552f02012 Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 12 Aug 2024 19:39:44 -0400 Subject: [PATCH 298/300] Tweak: Implement better extended culling options (#4285) * implement better culling * change draw distance to a slider * remove testing code * tweak --- soh/include/functions.h | 2 + soh/soh/Enhancements/presets.h | 2 + soh/soh/SohMenuBar.cpp | 33 ++++- soh/src/code/z_actor.c | 128 ++++++++++++++---- .../actors/ovl_En_Wood02/z_en_wood02.c | 13 +- .../overlays/actors/ovl_Obj_Mure/z_obj_mure.c | 16 ++- .../actors/ovl_Obj_Mure2/z_obj_mure2.c | 24 +++- 7 files changed, 169 insertions(+), 49 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 553630672..f0015a2c2 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2460,6 +2460,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP); void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH); void Interface_RandoRestoreSwordless(void); +s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, + bool* shouldUpdate); // #endregion diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index cac60cdef..eb7c34e2a 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -211,6 +211,8 @@ const std::vector enhancementsCvars = { "gDisableLOD", "gDisableDrawDistance", "gDisableKokiriDrawDistance", + "gEnhancements.WidescreenActorCulling", + "gEnhancements.ExtendedCullingExcludeGlitchActors", "gLowResMode", "gDrawLineupTick", "gQuickBongoKill", diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index ee9a2708d..ade4f7523 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -928,16 +928,39 @@ void DrawEnhancementsMenu() { } UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false); UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) { - if (CVarGetInteger("gDisableDrawDistance", 0) == 0) { + if (UIWidgets::EnhancementSliderInt("Increase Actor Draw Distance: %dx", "##IncreaseActorDrawDistance", + "gDisableDrawDistance", 1, 5, "", 1, true, false)) { + if (CVarGetInteger("gDisableDrawDistance", 1) <= 1) { CVarSetInteger("gDisableKokiriDrawDistance", 0); } } - UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVarGetInteger("gDisableDrawDistance", 0) == 1) { + UIWidgets::Tooltip("Increases the range in which actors/objects are drawn"); + if (CVarGetInteger("gDisableDrawDistance", 1) > 1) { UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); - UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); + UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this " + "will remove their draw distance"); } + UIWidgets::PaddedEnhancementCheckbox("Widescreen Actor Culling", "gEnhancements.WidescreenActorCulling", + true, false); + UIWidgets::Tooltip("Adjusts the horizontal culling plane to account for widescreen resolutions"); + UIWidgets::PaddedEnhancementCheckbox( + "Cull Glitch Useful Actors", "gEnhancements.ExtendedCullingExcludeGlitchActors", true, false, + !CVarGetInteger("gEnhancements.WidescreenActorCulling", 0) && + CVarGetInteger("gDisableDrawDistance", 1) <= 1, + "Requires Actor Draw Distance to be increased or Widescreen Actor Culling enabled"); + UIWidgets::Tooltip( + "Exclude actors that are useful for glitches from the extended culling ranges.\n" + "Some actors may still draw in the extended ranges, but will not \"update\" so that certain " + "glitches that leverage the original culling requirements will still work.\n" + "\n" + "The following actors are excluded:\n" + "- White clothed Gerudos\n" + "- King Zora\n" + "- Gossip Stones\n" + "- Boulders\n" + "- Blue Warps\n" + "- Darunia\n" + "- Gold Skulltulas"); UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gLowResMode", true, false); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", "gDrawLineupTick", true, false); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 0accb49d0..3ccb62bd7 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1208,14 +1208,6 @@ void Actor_Init(Actor* actor, PlayState* play) { actor->uncullZoneForward = 1000.0f; actor->uncullZoneScale = 350.0f; actor->uncullZoneDownward = 700.0f; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room - && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence - && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning - && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room - actor->uncullZoneForward = 32767.0f; - actor->uncullZoneScale = 32767.0f; - actor->uncullZoneDownward = 32767.0f; - } CollisionCheck_InitInfo(&actor->colChkInfo); actor->floorBgId = BGCHECK_SCENE; ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); @@ -2857,34 +2849,93 @@ s32 func_800314B0(PlayState* play, Actor* actor) { s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { f32 var; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room - && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence - && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning - && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room - return true; - } - if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) { var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3; - // #region SoH [Widescreen support] - // Doors will cull quite noticeably on wider screens. For these actors the zone is increased - f32 limit = 1.0f; - if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger("gIncreaseDoorUncullZones", 1)) { - limit = 2.0f; - } - - if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < limit) && - (((arg2->y + actor->uncullZoneDownward) * var) > -limit) && - (((arg2->y - actor->uncullZoneScale) * var) < limit)) { + if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) && + (((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) && + (((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) { return true; } - // #endregion } return false; } +// #region SOH [Enhancements] Allows us to increase the draw and update distance independently, +// mostly a modified version of the function above and additional tweaks for some specfic actors +s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, + bool* shouldUpdate) { + f32 clampedProjectedW; + + // Check if the actor passes its original/vanilla culling requirements + if (func_800314D4(play, actor, projectedPos, projectedW)) { + *shouldUpdate = true; + *shouldDraw = true; + return true; + } + + // Skip cutscne actors that depend on culling to hide from camera pans + if (actor->id == ACTOR_EN_VIEWER) { + return false; + } + + s32 multiplier = CVarGetInteger("gDisableDrawDistance", 1); + multiplier = MAX(multiplier, 1); + + // Some actors have a really short forward value, so we need to add to it before the multiplier to increase the + // final strength of the forward culling + f32 adder = (actor->uncullZoneForward < 500) ? 1000.0f : 0.0f; + + if ((projectedPos->z > -actor->uncullZoneScale) && + (projectedPos->z < (((actor->uncullZoneForward + adder) * multiplier) + actor->uncullZoneScale))) { + clampedProjectedW = (projectedW < 1.0f) ? 1.0f : 1.0f / projectedW; + + f32 ratioAdjusted = 1.0f; + + if (CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) { + f32 originalAspectRatio = 4.0f / 3.0f; + f32 currentAspectRatio = OTRGetAspectRatio(); + ratioAdjusted = MAX(currentAspectRatio / originalAspectRatio, 1.0f); + } + + if ((((fabsf(projectedPos->x) - actor->uncullZoneScale) * (clampedProjectedW / ratioAdjusted)) < 1.0f) && + (((projectedPos->y + actor->uncullZoneDownward) * clampedProjectedW) > -1.0f) && + (((projectedPos->y - actor->uncullZoneScale) * clampedProjectedW) < 1.0f)) { + + if (CVarGetInteger("gEnhancements.ExtendedCullingExcludeGlitchActors", 0)) { + // These actors are safe to draw without impacting glitches + if ((actor->id == ACTOR_OBJ_BOMBIWA || actor->id == ACTOR_OBJ_HAMISHI || + actor->id == ACTOR_EN_ISHI) || // Boulders (hookshot through collision) + actor->id == ACTOR_EN_GS || // Gossip stones (text delay) + actor->id == ACTOR_EN_GE1 || // White gerudos (gate clip/archery room transition) + actor->id == ACTOR_EN_KZ || // King Zora (unfreeze glitch) + actor->id == ACTOR_EN_DU || // Darunia (Fire temple BK skip) + actor->id == ACTOR_DOOR_WARP1 // Blue warps (wrong warps) + ) { + *shouldDraw = true; + return true; + } + + // Skip these actors entirely as their draw funcs impacts glitches + if ((actor->id == ACTOR_EN_SW && + (((actor->params & 0xE000) >> 0xD) == 1 || + ((actor->params & 0xE000) >> 0xD) == 2)) // Gold Skulltulas (hitbox at 0,0) + ) { + return false; + } + } + + *shouldDraw = true; + *shouldUpdate = true; + return true; + } + } + + return false; +} +// #endregion + void func_800315AC(PlayState* play, ActorContext* actorCtx) { s32 invisibleActorCounter; Actor* invisibleActors[INVISIBLE_ACTOR_MAX]; @@ -2920,18 +2971,35 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) { } } + // #region SOH [Enhancement] Extended culling updates + bool shipShouldDraw = false; + bool shipShouldUpdate = false; if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) { - if (func_800314B0(play, actor)) { - actor->flags |= ACTOR_FLAG_ACTIVE; + if (CVarGetInteger("gDisableDrawDistance", 1) > 1 || + CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) { + Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw, + &shipShouldUpdate); + + if (shipShouldUpdate) { + actor->flags |= ACTOR_FLAG_ACTIVE; + } else { + actor->flags &= ~ACTOR_FLAG_ACTIVE; + } } else { - actor->flags &= ~ACTOR_FLAG_ACTIVE; + if (func_800314B0(play, actor)) { + actor->flags |= ACTOR_FLAG_ACTIVE; + } else { + actor->flags &= ~ACTOR_FLAG_ACTIVE; + } } } actor->isDrawn = false; if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) { - if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE))) { + if ((actor->init == NULL) && (actor->draw != NULL) && + ((actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE)) || shipShouldDraw)) { + // #endregion if ((actor->flags & ACTOR_FLAG_LENS) && ((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) || play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) { diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 4adb7afe7..0ff04f5db 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -101,13 +101,18 @@ static f32 sSpawnSin; s32 EnWood02_SpawnZoneCheck(EnWood02* this, PlayState* play, Vec3f* pos) { f32 phi_f12; - if (CVarGetInteger("gDisableDrawDistance", 0) != 0) { - return true; - } - SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, pos, &this->actor.projectedPos, &this->actor.projectedW); + // #region SOH [Enhancement] Use the extended culling calculation + if (CVarGetInteger("gDisableDrawDistance", 0) || CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) { + bool shipShouldDraw = false; + bool shipShouldUpdate = false; + return Ship_CalcShouldDrawAndUpdate(play, &this->actor, &this->actor.projectedPos, this->actor.projectedW, + &shipShouldDraw, &shipShouldUpdate); + } + // #endregion + phi_f12 = ((this->actor.projectedW == 0.0f) ? 1000.0f : fabsf(1.0f / this->actor.projectedW)); if ((-this->actor.uncullZoneScale < this->actor.projectedPos.z) && diff --git a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c index 2f5cf4ee3..2821b47fe 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c @@ -275,7 +275,12 @@ void ObjMure_InitialAction(ObjMure* this, PlayState* play) { } void ObjMure_CulledState(ObjMure* this, PlayState* play) { - if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] || CVarGetInteger("gDisableDrawDistance", 0) != 0) { + // #region SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1); + distanceMultiplier = MAX(distanceMultiplier, 1); + + if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] * distanceMultiplier) { + // #endregion this->actionFunc = ObjMure_ActiveState; this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_SpawnActors(this, play); @@ -398,8 +403,13 @@ static ObjMureActionFunc sTypeGroupBehaviorFunc[] = { void ObjMure_ActiveState(ObjMure* this, PlayState* play) { ObjMure_CheckChildren(this, play); - if (sZClip[this->type] + 40.0f <= fabsf(this->actor.projectedPos.z) && - CVarGetInteger("gDisableDrawDistance", 1) != 0) { + + // #region SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1); + distanceMultiplier = MAX(distanceMultiplier, 1); + + if ((sZClip[this->type] + 40.0f) * distanceMultiplier <= fabsf(this->actor.projectedPos.z)) { + // #endregion this->actionFunc = ObjMure_CulledState; this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_KillActors(this, play); diff --git a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c index b883072b9..1b8905ee2 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c @@ -190,8 +190,7 @@ void func_80B9A658(ObjMure2* this) { void func_80B9A668(ObjMure2* this, PlayState* play) { if (Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z) < - (sDistSquared1[this->actor.params & 3] * this->unk_184) || - CVarGetInteger("gDisableDrawDistance", 0) != 0) { + (sDistSquared1[this->actor.params & 3] * this->unk_184)) { this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure2_SpawnActors(this, play); func_80B9A6E8(this); @@ -205,12 +204,8 @@ void func_80B9A6E8(ObjMure2* this) { void func_80B9A6F8(ObjMure2* this, PlayState* play) { func_80B9A534(this); - if (CVarGetInteger("gDisableDrawDistance", 0) != 0) { - return; - } - if ((sDistSquared2[this->actor.params & 3] * this->unk_184) <= - Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) { + Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) { this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure2_CleanupAndDie(this, play); func_80B9A658(this); @@ -225,5 +220,20 @@ void ObjMure2_Update(Actor* thisx, PlayState* play) { } else { this->unk_184 = 4.0f; } + + // SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger("gDisableDrawDistance", 1); + if (CVarGetInteger("gEnhancements.WidescreenActorCulling", 0) || distanceMultiplier > 1) { + f32 originalAspectRatio = 4.0f / 3.0f; + f32 currentAspectRatio = OTRGetAspectRatio(); + // Adjust ratio difference based on field of view testing + f32 ratioAdjusted = 1.0f + (MAX(currentAspectRatio / originalAspectRatio, 1.0f) / 1.5f); + // Distance multiplier is squared due to the checks above for squared distances + distanceMultiplier = SQ(MAX(distanceMultiplier, 1)); + + // Prefer the largest of the three values + this->unk_184 = MAX(MAX((f32)distanceMultiplier, ratioAdjusted), this->unk_184); + } + this->actionFunc(this, play); } From 0bc6ca08e0549ec2ce780e6dd1295f84a194cc25 Mon Sep 17 00:00:00 2001 From: Archez Date: Mon, 12 Aug 2024 23:26:30 -0400 Subject: [PATCH 299/300] Bump MacReady Golf (#4279) --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c8644af4..6381f803a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,9 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(Ship VERSION 8.0.5 LANGUAGES C CXX) -set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "") -set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") +project(Ship VERSION 8.0.6 LANGUAGES C CXX) +set(PROJECT_BUILD_NAME "MacReady Golf" CACHE STRING "" FORCE) +set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh) add_compile_options($<$:/MP>) From bfba2a180ad4ab3d215982889a2dbc141c0017e0 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 14 Aug 2024 22:27:32 -0700 Subject: [PATCH 300/300] Fix tricks menu (#4278) * Fix tricks not getting disabled by button click. * Fix area trees not collapsing on enabled side of tricks list. * Fix difficulty tag button order for Linux. * Fix Collapse All, Open All, and Disable All. Prevent Disable All from disabling all despite areas being collapsed. --- .../Enhancements/randomizer/randomizer.cpp | 57 ++++++++----------- soh/soh/Enhancements/randomizer/tricks.cpp | 2 +- soh/soh/Enhancements/randomizer/tricks.h | 3 +- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index e87e08229..c25aca93a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2169,7 +2169,7 @@ void RandomizerSettingsWindow::DrawElement() { {RA_GANONS_CASTLE, true} }; - static std::unordered_map showTag { + static std::map showTag { {Rando::Tricks::Tag::NOVICE,true}, {Rando::Tricks::Tag::INTERMEDIATE,true}, {Rando::Tricks::Tag::ADVANCED,true}, @@ -2236,22 +2236,14 @@ void RandomizerSettingsWindow::DrawElement() { window->DC.CurrLineTextBaseOffset = 0.0f; if (ImGui::Button("Collapse All##disabled")) { - for (int i = 0; i < RT_MAX; i++) { - auto option = mSettings->GetTrickOption(static_cast(i)); - if (!option.IsHidden() && !enabledTricks.count(static_cast(i)) && - !option.IsGlitch()) { - areaTreeDisabled[option.GetArea()] = false; - } + for (int i = 0; i < RA_MAX; i++) { + areaTreeDisabled[static_cast(i)] = false; } } ImGui::SameLine(); if (ImGui::Button("Open All##disabled")) { - for (int i = 0; i < RT_MAX; i++) { - auto option = mSettings->GetTrickOption(static_cast(i)); - if (option.IsHidden() && !enabledTricks.count(static_cast(i)) && - !option.IsGlitch()) { - areaTreeDisabled[option.GetArea()] = false; - } + for (int i = 0; i < RA_MAX; i++) { + areaTreeDisabled[static_cast(i)] = true; } } ImGui::SameLine(); @@ -2288,15 +2280,15 @@ void RandomizerSettingsWindow::DrawElement() { } } if (hasTricks) { - ImGui::TreeNodeSetOpen(ImGui::GetID(Rando::Tricks::GetRTAreaName(area).c_str()), areaTreeDisabled[area]); + ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetRTAreaName(area) + "##disabled").c_str()), areaTreeDisabled[area]); ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode(Rando::Tricks::GetRTAreaName(area).c_str())) { + if (ImGui::TreeNode((Rando::Tricks::GetRTAreaName(area) + "##disabled").c_str())) { for (auto rt : trickIds) { auto option = mSettings->GetTrickOption(rt); if (!option.IsHidden() && trickSearch.PassFilter(option.GetName().c_str()) && !enabledTricks.count(rt) && Rando::Tricks::CheckRTTags(showTag, option.GetTags()) && !option.IsGlitch()) { - ImGui::TreeNodeSetOpen(ImGui::GetID(Rando::Tricks::GetRTAreaName(option.GetArea()).c_str()), areaTreeDisabled[option.GetArea()]); + ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetRTAreaName(option.GetArea()) + "##disabled").c_str()), areaTreeDisabled[option.GetArea()]); ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::ArrowButton(std::to_string(rt).c_str(), ImGuiDir_Right)) { enabledTricks.insert(rt); @@ -2329,23 +2321,16 @@ void RandomizerSettingsWindow::DrawElement() { ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + if (ImGui::Button("Collapse All##enabled")) { - for (int i = 0; i < RT_MAX; i++) { - auto option = mSettings->GetTrickOption(static_cast(i)); - if (!option.IsHidden() && enabledTricks.count(static_cast(i)) && - !option.IsGlitch()) { - areaTreeDisabled[option.GetArea()] = false; - } + for (int i = 0; i < RA_MAX; i++) { + areaTreeEnabled[static_cast(i)] = false; } } ImGui::SameLine(); if (ImGui::Button("Open All##enabled")) { - for (int i = 0; i < RT_MAX; i++) { - auto option = mSettings->GetTrickOption(static_cast(i)); - if (option.IsHidden() && enabledTricks.count(static_cast(i)) && - !option.IsGlitch()) { - areaTreeDisabled[option.GetArea()] = false; - } + for (int i = 0; i < RA_MAX; i++) { + areaTreeEnabled[static_cast(i)] = true; } } ImGui::SameLine(); @@ -2356,7 +2341,7 @@ void RandomizerSettingsWindow::DrawElement() { trickSearch.PassFilter(option.GetName().c_str()) && areaTreeEnabled[option.GetArea()] && Rando::Tricks::CheckRTTags(showTag, option.GetTags())) { - enabledTricks.insert(static_cast(i)); + enabledTricks.erase(static_cast(i)); } } std::string enabledTrickString = ""; @@ -2364,7 +2349,11 @@ void RandomizerSettingsWindow::DrawElement() { enabledTrickString += std::to_string(enabledTrickIt); enabledTrickString += ","; } - CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); + if (enabledTricks.size() == 0) { + CVarClear(CVAR_RANDOMIZER_SETTING("EnabledTricks")); + } else { + CVarSetString(CVAR_RANDOMIZER_SETTING("EnabledTricks"), enabledTrickString.c_str()); + } Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } @@ -2382,18 +2371,18 @@ void RandomizerSettingsWindow::DrawElement() { } } if (hasTricks) { - ImGui::TreeNodeSetOpen(ImGui::GetID(Rando::Tricks::GetRTAreaName(area).c_str()), areaTreeDisabled[area]); + ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetRTAreaName(area) + "##enabled").c_str()), areaTreeEnabled[area]); ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode(Rando::Tricks::GetRTAreaName(area).c_str())) { + if (ImGui::TreeNode((Rando::Tricks::GetRTAreaName(area) + "##enabled").c_str())) { for (auto rt : trickIds) { auto option = mSettings->GetTrickOption(rt); if (!option.IsHidden() && trickSearch.PassFilter(option.GetName().c_str()) && enabledTricks.count(rt) && Rando::Tricks::CheckRTTags(showTag, option.GetTags()) && !option.IsGlitch()) { - ImGui::TreeNodeSetOpen(ImGui::GetID(Rando::Tricks::GetRTAreaName(option.GetArea()).c_str()), areaTreeDisabled[option.GetArea()]); + ImGui::TreeNodeSetOpen(ImGui::GetID((Rando::Tricks::GetRTAreaName(option.GetArea()) + "##enabled").c_str()), areaTreeEnabled[option.GetArea()]); ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::ArrowButton(std::to_string(rt).c_str(), ImGuiDir_Left)) { - enabledTricks.insert(rt); + enabledTricks.erase(rt); std::string enabledTrickString = ""; for (auto enabledTrickIt : enabledTricks) { enabledTrickString += std::to_string(enabledTrickIt); diff --git a/soh/soh/Enhancements/randomizer/tricks.cpp b/soh/soh/Enhancements/randomizer/tricks.cpp index 8172f2a55..4828dde7b 100644 --- a/soh/soh/Enhancements/randomizer/tricks.cpp +++ b/soh/soh/Enhancements/randomizer/tricks.cpp @@ -6,7 +6,7 @@ namespace Rando { return rtAreaNames.at(area); } - bool Tricks::CheckRTTags(const std::unordered_map &showTag, const std::set &rtTags) { + bool Tricks::CheckRTTags(const std::map &showTag, const std::set &rtTags) { if (rtTags.empty()) { return false; } diff --git a/soh/soh/Enhancements/randomizer/tricks.h b/soh/soh/Enhancements/randomizer/tricks.h index c473d5e3b..77d3a0b23 100644 --- a/soh/soh/Enhancements/randomizer/tricks.h +++ b/soh/soh/Enhancements/randomizer/tricks.h @@ -7,6 +7,7 @@ #include "randomizerTypes.h" #include +#include #include @@ -25,7 +26,7 @@ namespace Rando { }; static const std::string& GetRTAreaName(RandomizerArea area); - static bool CheckRTTags(const std::unordered_map &showTag, const std::set &rtTags); + static bool CheckRTTags(const std::map &showTag, const std::set &rtTags); static std::string GetRTTagName(Tag tag); static ImVec4 GetRTTagColor(Tag tag); static void DrawTagChips(const std::set &rtTags);

bTjz!^O?X?aXd>t;;TMZsjB!pT#s{SBhi6F)$|> zQ2pX$^-xvSwD$sgl?~k+rDurmdhihy8%|b{rZW{ipFN?CLtNZ0%p)u>)a)|FRWp|8=Rdv8CU@_5_W zS`MF!mmAFQVPUK$kefJ9?X9-M#J%26Od8x}QvcsgTKhR~{{?UV58nPO-hPisQ9P~> zQ7+nf(Z7c^<-SJ_%2gWI#&PZtW-3ei&~tU*kJ@?bg%-*S-)BbqC`-@4=_!N)|8^=& zI14?&UsgSFoR_8Nw9`|FW$TD#VPfeC{<7+c^L1HzdT(;Sw-c%b{p>WfKn}+z_{*v% z`rWeh>~(rVB9+=YVp*7Q7J7oeta^GJKb56t&FLw`f_`=?Oe{UYUsgQ>j)Tk6v*Gj< zV%a)kS(sRQg1@YK`g}c8mY%-TQ-}rq>{OUodV;^Kde->5v@AWRoSs4~TSqJl6H8C< zm!@ZP9J1E+IOOoahI&tJWMo5^&+xTg9&=r8Ypq_MHTs^PH*M~xxbZZ!q0UmrTW5TQ zv2UKH>wFypj)A$u0G(r~Tg3BwW>hL1zY3Y4Z(Sxmzh}-pp>2Au{d+He(Y^rcUnBDj zKff1?ZlPL>S!G+E-y@C|FCM3N8;;{~M|-)e=l2k2AU=k6q-qh*@A+;VQs|x3CkqqK z(*31HDi8iBJ`SJxq;hDQ?92T8-q~Hp%_Hk3>ceIHj_eOiC5rm1ISKyT#LaX2y=UDv z&_-0+Y%iS0GVH>3Ik$NO53Rfy4%=-nsu{a-90QJlM?VAE-WQ+AxS3)<#D6jTbAQs@ zGN<1cN1PECH#ZrI^t-ec{qAJdetxgzeQ_5zhcs&5(D%wzm~a+xbHMy1#m$-D7k_2f zar4AjeR%yuqw6isv^^({;X%0mr}` zV?gzbyXSi^2^}`|ulB4ZqgeY<``*i`3GcmdoDml{hu0p|m(bLj+Hte}-ix=xy)SOK z1AlS-a%h1Z;%4xd6gQ{cZ>DnedoQei5%0Y`5g-%NEbqO1C&riBTkSU{?)83a(%^oR z`VW}2_B-DG2j2ci-u@tO|C32kJk{S<1*2TF^P=B-3EXo>pj@SKZ5-zgVWzUA554yS z{?eX1f}Us}W$8KX^b|sMt|$1*swa-~vh?)c?B0_I1?^l<@RwCjoUhB$v)Abv%Gt&F z7W`$^6a8*kde)qtx%32oS@rZdekx1PhSM{bp5QO5o&m?fW$EcVJ#*;^{<7-n^Yu(w zdQLe#bLk2Gvg%pm>(a9H44j_1^aOutdN$vCS=aSAmpadTsE&4%In_;|N3z9h!YceGYJ z&l=q}{feoldw)Z=uk3lpTXwFZ$8(;h>wFypj)6JGfa(`_&-Y&9;&-JD^{@7YlGnSqIhmXGycW}lT`7(M$H1ImK!sW}@%*0TGC6K0D--*L zZ*53Vm5;>CysS;gFClK$+wmt`+&rm%)9{GnE0vyQmCCY6+>LT%x=<}(#(D%Ch@0`Q z3;j+a^29y=Zld)&i73US-izX&-$R@c7dIOo$)Ea?_%!YLy_$=g4RuZa;`(J_!db-4 z;IG@bnaa`6@3H>&^Lwgo#kS2*`&MizzeAe({2rBfKx?u3xb>fC;@;YmOzItK(%>+Y z`cL8QPvz}5{`Tah7pw0cf8C`1%_c?hRDXJY59Okr7ybNRuNyxBFK@Ajc{N*JbJ1>+}re z?B;yS{AJY>{cc%$)|{TX^aOud^{jFHRF<9%r)Mrb!CzKAJ&uFR($jZ(=F$`VWz`ec zGiB*H<@C&@C-}>%C$3A&(lc;+=F$`VrRmvxes7Dp|Io$rdlwFlPjveY5vn6@3yS)h z?2lX4r?3^6~j)6xr1FBz~tUg!OaId}0 zs8rk-20g#mt7aNAqp`lb9(+VUlZG^%py>Im-M0*||Gnc2rT*2PwI%sIYR4g896t_; zI0Nx9xT9bP`8?y0z8iI~{H0w7LeGHPM_GD$Z+GKXp`e}X3I4L` z>GN@3mY%&%&rr@Tj!*EHRZpC+%hI#v^vtCv_{*v%`rWehY&bo0=?VU_>KSnSRF2AGjMw5(i8k;)zjna(z5iNc6#R06a1y= z*&K)bShwSl=hVk0>YIB`xS&2Zu)Z!pXU!&#L;fUd3EAxQIAm~#xu4?3(~_=%+pl-L zwdbdkdqvrrt+R3rI0oh*1L|`VyW{(iiO&t$W01PPCEaKovzu`%<}a(B9v|mr=~;7n=F$`VWz`es>$3E0I6ZUe3I4L` ziGH^%J$J#*;^{<7*B@byetdQLk% zbLk2Gvg+ycb!l08dhc-8pP`_g-DlC)pUhvHp3QN{YjTc5o;b8=ECk$1E^!?4u1-ox zx7GJWYt!a_iW^T$YE$jkJKoy!)5*P}^d{>p90QJlIm*E9Iu3~;HCvXsISzSx{5T}y z48+GEt*CKG?K!8k0vy4N=JqSo`&-*ox zEB+6UEB?l$wcnc5`(NJv0B`>tZ~p^t-)T}n!?+d7MLREg9J1G42ZC~ycGk}IcUd!D z2SU$)+ecY?)|{TX^aOut*Y(iT=i|IAJsVEXTzZ1Pta{>nU6!7{(=(Tz;4iD5=y%J~ zbIR$NOHc5ZRnLIqr?T`6oSwP#1b6u4Q@RwCjkFQJ1(zD_84CUDe5I{O6qGkjuvgE)_M{wdN zhpf4ANYM_H`eb3kS&T!1KZ=iYjYG2jMT|qn{kEg5L6&jIwbFs})b{*8@wno{Jg&IQ zq(S9={X3BUe3RDpGO4$ZNrT7m_I*u?;+x|fTrS#q(c_T5yAA~9D($SD(>NsfOS=w) zo;7YCW$8KP^vtCv_{*xN$H#eDdInCnU6!8HPS0F=g1@YKqTek`Pw(^5 zep^&-4rV*=KfzyCJrO^ZrDw0xQ?%R8^#p%e^+X(8mYy}IXD&U#UsgSFJyVvR4X0-= zJ;7gAJ$=3|ElW?|>6uGU@Rz1%a~yKn|LOY?o&P>0f0y;_`smQWnz+ZYMLlA(iQ|y} z9&6t9O7lMCV@+J<#?zAe@b>E+Z|(W%bS59RGoHYtk7xRuA{qMa8#4mstn13|e;J8S1O z4hjC!t^=Vb+DBP>22RghdV;^Kdg3@QOV4SiXD&U#UsgSFzAj5o?+elMyr|q9%yxdh z1%FxfM88{>p1n>_(QZ4}6Z~b>GvN5CEIn&Z&s=(fzpQ%t90!-BXT#~4OHc5ZRnHn< z&y=O7@AS;2C-}>%r^nZ&W$8KP^vtCv_)F8XIS%>aoa2xyHr5Ba`!H+bIONX+0|jKw z`;bpDakd*zONz+BuCwg1@xuK`i^Ro18I6XzX?OadrmsL-kuglWYcY5a16Z~b>6a8*kdQLe#bLk2Gvg%pm z_^B*C1E*&$J;7gAJw1+t%hGe&>6uGU@RwE3fUjrD($l-%#kZlLoySAqFRPwDUze7p zXRp&Ul(UQLPwJt;)ya>sK zCfYTq#Vq|`2fu0dLwVEp+|!3y`oRu< zhy2Fyg7Ut1%PoDFr626zS7Sevcl~wO^S^B{aepBp+^4>T( z*@s#B!47^q*bn8YwyEl8X6Xkz_<8s7@yGsGY&k^XG_&-B9sHKCAIkf|_rJdsv-E=< z{2J_s^2keMHXs=mYb^*wd$4|eeD{VgAV>`#7|yz8-5#Z3e!?BKVG{ZQV+e|lZ@ zzI%t1_Lbvh{a^<_pZ!oC?eC7;SN6U2Eqg`w2Rry}Wj~bngYTc!w3ZucJP~GKa@v&-t()q)h}MZIN}F8`0Zdnlt+F) z{mCn;U;UTkB7U%gpZC9f{INgzedDGRtCzm}fQTRL;J1YRP~J~=tg2pi>4DYHU3+bW zPuRh)!G0)j+t-#>gKvFHpJODSu!G+g_CtABf9!B|zMkxZ9^eyp@C(=v<m)+*OzEc<^Es?KcD?j-VbkksctKD%u7Gm!EY=3p}d>FenR!SFFdDO+4V?- z7udni|GlXn%KP!1=T_DEy84CBFN)L;cJSNEekhO5gL;1iQcchgcJQ0V{y3%fiMmNY z*un3RKk)GmKefL*Zoj>G>|%eggI|sPP~O%r|4sGHZ+cUUAMD__nf*}S_HEnx9@@FN z@7L4Q5nf;izbW=Zd34TI@k`78U=Q4fgSvO z_CtB9fA0I#)YQ_J{*Ue8H_gi^PaQvf)VHg1eWZS{gWn+!^6|(16n}j5s;j7e5kJ_$ zZ!`O$JX|0B`Jsm*ez1ez6#Jn(_z@>G;W&aF{C2P(%F}*)ZjpYlgP->hw@>ybKf-9^ zgdO~rupi2UpTQgAgdO}E?1%DTPwiXcgdP00upi0`{i5ej*ugJgKa|(>qn)VgDyFsn5r9Waj_#Lv#)DPt;y;Xa;yQTkw9sFwS zhy9XvbZ$}CaS=XY2fxkihw@bYv=6m4SwGmp&-=W&kBIUG=^q*uifJ z`=LBK?&unht{>(8UW_V_<+=)X@az48;S=Sl>+n9Mec#W1`pO6|u!G+!_CtAe zZA5LrKcD?j-v9n~M7NiJ{mzRb`oRu;s-nUO|u`$ zQ|DcMKBKlRb%!1N4!O?og7TE^RmF*ld2fvP!47^k_CtAZe$)KwkAAp9-S3IUb+Ciq zX7)pQ`uq?RXTc7BQ|yQG=$_(x|MBrv`+6F7@Y}(DDDM*=KeA88A~?Um4u0PCh8L7a z9KQW+Z&TO(l}LMm9sHKCAIc;C>As@P3+&+6U_X>c`_r+Db>4*?{I;+k%4_JdGNF2EZD)Xm&Zj=UWhXqpTQ1(tJn|ag|T(i4|eeL z*$?G~nn(R$2fwZChw_+4l|=nu2fu0dLwV|6t8ORQFZhHV{7^p1!!rC%JzI^HsR1(Y z!`JBXrPV6m$#~hRXP-1OG*n+RF*q_@c}}zRLNa$3Qc9jecJ0dJO}=NIsK(~@R{Xwx zT94aZtJZbG@0lmAUpY3oZe(mtefeqq8|&k7ABgG@%{!@M zYGDN$cxRo}QeVQlPsI$|QvM+|@5i%Bc8lqdFL8YFV_)N^cMZb#4JwuWUv$g1C{Q|| zV3u33&YW-LmN0K`vzN(Iu9JCt8%nipTJ207$S&R1l$vChv>sTHCfVurlWaw)nj`CI zlU%3rS_5@Xj+D9AJkzcg+^M$DtL)lkj*GojVmdf+L`_6($*qojV- zS8g~@9;EVd=eB*+`m@hCp?`d0Y}1;F{=v1QVWC>Jb-gC@c+BPuDsDAMgMl>IK}y-@1YEi5EPtwTy1o z_$v*6NKuBZ9q_>p_+XEe@QrUQ3Y~f`>1B-X=NlvaQIfu}2R`r27exFB-}?GU|G@Z0 zK+csm&f)fVu1Qgt=_Rpb;&?hfU=Ms#mLGYn+cdl;^z1GdT=o0N^G|juq_5PN^re1M z`swY#GhYJjffd+MChA1XqXT0Dd70gsf}OaP`~ti5BkYSRA$GI_VE4H_p}pvKF|e`T zKeGBYDoUrSO+)UU&M*aY${e?w0?fJGZu8HNHmhZhNWj8@$0k>T_l781pQ-_l58MEj<(a z3{}dD)qJFyFHy7q5p(UYvMNF~F)F3AHPJb+h<#Ii=-8o|>S|Bk3e%U!eUXh^-V^gw z2Ra65rgNMvcGw`dMuv3~J4p+h_SJ!u>D z$k}ub zaw?V6zB*4Y2bVovZ~u8?zdqXErq?di{x5v#Q}psP&)BB-H+*|(NATgwe=d6l(XvzC`w%e~g}A=a{IE$_726SX@} zw6k+m9&JM%Z`I~@Zg+{>ndhYKXqQRb(N2@Lqut8wH}AT*i4W~qZa?nfa68(y+&=ip za68($+`drwqutBxcmFZ;$8jLH|6bt3aUr)$esP>6ZO3twv>nHh+%ETz<4SIq`^RyX zv>nHt-2Pm_4~|2*{elNWesEmM?f-OFxE;r--2V7S!tFb`9n0mQ_S-JR@d>YOFxxbXa?Htc2-oli#i z%$4=w6)FSvc5f6cvy9=#u0ru9@F?GJgKRqLs~ru@V8c7xOS8h(2!^OOy+(SA^0s;k+T z;mTk;T-OQQ5(fr@;m}|{Tx&sfCVmKm;jO3gWR-sktyb$P|8&mNy2Ch6_acwrJf+Z@ z)L5if?)%Ysf!clAwf4)-Iemc6C*4l={WRi}j?tv)j8jL3drnb5 zzWr?TTii)@N$YW6AKRa)GUj-~nqpJ`a&tcsr5>v?MlY<1rs@g7V-_uXPIP4lOWw-X z{q?r-KVfLJF_2@A-m6>px1`PfRQ=j)P2c1-TK89LbEXa2N2rr z%T)oFsQJzFe%^O>;{kmy9J=l%ET{1+-uuZ|u4W1WBAalO^!w*E}#-+s@-DqU8kGXM5JAMU&E zZHsh%?*kT8AK842&Tl<%fl7_d0sTi*>#zEw_LcjRWq#y~&#Zp%uDi8O<@~*u9CpCI z%k=rRXYVDizxTl^<^TNZH&kCM@=crnns?lb793>kg)iB|=1(f$w7Gk)B`d%9p6$B) zd*&VYhqqm&^JKGAAg#zFmhl@yk50Nen8oSn`tl57KxDGx8E! zMQ}3to4bzl-u{VZ`TL1HxRMws4{oVUa7cMzlNiVzyh#ovHrZ}pd)Ze=?m9dRsF z+O!k2d0A#VU79)y-IH`79h>b+wnKqUVve*cWrOxF+q`VsWZyhaMIEWl#2t5$b|sDl z+2$n%*{&k(P}H65!3pKj=H;LeNer^hOU`AxmF--%f7za;y|j_* zrM=~{udQLImKH=T>gm+}-(Qp`r{D5Yx#vZa~)D2^mQ zb1pagBVUSFDQ2eli(+YtlgS=2CoR)@is$Ki=Ba81CMvr}%@j{l8RYXcHPgPS464)N zYNoiF;w{?8LN(KVsqTdN2sKlzO*T{p;US!am&&01(SFH>uH7isrg8}rmGN{nQ%p`a zR0i#j%0(H^P9tWzhbpe!XfYoHaEQ9x9W#{A)E+SrlDTT~ARnVg4I66UWa|Gwp-oH?kvp@_VM5 z3H#A%CJv5KGwDwIB2AyIW?E0%$&O-NDu>FWau=zY%KKY26L*A}_Q_Fnu!ncC61P=nQRGPkDBQ~p|Xin(u0B`;^_Hmrv1?V$d|T}9?R5B z8b4Rfg!=?F6PL7&a1b8CMfIU_s66teZKTJEY9{_(pk^v(nVQL$wviqushKoftY*SV zcnLRcBaF+{OuP|4R1TF#zEo$bC)JngP5MwdR37;fMye;(w@1y-Q!~|%>OnYOq-Mf< zvYM$}(wVl?GOZ`Pd#m|WHB;LluBp9HyP@_%?S_`=81U3g?Ty+UwQKUH@@YR*FTzFp z?@=@HOy`|N^VM}EU-v9f>n>4q!#nhV6TB}RXx?zj1%>r18f*QeC;vu72|U z7(@N)j3a0rZQHVN!|KD1KaZ%?6Xj_g z*^n*S(FVdzWzc$KsoE`KhsMNvr?0ITm)Q&36cR?nrl&5>Ja<;d-Wy90%!oxhJnVi#bNn6UN+0XQL z+4kb{GmR&0e>TRv_O?Fua$5OCZ|}5zMepC07d=Mp_FymX>3rGk&0e1E`q_Bw<-GW8 zJ?-UA%g>81uYX?rc75&gnsE)^H+OMO^n79Sx2G)II;Y|8)IP1eqPN?}k-c2>{_>XB zDZVs&TOWHlFWyf5)9`j$p0m$)-m%+*y}YOMYqvLhdA93kuE1{T7F)9dHwU^x9e+{*NkiU zIY1ZJlL@Gk7%ZrRMpS zc{-*1JoS$r5JR4DB2UlfQGS84p=a@sr|0^Rr)T$&?-BVUMZQ<$j~01)CJ?^#d>!)i zEF|*ud>}nvN0`-vF?v1a={Z5NA^h}=AM!5|`7=3B_*aPhxgt-oF80+g@@qtXy~uA6 z`4N#H7x@cC{&gx3{BIEXH;VjQ*q-X;i#)a8%ha;eSIMfZcCYzdMf55K%3u3c{hgOD zGd`7Mn$A7*+>x=NwV7-?HTtD;2)-Zv{!FK3B-xLxIcq8Aihgd3EGMfy5r?amDFi2& zRXr-DKHi>4(Mo0Wd0*1sC-UAGeILuVrglN?1ofih)RYjlq~~0V{06aqyWtTj_Ga%J z_+Zx#-`LvG{=n$HbiST)*&KOx+pBSsx z+Zo4iqf<`o^sCslovrj9bL$5BuA@OoAXjz;a%!)6r%*Ze=P3)I^aIzD^K{kk4>B(E4*v!Om=j%?U< zpDH5ufC=Z9PN81K`opi;4!HfJ9bh}!2bRwn8QRqK$B|VbdHsQ7L1me12Oy)1blDrt zc>u0BzvFz4^EG{_f{ozN)HC=0<{#S87k83na>H4eL4{-Zvwig^X z+>TK03KioIub*gOxzjYSf4D#H2R^fQnBwv<9yn!aWMCpR>o7MpN7_r}v+?Z(_5U!p z7egOkryn`-qGo&H_JQ^Sn(gz&WW(Zk_0ur+-gTpj@($z%YZy=71E|jP1 zkxJ!s^>|JHqpzNOsAi)d}Lz0M}=i08@j*C6Thc>;#YUP_SRcYt710o zjM^>cW^rm=rJ{a2qED~M*XVRv?TGa56yqprU(^n^s2yYdaVnn}9XgByBh|b&1y2WdU1}EzM8wV!pV}k?vK4TaHQ@Q_AbMO#@4@6!^dw@cCyO{=h5YQ@_!xZUznw(vL}=rG7%V zJ~mOhG_QA zf8T9AI!Mo-!_J~6VfvKIJ(7x=wbn0ljL#BY)3@5V|~ ze&gj)e(5`CasocsH}SnJ>PJ2~em=Ch%jpz;i930W6Fz!?Li*|LW5?bN>>gtU_9n0lsO*2i%13q^N75OZua8 zF(m>Y@Bp8GuHg^33E%P<|Dsk=`Ee8Q0T1x?t}^(5oBU7cAD}Oj#}$)%ojf1O!hjEW zfG=Qtz)kp0oJD-V1AI7V0XN}0X%_JT5AcCw;3j;_OT?FU{Gu-bzS{Yw{h`m1eG7e4 zGw(FTeb-dK*$>J~>RVvn#CKlQkNk`1TY@h87U@S?Rw^6*8^=zKu>$)vFQZOme}eWY z=TDmUzyo~#D-E~6P58>}Tg-jC*1Cf~-~qngR~dZ3P58>}TUwEsHNXcvz!xw+;3j-! z_AP1r0T1vsUTydTZo)U4eGBjapU39};MVQ0#B*a>-v>OvhjSKi>-IN`_<#ra&|ZOC zx4#ncVSjdt;{$yO@YP04`$L~YeM^zo{nOlcO%0p<0GImQZ)5^K*aM$G5cMOcBKnri zUG^=~kF>0ehkXmM0(+bZ%6`?S)O#s6X!q1=D`y1bnauK7XCT2V1T0kQ%tfiWy3Q4|ssDcfG*} z+=OrA;MiEM2ROT^6Yv2K@CA$yxHZ0kae7U#l*!f=I{`l60lr4V@CV$4Z@e+MuAJV( z{MG_6$rSj22lza0x4=#J&4xzk4a%9FfDd?p4=8|}@HN!qeOO<7`uf;QGvLGd1o%9T ziE!Sb_OY@+P_@^X_S4uHJx|!}5cpsZeADa?NV9!@0UqG_iUeEfCu<`hYUX8 zp6&As@Bm-H_<+0Y^9$OMoud5#5AdPg0{3j6Uw{YrP!Hgq?eh!HC%}hmE}VDhxSyEC zF;n0HKJW+J`uM01Z^HVbQz}1hLi@wDF!0shz~>jfhSmJlHy8Fe#x!4hPyK!L{G51g z%=WhC6Gam5gjT?O65&D*O@u}Mz9RSvZV;gvYZ;J7ONAjQ5Yh%U(e6c)8~m*vs(1F`l$^MM z4|ssD@kYZRa0B0ldg+hYM`{Fozyo~Vn+!hSZsJ?iPd`IFV-xTJ5AaPfKHvsEJhNUj zKq^0O0zTjYzS^4&f51)tbp6ZU8#Kppj`ve-ENS?F2l%ELA8_xjIyil7^smYFg_`M< z?=#S|^E6{3{s@!wYpsjPPjUb9l~bRJwpYj~GE8s>w8gDatpnj;w_?m%SUm9qn)PtU{mCx8xd!g?lOF#SgK$`+) z)WLhZsRQbUI$Suow)+nXDJ)Z6)ZY1gWy2!%r=;ogpF38+pKKQo zj)4dGYQEtZxHZ1QMp$eVmC9$YIeJ^`+AvN79^jj1e88>o74gu090;}U`s=Q1iw}5! z&wq#E54bhH#R-KMu=?jedv#lVfd}|{-)Zmxx5oFp0)QkG@t?o?6~EISH9-3V9^eZY zA8>1YB}QnUn(A$f4|ssD@h-z3a1%b=KM#$p?O!)GuqIl~(w4v<@Bp88iNOcl5quj5 zhf4!w6%2g91AJ4A54he{%!s2|m1Kz$xS zg#{)S?y??J-~Uoq^^ks4j}JWiygtnI?F#4t+^EMi*8}yVaaDQ`Sznizc;2^~OY=Jx zzyo~#yA9949l=-Pc|Qps@Bm-$r3N2xNAQ(+-cP~@Jir$)KH!evEAhOagb#RtuW^~- z54a=vN<8l;;R7Dv^WJ0d0e1x73+z(LTgLGVJis@__<%ct?{CV(W0wqkzyo}>%ME|P zP3OsVBkQ|7JBE9m?(#e-{p^@Ma-L+|sK+!fqkelUXR62O$oSxd`kq9Hth3yzlxKUW z|E3ue@l4-CkbYE;AFGS3X*EL!;01pFAB_&sgM8@zu&M)!o{<#zfCu<`-)ryzH{qlE zOY4V5Ru2pn50lD|n}82^fUj}A!3W$lK2hZNiUO{GaGlu?u-RQO@WH-`?|o4}@-O1q zvqnn$BpxM~gpXn^>8H2<^>drwlV~tjVE5i{u%k|7zrO#qt2eDv@0_T7(UZh0%Lcc= z1AJ4A54a7!ar)g7>0Veq4Il6TU+n{iKj1d_)@&M5$IaNt@I+z2QVIfpzyo~Kj1Ra4 zzSZjE?Plz0K2YdsCJi6(0H60kgAce3K7D@a zAK$3HT2=5HGHLjL2l%EKA8;FdYla3#M@wmcErRn3oL_(k_-Y?A`~kPYw{h+Gx(V}U zcmLYKiAHfBL*LEOML1qGqGl**g^U%g2HopFKgF{7j!fE(`2lyKQ&+rG_Hol=v zMWTzgIk^OVfd}}!s|-HiZoxOQRu)rQ9{7L<_@)>iaNGFQ57!M0&cG)Rfe(0qul7;H zA8_0F)Q1koM+;<)%8#3X4|srYn(+a*#JA?6HAD4@i$;r#q|@*L5AgXPGyDN}1Rp&; zQ1BT#4Il6TU+>ihA8<>2ql2S$ieTdO=yqKiKHveqfbjvh#HYW?rtbD^932=d6l6^0 z(Efl2_!=KK`~kPb_uBEXHRJUeICvFa-~%4u^FCql0XN~J=&FBgK;2r3sc6nsY5D>W z@J%s3;3j{%cci`tp?KWX>_?soW!7;;I| z7kGfLcgo-cZt@=(P;$mqvcz@Z4|sqtV0^$$_+Hz;X4by@0X)Fh_>|!fxDCEdqvah5 z@gjgf-~m4G(*_@K6F&9C+t_U310LX;Vtl|&_|^=K^^Xkqueo3bZ=Zud-~qncXAFP9 zt?^y3zJKlb%*6Fj8~A_+_@)^jaO?J0e76A@i7D^_5AgZd82*48{B54$@4^8e@Bm-$ zXAM5!CVU)MDV1j`dI{qf-~qmX@c}pCQ|}e8srRp*nZSw_2Y4vdZ#b!n7#e-dNqz&HIRK0osqIE}5Z9UHi? ze`w&MBJSFIU*z`9`vD*FxpZ3BJpZvh@J;bD{3tDAY<;TBv32Q3T2{o^Ir# zPIApPHNIxbpW0?p6ejx?S_gcv2R_?R;~O3LyG;d+NqCG4De&2G4)DPa_+XDz#}D=O z8`XOvOR%oU)W(Iffe(Dy_`oaiH!(IaJWk_v1w1-f|^c$Z={%|}1 zpMRriw>WO7UW4QP>J=IwE;hA!L+RiTc!00>>jocilfU{He*XnUTv%b}BHdf$Wfu5= z2lxWU2i$~@-ak^K6Y3Pxziwz?W^S+pAMgMle%}_j>G)Wu#%5QKjBGe{Y-H1@tYjDY z#!alxH!`08*dF+%EkB8GQ5Se@7w=|+t7h#dDSm-H@J+El$|ZfxI4su8ObUI02l!Ag z;3hOhT-$rMwSSNAV6`8bF%iBes0HaqT#cW?jcq00tf|z;Q5RrGT~HS4sJY%eIx;qK zdf{XA*jHQ%d}y0CKD2q+R*Q(X{coDK8hk5yEG4y7*aKg$$0s%zqGar?5GRc4eB`CZ58Kv8z1@u!l#0^P5l!CtATwcQaYAA6%6C|RYuMC4pSo70BRg zl~br3Op_mf^4DK**mq9yfBAp2F_D4^hU?l{kN?fCY?y>v+F8=n&_fM zszTZKm_^U+?j_;*ilu$j{P2Mx!e4&k$yLnW!Cy7)6X_FpnbXiKK3BWzF5S+MzV(&Q zzxn1H{_SSbzdoN(`&u!wW<#BR^1X{6I9j{6uQ+@1HySB@ zBlf?$r2b7WXgRNSgN@n&^@XVaRk7{B9RIq#@NtpWUe4S!k*mSv^#>Q!UUnTgzwq|r z?_uo)eB@2hUQqvb?S*c9;ku)sIR7p_DlT_`Wy5=-hXkw&;7r# zR^=An|8#fdlG^|LCHFT-zqsA>N1UQQNvY5M57JFHJ^$wCRJYA||Fh$zm)yMLrEj^p z{<(v`QUBcj+4~=^ciQz2l|6;_QHL1bf)| zr1te<`ybT*L#^kD$z8j4UEGXU__#=GFM0cqy#BJi=>DhR_Tv4Z{e36w|IwDB|3UrR zwHNAta9&L6f6$*G^{n%--T$D!LH`p>oBjv>;Jfht=Q)c|bVn)rpWh{2|NJxeH%Pbg zGN)-f3%LJjrYl~!eB$>XK53?}f9}}!&gFM(yJYz>_fMa6%>DPP{kNZ*=M%1X+WBN~ zH@W^%k&wCm`HbEFoH8^r(0TuJ$F_GV&h9;_wuhZhyl0vFJMC3Y--`1I>i=P@|505J zbw6SM!^cHhdl}hHu79Y#=>DhR_R`qH+Dm#%$Yz1|g8H{>FVz3wyqMJgpg(D*)_K_O zf6(8c|M7oq`XBhC7KQgei~bfxca)~~KVRkk2I)3l<}__*-cQZ_H>5q!U$%V78K0W* z{%6NgmoDFN)O(h%{QZL`eflAF(4|bx{)g+Gc0SSl&oPS@b$1n7sT6hnQ}q3}9YAt}fb^TNH{Wr9i={>Byq?`^iZ$|%v z`nPK@)c@eTnAHEEKSAnQ=V815L4Sk(r*^ODf8dXb6yE}Umn^^Jg*`KV|Lw5bKd}6;+pk#ugL60E{DX5FYX9x0X8*(W zPCK9E?LYGRhqWp8`sc9QwfFFP;2|54xjQ=gMs+kZk*$(^l# z{{!z_{{9CpS-$d`shd|`b5-{KhwGhoKGD}dok5CN@2>sN`yY6h;_Tx$*Y>dUiC6IT z&;MudZ2;sb%JlJ0h**b+0TF_L%poVM2yQ+=M1;-G01ZOSk$@3BlO>)z`B!`?vjmTlZh$|q+`3DRf;*wdQh468RTn>TD@#TsLh!_G!_*Zp5Pw!0a^z=+u z&60L9y1d()dEb8D>ZjkQ-m2Eh{)zDNKiTT9)YbS^ zzD)jc5q~wj1oJ-${6jvW6j~nE`GU2XQCmlYoEH z52tLk<8MW@F#rFC)=Y*BA%|20dznv}q@rUfLe`EaB)-whCgZm;0FQ)uqs$Ys1o9o|*m#&QA zh3#P~$v=$08eW3=ALPZj@i+1brO@)Q&OhWE@{jvR%>SScVtlsv=a}HVU`O|!p6>Au zxpz_c{7)?ZEEoyre<)AIF(l)OlP=nqa=(|4EX@1m$hxHZCyXm61Iwk1tlXnLU%9xj z=PQ>K&b$1O;(3?9uXg@H+)4Swls`=M8LjR02YbHqHQ8nd6}^n*6W{XsYsO!#KO685 z?u#V6nDU3Iekoo8{;~AD81XWgF}$!nOeOh;@mIr3F#nUlKjafiq2*znf5}k9J&7B#*v-n^Ec!B{OR6u z{lVUH{lVnNJ~KS|v3a#W|AV-b@`)*bnCg$Vzuol*d&~6)lOH=}*w0u#aV@VuVEom_ z^8^0DeUXG0Q~og3FU5<^^#{buNXGCo+8$=Vk$)I}HM|7#KMDLpKA{v^9@hDXd_(^6 zH(~w4)>T+WDUs-+7d5vp=_sRoNPU z^RT~*j)QuSnNJvhwf<~?7u**~c)1VV!@-H{>60Gv82RT9arI9R_=a)`jv*OOoD`2^{s(f6 zo*1u&epZJ#f$3^_r z`m+K5;J!%0OUOTU07Uz$E&j3n{3-DwF3VPbMQh&FhvXl|Ukxw8{15VC?EDYv7xIeG z^03Z7iO0X-kbKdZqv zS3wSzOP)j*Y;xVO*_NCl!Djb8@Q-&VpOybEjWcb3eB` z&XomcU~TMks8Ric_?b_{m0|phk22to`RUfcD;riOxul(m&ah*1|F@vsoVOQSGL}#L z1MEKk!}v@3vq#G2#!t!qZ@@={mo>OwfFpIS)hEPDx-~;e-`2#a?fJqGF9#LfjN!$z zJYUH8OYovD8$Km?0X`zUFwbgvCdA9sX|zzUlz2HRc1iI)!_T5c+F6Ui9_~>zVoK9wL{y!4F^$_E)%tv8<3DzSd)I+RqCstby41(< zxIf3$Lsz3eM|mxdAsJ7c^w7SP1J|_`zx;Q{%UWoB*CT8^Z)I`gc`J(h?)A<5zI&L#oHtEoPXPmo&;sd~t}P2Ugh2v1@w`i9n|&wmW-On0 z_t{&IJw-Myu4byw7!+>Qx&+&}>B<;x*dC@*JUL=eOZ{ZAiuw zCw=e{<(_~1WbuTb?=$XvGrAzZ5q%`G~j~%ouLi9;T9f#Q1B$jp8Hb z$v8eDzeG~Y%Q_#Cf5=DP8(6P^I*D;w=cB1+`z6HIM-#z6l#_4_$#~+V_+PA7fV`v7 zQrxbn_+WhNqm|RoE4G~8Uu=Ky#(evOKdYUO5O-2u>E24#%h~3mmebFXZFY0s&sbh@ ze_^*iV*It_m4J_MeEn3#HKV zvd%~3AM%kq0q+t;oy54T^U-t_P5mF%N3X<<*KH5}p%gfVOgf_r9->@xo|iAa<=5lR zN1KX%epB&*{E3Bq3nv!d7rSnO@kHZwh&w5-nASI@`t;lOeDtQ`df8_C6~zB#Y`*Aj zdwitcU&r_>kN=mUAG`$8IwJkMDS#d}Cd4 zC)UnK zh&w5-nAS6<`fPvO^FwVHze~2+?1G=MyyD+!Z#+)%5#z5VuLOLA`y&ZArge>}ekpEj zu2&##MlyyQwuh-CA2I$~aHIH$`7(}=$S;&a%gZ_+k$=cXuE6{d>LkW#pO4JO=VI%l ztH39egE)p{JaN(m4^h7BvKQ7}^m(~>be!v>$v1wqIQhl{inDJzqA>fW_S*RfaVO;! zQ$8`(XZzdcqscc;mu=Qo5Km-len{M9myZ~KEqNv2BitWJxH07uQ~grh*yJPPrX^#z zVSAWL@)6^&1viS1m?z`-i2On+w7jhI5&4IFBzC}j5$YtyX`PRzA57DANzNC=zHjwv z@DJs+IEG9*nFl_iRP#k^->23KjPH0I=Zkhd?Cip>hkdbjK0@3{dBv1ZO!Y^vgZ=rU zT@U+w!Od7+5w_=x5P!At|A2>ZUnJqhlt)bUOYvfRzDVJvD`R*WZ4a~GqWPj4@S^yK zc`=TE$S0IS%fmYVkZ;I8{@XBLgt~~)+2z~;1xSxP;C~v?qWYQVM&iFp$>W;4z=bSbE z>$R8evc9-NWzOLf0*hM017Vw|5V&REInREGKLqnhp8n0 zF#c+IQ5l>0F^+%8CzL|V!#e+vZ^%FHJ1`%FI*9RE=bss7{1f}U&`sbE%C$I#WIS=w z1@BObpIw;0G#dq(K z?e%b8JejTeAn$&A^FhJ$LWsXwe>UJB+!slBG35_a{ZhQxtbd4?mW<(r?O`g(Ka9T` zUR1_rUX0@(@(HET^03Z7Zp&}D{&xBE zi`w}IaVO;yQ~og3A8miT>kn2wbc<}SJMvz}@`-Die;9w_`UBh-Nq8~k4^#b8yafDn zjlLi5(LKE#{i9#2@i*dSFk^VBF}%dDk$)I}HM}VPVP1^mAM!~gwLGlz5BY}tm^$+fgB)pjNhpB!kUTpJ^!plg;@G{yS zX1|et7=JaqDE?u7jN>2j38m2Tu+Bf^8}g648|Hsd2QfP9{4+h>yR*3d;I+8@;_d|B zQ2IEAWIS=w1@BO*^#|Rb8*Cr%_19c~aQO|-wSVH2?Q7>B#GRB+O!>o9pY7j>^#_;V zu%%r*m9hDsdo9oZApUCe$pQc1zDUB0DSw#im*OShAB*b`6kb{~h8MPnsU-g}{%Uv$ z=6{eM5&-S~2H>Nyds?V0Oy?-`w)0HvYusuvAal`m) z!Hwc0=E*odBEL`yEidbQME)Tk`FmhK2z3$Tw9ZGZX5(>N;_9LMz(14^;24te#7Q4~ zMENWEK8K}Uv&a2;pw;qy4sG&%4s&OHw=j3szt#Rc5aLeCE2ey6s?YYf%|~tWeGYSH zT~_cimRDTM`}HvXTJlQ3N4P(daAV3RruwD0QFW26_uUaUgBimO+rw0nj~IU~xKVt> zJQ>GFhB*vZru5Z?_Zs^|F;X%_Ww@pe1y1@@`@>+nCi3rZS#?O|LU~;R~7t>GWe1y1@@`@>+nCkO7*yf{o^8KqVyRR&Wr?WL*T3E4pMeTfq zxRdgVDW90?v;7;feqqJtiwbVW@``79{{+TgZ9Y2SA>0>9croP>Q~grB*j~S&@Y0nr zys$k?rQ#vA-jeZG!;9h{=EXSvA)inREf4GbL%t#Z_&LlMp)O*4*7@h)293`>4!)rr zcp-d#2$J!{Ngw<}sn#z{x&O#<=O35&-S-n52<&0xlG!}c(htcMtXEx1v9 z#5@_tN931CYI#}bBk~XV$lDk5MW~Ayr*%G>I-RELl8NJU=YfAH&&M%j(#gcGm@k4< z@4s8L+iBy@M|}U?J(pZlxaX1|*Um?XJ1MVp{}sRg?w(7oE%+JBE8YiQ3i?e+_)PkD z<`u?YOI`{12=_-4ZhHTU-+!lYGm8>`o>hB?Qgq2QtvUl=(xdxcqUu(MZ)rWI>uj1UJ3XJ_eT9ltRnPIvqXa%8zeG~Y z%Q_#Cf5=DP`!RonI*D;w=c7Z+)_2Fgk7yeBhjIpvAsJ7c6z{_P5#*FdFDuTup*ZgQ z(d~EK3&s78`%UqPyCxToxNFzi`3P|*%gi>gESmz(|4f)4C0P{ttix{1C{yBICP1hw8*Do9bzM(u6$B;=UbJ4z(ihpiC z_Cw=d50QU9e)f5VkDq;h?fiqdlk$lvf0*izUI+X9^YOF4ToAv>)_jp?aX%oHPZ)o- zd=l^v?u#V6nDU3IekopT^N+$yOUCdr+8$=Vk$)I}HM|7#LkavtKA{v^9@hDXd_(>b z2V#B*br7So&p!=XKX(}ThVpP6Lo%K?>7jiomrwY5@#$a87l`5@FmjLts)n9T>p zj=voNzM*WxF(l)OlRny)Qt?l2{e9y;{zm?pvd12UDSPZ)JO3c=qZLe`EaB@=3ryxG$3MV#*(;`lWcW%|8k+gBioiXnUCbM*d;^)$kI` z|0M7a`6QBB9@hDXd_(^6S~35FI*8HP=br}cf7%Ydp)BASlJUezu^Z-pAf5bR@qk~v zf86VzwrS4rz@p8?p&y@9*m&|l?fiqdlk$lvf0*izw!dBe8CbMMw%L~oe#Y{NZ@K9hSJ3`B;$#bF4~uJ={-Lw-ZpE$ap#|vQ^fGf zDU*ixKC8d5_gSB-oqrH_Qa&-|4^#co_P5JFE2nHP+w81@7|GWBkFZ?-F#c-!B;X(1 z7fED53}FMKa9T`UV{0b1pXnPPzo&%>-)C*LwP)oA(PJNp?xV;{qyMu``X9*eR!;YhWEazeR%IX<@u|B z6pn&?g1D3Ni79`W>W@Zamw!}$c6jfb+TD!h6VEdLF#c-!B)|*qizK|5@`tH@DPC;y z5Ao8KF}#enhuLrBAI4t|FDhd*FUHkB zKeNC$l(TURnRGHA{6negpVq_PJ?{L&`p5m`G3{%v`Eu?2gSeCOi79`W>W^LryZod2 zv+gHPZ}&2mPh89V!}zP^lYoD4UnJqhls`=MOYvfpe~6dCjNxUpJOA>8>c8)KP~qSAoL2kz8{$sNC#L*is?YYf{XFVC`8?{s@7Y@LGnP+0 z%g>`S{#u?Z40s6lM-pyKdBjw|6gP^8Y`y=ExEaY9ZrC2CQt{9fX@v3Df*Zw0%$IR| zM1G+ZT3*)qi2Or7az7IC5%n3Tbv~ME_B_yQaqnY28T>;z566&dgGF zHhpp2>!C>t{v$tW!Oi*HtJk*YUR_^%J%qTE@`@>+nCg$VzukIh(t;aho88(jew(fN zApanH`o9e>57q{4?+58)cil zTy!&*Pdv-~!}zP^lK?NcFOu+L${(isrFgN)Kg3H{#_%%Q9%jFhe;9u?yr_)Lycown z6vZ&vT3&bghRJ9cr$>7D#WZBlAY zoj=W4ytJotnsZQVYrSt7+QFINd`6#I@bFcxG=o_)KfT^A`cjU+_*~k{edGR+~7VTZiIHf(0;zR#{@QxsXqOf=oBUf zJhaD)0sd7+n$x@RjL!bFXIMScaW2mfW(+rMk9uX!8;cuNH#7d#6C8P0j{QV<0X~Qq zep3KPJf7LJw5x*$DWs|X=qZ60OZzxEj>5|~@_v)xWhe$OjK5mH#hE0>ZNamC46a76 z)4-9k*29m);Kc3lPwH>_C+**8e^h^>ZaO#~{r6Fy#^@@)@DqHWes24F*rwasAye&8 zj_-TdAAcl&!Z61ESMkIf@}s2ok$3*+r}WCbJAN2<11vvI%>W{Wtj;+@3J2?01x&^;^zwH0lUVo(9>4z;%iTY#UQ+cQD%kung zQF7kx{8!2`^#|hC`vv?yrD^?Os!u-}Qhzv0^CKDS7l?c9)*p<&=K2Ho32`H|`-Rsl zZSUTeKJ7H7{`g{EJe#d~JGMu?GOqq${E77k@Ik!r`~o=Qv1$Eas!u=U2u)b8TCG1i z^DRw+m$>?a@h8?F;Mr~U2Wu52x7921{@m6MTUGt4Fv%asVeO&hXf7@PP1O}?>krl& ztUuhgu>N3O!ZTT|KV}5=#|)?b=?^Dy{^P5tHz-%&_~MxQ!@0R?{m~}tkKEsFk@F6< z*B|Ltwy~utS%2)FcLoZz*B^*m?-$T2rD^?Os!u-}Q-2(kcQe*6aIZ|aA6ne}2jj1~ z{=j`g+z9P{;r06Ku0KAK@5&f%cwOq1arFn|Ppm(H58{RA7r+sZP3s3!efrUu`s2NM zuSxI{SAQ`6#QFm~yRH6E{cZlJeqQjqf+>HOa@*g-_Sn`AkrW$ z)*q}()QzD&*4O_|HQNs}cKy{Qs5dCTj$_C$n)v_vSpQ4utUoh<T)?G3FYIsrW zf0-9!*Z*Stio7DUJj``2oPQ_ZkbnGq$UoF)bhh{>SU)U_Xo*Lfu1oUylT!Xs2HyMa z|NiK2ez50}VkP*7@>@8DOgfpEg6HuepZ-l-e(356a{Q?}{{(U6R8)Pzf0NFW^zYC8 zct!rXAFs^k1`d-y$I0_o|3v(QxRdgUDSw#iGa5OMD%TlKaD=6GoX`FE64_qu`H_s} z6H!bz|IT)#WIkd1mB%qk*8SqXNWzOLf0*hsK7|*X>wbwB@w?`jcV|0N5-*Iu8eSCt zFh9oe5BVgLS{~N|HzmAnv4m zV#*(;`i#~#|2S)|lLA9qankp+=O2&h>s`K-|6H@o zcl0bgy7%;&zpsB$@sIk6eILMO;G3%;2g@bxd7m4q_`I11{-GRN^#1nVr~bA0qIjR= zfcWPhRb0z^I{G_vCehJ5B?sDXxZpB5_x~|D_V(+dd^W57hV8!@%R^E9gZPhw)b%PYL)3 z_=xbb8utru#ETW;rQWBNsV(s`y)b`PXGdSYr@Q{7F=|Hs)&RUXyAOLA!;3eVZoNoZ zQ>xa)_#5Ld$BW8$YHiuM=SKMj_=xawCGeuDEM~uG=FKuTP#^e{^gLvVE6u=RW!~Bx&9c0Re#EYaOS~HOiz>9O}uy`(8pKLBU?cnil@INl8Ut73h#xWA3)t|R8jcbexOD7!VT(Z+qj`MuGGa$!V7ECcr^ zOWSV>@iU)@Ys2;^*OL2&E$=(6V`2Ky5>tKpvmNW9z4U#9!kx|dy_%(JH|NCIajBZ^ zjPn=89qGnf2KFAiZ%{Cfg6kgP;5ytFzz4%SxwmKe;`A_ZO!euXo_o#NYteJ;DL-|#MCzX%*hU2hnF^o(1XXl646?T4j zxbV4uIJy1SgDwij&-L$=9!KNqh+Dt^OTVjr?_MH%@hSF=rJZ0Lga-!F_PUXsA1=x^ zJFDHx*!?d)Xm{N_<6kZBarIn(`KM&vBJPVMyz~ZTUwXiVWn;M)X^w2KTO?ivGlrKm zZC6Q$;~0#;8eY^m2J>RvI0pG7l3E_t$1%t^+Bl&XJ#(_%zC*;58w9H!o#<%DD3r}AGPoG zonO?>KZrXip9K6L7+@i+@h+l*=9aJ7q^I-IP!w|J(w;p}ZBxkc=lzy5Jqk+`(;yp{swG%s+7k zQ~rI!{$DF>*#BP(xq;ucPab+p;&@?|7_U*64_>dZWq7L);zBNe!Kj` z_^b721OCB%k%X6!fByRFAL6AYV|YoKR>r82e;9u?yeR%*UX0@(@(HET^03Z78^xW*;?j`-X<2(D72546AAz4;Ct`+~NpI77RpWDDU=iL;(7wCM* z3qr|wyhSnV=2`bZ9x!Rc%#VI^ZQ?v`XJ`oGb<7WIp{W8Cmhjq(*Ypc^Y)d}B}WKi_k9)AnlZC&2YSUwT= zq?^apFC6m;B!0Zv9wXnWn6yw3*yBj1%V zyttO}!uYGzKLK8Vj|eY|fEO*#gm_7R!SnKsa(&Z~U(zqXms|n7SlX8$%r95uy^P_- zw~QCYpO{~Oj|eZP0WZK2?`z;CH6hKEcBukXAJ=G5ei_L78N-Wf883`KF~0yG5nlcg zcma;e@iH|vA7}9Qa_k8(-K}9lVA4Ew`2@2 zBIQ2xyq=WozcBv9`~rMLco_g*fFs%s@sc{dI2dnoOdsXip7qgB7cEimuN!^;?y>0> z^akTro7>%t;l)k)-ZWlMO5%m_Up99A(|}q4slFG~)4)fB7miy3N3@IllDY??##?i9 zXw5`6VEo0osl6*>coD1Z@)6@t%rC$P@xm)9fFm9QFX<+ErI7$Hb7{>)HUckQ?Ow+4 z;#uY+#-E56%zqFsLYoKSl?~UY%uk(POy8$MKWwkB4Che(oFB{>Uf3R{l6=JYEBAM0 zuaSHNd=M`@zW|PS47^NDI|5_zeJEDfLj`ylcsB1hIbIllwfv&yqdm-%az5I}F>%8A zWlF*MS>UO3J~~+6tJ$L+o`-fQIlsxgR%&mpdcFkn*__|@Zx83UsZaa1=C_0AOXg2= z(h~1P5zcSF7&pJ|p`N%C^V~k<-JxVW-al2I-xlu<*Y~=R$NzZe!sc7PCFho_Kc~#N z(%$d%E0P1J6r6zz<-GQHijMO{yVLgBg0uQ7u@7}e`3dneKZ&n~?Gf3UjK4CUl{{Ypd_;Izf%^wI;w3h%#}CZq zb+v^*2yCEYU|3MC)N#V+Nk3q*~<%k%46 zGKLp%t=;^>_!IF0d_;H|0v`iMyqF>v7e8$#u}0i46Bu5VoF=5Be`3DRyNHFD5Nms>^zu@mH&_g7IPC zBf`rt@B$psHt>>qLP7OkwqCrPQuLY}FN{ACFTh8H7uJcuk%pJl9T?evu>%+E+hRAr ze6cv#`QOJ&xx`lH=jPQ|b7B@VuO6 zFS3KbM|LnzAlP35ZcFW{`2@}%a6Z8+hVu!uL;KdB*FGfO$UC3c{!83^!g|ybl=tBn zlJUez5A8@f=N~W3ulX-AoVZ_AoWYcTKWCr2^5^VxfBvk)J~4dOVIP<0ul`YZ3+gMx zt>-6QJLv!Df2`x!RDbkTcGpv!v(G)U%}y9@$yk2!eqedL5Ao~ysdT@(057;NlJFAp z+2~cP_cv4h(ev5eFNAn;GlrMZ_AvX6e8%{z;U$Qmkc|r|5@_Se(kqD`NP;n22uTkIBUx%={F3q7pvX=tTQ0n zEawdmHhDf_{MGV_8vo$^&imi@!~36kfoQbe|D2X?DxCe#KgZnv;$htHlpAmi$#~+V z*c1DuLO%D0BMYajY8m(b=b3-HxNzp5E-762)R%@YeCi9e_dgML(*1ARe>Bx+``dmV z_RK$hO}5!N!+yr@e_{DOyNti`cz(%xO57Jocrooin(CM0#pZk7iIpX3|zk9Rl5-_Z}Hef#{AZflxE{&@s^L-{CaC zQ%U||{MGOh%>O3v5BY>rXn9!YAMy?P$6b%{cho_Q&p!X8d!mf|vn8(nc^rI0xe>>Z zj3-WdXkW^UK67yK&8UC6-m;?D^_KICb=Nhn6-u75WCy(inOZ`jLNKJkX^)<2BDT7Nd+ zAKVv7croPS~ z{s(msbM5_=a)>$B>LCPKv!S{{#6iKl)1kqQBd}eZ1Gd&i&GG ze(smn=Vz}yrM=}d|02&{{iARczvRm{`$D^)v3w$aXm9=N6xl|MpYQqJO>4I?>tJzzB;m%CM@;n@hQf{F zA=|ha$rx_f9;Q;|4}}}XUkh#&A2DCX@e%nYl3HHY`H1{OKJxwx^FgSK7^f{hI=c6C zY;~7zt6%a_?0VQ|!9SGG;TV$f#7P%CM0voI%ZkNY?w5NkReyiDj4OO&QJmpA|Gwba zTZ#*w{Yi0`^?MKRvVM=+>mkIQlvhmo#8jWnVS7Ao!Lv8XHrsPp^kr*4$g{{tlV#&F z{%YeZLH`B!MG{_2dBjw|6fZW%46H1}wVV!@- zH{>7pmzWPiUBvh-^3PFAI!^8Bq~SVcBL6%OzM*^($B;><^T0opihtg6`fZ8)69$!& zG?a9P+WwvVQ@D5XaN*t^Yv&)tos>^Z`NLG7tzdgRPUVxry*mxN8OtZGW&UCO)y7u> z{=t2bgcno(Fx4-`i_P&k;-xENcwu{(O7aimuZ9=JKg^49{6jvW6j~nE`G^z zd=Tm&#%GIv=5%!|>NMEwJCT200^d-+jAKZ~6DNJ}52fOtKdw!F9zBT5Vg*G0>3P>D zhI`&s$MfijJ1L)-@`tHD+rJU@PtUtf81^!jPsESxjmN3_hw)eI&j$R1`yvT1ru<>5 zUy2vo^^d~KV8-ym_Ar&?AI4t|FN%Md7vuPcd_pO-JgoB%`G)-CKaBYx)Ip5T7XQp# zd}?>+lK#{Tl*m7uz&DheaSX|L;-uIc^Ffe`fA*ZSbK-gg#AS_v$UlQyK0Q3R<&(A7 zKZrXipP2H8sXp7k5&Sc_H{q;^V(+MdP z`R6t84doUbLzbAT_^XTdrBwX$o@r|SrTY9&5LeD1FwGnC&w=-xK78Ok3v1^e#GRB+ zO!>o9pW)hGkD$g=4!oyxSS-uf{EtQcnIapP@z*l19PkkCk0jif@`$N^DQ*-G*;e8^uS=lW}}RexVdvUe@`D{6ju+AHjSO>LSKzi;qt1?CV|L z-+55$bhG^tV)uu99sEP-ymXXWcO@VhPn`6?N0b9=zIS^q<8g8J(*AwHf9}3+=&XOg zz3%Zi#GRB^O!>rApY3A19vV991=(gN47(Z2E8ei(_1TQSTK_iSA>0>9croP>Q~grB z*sO<$m#&QAh3#P~Sr0M(YIsrn!@L;BKjafiq2*znf58j zIFHU6QsXOL#`1}8nSU66wR{rr5AKU3yqNNbseUP5Z1NBBGMF*EusuvA`G@gW!;9h{ z=EXSvA)inREf4GbL%t#Z_>W;e2z3zSv(G;b+Mj28@C~KFF(l)Olj1#?4}!erk$L$O z?mZ`QJzSi<)PG-ddEQxbRsOZ_++KX`J2%VoSN|v+1^EPVC*>1U{xH>NG}ifN&6Tpv zepd7|mQVbm-TH^|SIZ{>UT|L|;l-3cO!Z6gVwHb@mywL&h3#P~$v=$08eSCtFh9oe z5BVgLS{~Nck}pZoF3{Mz$xD6T#K+S>UCaVO;yQ~og3XZzdcpXYvjiEOj$i=sbc z^FfyRhw)d-CjtN9zDUB0DSw#im*T}H{}3-N8N&@N}=UpoqxzT5&-S;?KhEQ`hMY@( zR`fEKPh89V!}zP^lYoD4UnJqhls`=MOYvfpe~6dCjNygtVJgW#jK3OQg882W{vn@G z3M~)o{6oGW|M*W~{s(ms#-4cQa&-|4^w@%hwb&)tGB!|Q?1ALGnP->tL#0GIz=`v z0<5@<-md z&j*o@ZhifM;;paywa*73?xeh8$|t7!ybg`vqg!8JUlhwTHXme}j~IU~c_rW@+#gA} zG366e{Zic6<|BohmW<(s?O`g(M~uG~+$cU`o{Zxo@(ZQV^0LlHn@c5%IQ)5jR~K!wuWRRFaPv ze=WFCe8fB%$4BHBN}=UtosY;re?yyL`e}{*1#Xck}QQdtEB`O?X9~caMV8_S4}fwtP2s9|eV{Ag>_K+VaZ$ zw3opN-?m`h4vLS0ymH&3C6(UiQ1=;fs?ByRcuk&H7(eq$TstbpYkc#-z~gym=)DD*c_pp~_Q*p3~^MKk%lJRpMaQdImJ@Nqg zv$On>cseq|3-A%)nHe zY`igQif0rbG5*B-0(?YxIRbbAj(CC)FX`sml#P5>U+?0M+{ZgVpUcaAWjp(5xK7!S z{Nn62+|uNDVf@T5^0LT&3x7)bFTh8Hmp0%9IO63D@shgxQi_*33p-N3hDDBHG@!rR zw%@SZx-x)S7Gn9}RqP zxU0$W!uZSi$Z^K>cY%)xF9qNQIO4?uUedj+RvHQVFJ+*q<7K9FB9INh%g~HrugUSk z_!IF0d_;IT8h8PYc&UJw)E$^lopf@(cgb0uef_zQ&v0sg?=8Le97(*V4*9X0GXIbIllDPDdw*fJI` zzz6X{dJnn$)ae-z;5 z%5^PGju*yXxt?~MX#NQJi10ESc+v6<@shR!Gdh2i4kx2pZ4JmTPpxyC950N2Y<>w_ zKEey|5#i-T-~~A1bpl>e?rvgp{-_c8<(aJ^=WL z@G=j00gg1h%t$*yU4j?m`6K&yIjiV5IbIllB3^)x2rs7qFTjzGm$ZCTHWfglsbmBC zy8{;$N17Zjj9=%YG2<`5M}(Kp058B1FDd%FGt!Q~jGaHC<$7f!`Y)Fi#pjxQ`~~qR z;syAK@bX#U1vui>Bwo^vzm(1gqwYCO2kXr z{%$E=(&nhpmj>X)`B~9za=bA9M7#hW#0&8ufFm9QF9)aX?*{WnG-f0lfR}-Li(O5Q z7sg)=FY38NJ`cm^4h5cz;U(qsLy_eCHO7A@;)`nhFWBb=`n2cbnCFS?;JGA0dl>K0 z?NOihJlLb3vGy(7o$}}CXnqX%i15NZtL2#xFX?;Y%rB`I2m!c_ z$uH-$`x(QFcYs~IF#g2+0(=lJ%qIdk;xY0|YC;O}GIPEuUK*2MUYt3SHN05PFN|Ny zFJsq(p}(f%g*c%^{g-+@Sh!yZt)-XSaedET`t#u_&#*xC`A(F5&F1_lo>6rP>k!r@ z?hDwD4EsN@b!^oo({rSS>U5mm89d#;jAu!fYJW`i^J-jOavAzn&Yyz1 zLrjF66iS}KTNJbJ1M9}W4egxq^!4o*Et?^+Qhnctvbg$WVBtf{bwozbDBqHI2Ck9M zq`$r3EVxjfe^-gsHL-Y&`VEMm_qDjZG9QIJ(8`n5E%U9dPTy2#PRHV-`3W7v~=eEg8d$_=R1(F#g1T1Mm^yoWl!)S;LFv{KEJX^9%41;pJ-J1vuh$0w1LwSk0%08eIrv zWBM=C3x3w{vfA!*lZ-zxzW^T*UakdRfFoWk;N=h=*DGgQ!b?N)%fJDJk&NNRvy2zU zpO{~Oj|eZ<0WZK2aS`Grb$W3y-sJSrU`n|?$6tP`@1uC^l5~&ps_~ci7Q`1aHvV#l z-Tp4)zf6v?%Kw*s2Hud1gQM{};3L8d$1Q;)Dk8t6?t!TB*4!LgGm)0(g@f^zJqs;a z!;9to!uS*O3-Cd_@Jb5ch{wQ7>LtAaUJTX`(T|4k(asX~T^Ykm)F6hxD4tRKgfRZf{atyN%I^j5 z4*))h7oMK;Xgmg9rluW%v9d*L;Ed(xR1{tYK40*f950N&T7C)E1!KOH>tqGyO^FlE zFH;K6&mu3Cu9FSc1w)_qXvfESXor&Xo6Kva_SF0~=d(G#E&hP_n_&Gd?c18)p4<7k zsq>F@Qde_)ufe9c`R(m7pDiGFfZS1=-@c&ox?30ROS#<*-^lNkyE8vyr|R?Dh^xPI z$+GU#KF?M&kOPn9=N={BYcOz&yx(?}^V?77=YC}$DJy@X{DkaKvNwm(xx_*~>3OcK5vs@bY?Id@)<& zeY`HFl6YbKT7D^eZ;I;QvfrimZ|Mj7tCZv^;z{q{vOmlIt^X3<+l6(Uw7WWY`7Y}B z(f9Ys9^J8v28Or}CpCE2MpXhp~@82`kr#}bMz7gzlHkg+#fki- zOqSX&)#2~Km&?WtC)egkAl8$rl`s0t}PZ-A7|El!~a!tY;+ByaG zMRf~DpVEI<{S-C6&U%COhxan}wZJ$#m95qv(}VgW)m&v_{jn?R4a(hcJSC?7IIw#C z@w@-|!n!@5m?-=Iwbvi10%Jo*67|Q%!wOFBXnFn`>kq`O_X{Gk_{Fq-Fx96&4XHl{ z+6rFA`UPIf^-FQ}2jj1~{=j`g+z9P{;q@}DA58V>M?>n5wtQhQW4K{^)GOoa55}KZ ze*hoE3(qfrBOaU952pI`qapRj(8mgXli($;{$Tux^#^!%Tm2E#C+L$0eY~KbCvm#1 zpB~<<+uGqxZ3l%({xrV+V77Vyk4gDgQ-6KuwQ>X zCFeip6vR2rF%KVCe=z>U`UChNUU*#uaKvNN`oUD6e%P-+Bwn0Zg_b74OI-cI_!H|7 z@N7Nxhq`v#=0CR8CAf#T)g@s=G`JmDdnnoX`h)cb>kqLR&lg}G1lQiNT7OJ+IzQLH zysyrsTY)Qy^~d$7Hzw1^x%Z=j_=owaU2p55`|}{ek<0 zxDnd@LVrx_2UC6eVZZ)(rrjA@Sm??aZrC36%DDQ2@h8?Fzz6Zd^9$gJ$ENjzsXqO% zUw=rvw0*YVH3?qg>JP@BSbuIvMF4em#8Yv*+BJihe@>kZZ){;PQY1M?uv z-?pA_KI!CKd&jcwWwcwbMaJ^vxwP0m#n1~b+#a6g!?{?Hqg z&wnuf*!n|%Ukq>(;pP_HH^39m6XGWQ6Hf9WshoTUY))?-;%)6a zrf@T~UBS;7Zbn^FrQ_526pFWq-67n&~LcMSN5@Nz5gqU9UYeH2=AbGKf+IIrYK znj9~TKM^m$M}(K#fEVD1=ne6bdK*k<>eifJ2A;`_e`=2TRbEd@<`>4Fh!@}^!pjiw z0vyq9h?mscC`i0)&H3fwd`pw#h4Cli1^9^YvJQ9wj>_>eRXs|d>N6)dXJJQ=S>Gi* zG5RmIo<~&u7r9T1+vIp*{H5bz?c$$Z5@* zd9TUw!uU)1h|e`D8RZv@I}tC!5BW&Hme|)Pb$*%W^eZ z!uU(`i)wMXg|~cS_T15Zyn&AhFL$H=0vz!waUZC(3FcEYWGowi7w43M-{g2<{E2u0 zJ|euV2VS&1L%gKjH*B6UPH3P3cp3Wp!bp?jh4Cli1^9^Yav$&l9Pug<~8kHFB9skFQ=;ehJD%q+AtIbIllB3^)x2rmx; zFTfG6F7r#;Jt}O?AIYA&-F++-UYw5<+$P5h<4?p3@DbtVA>ai#((#gZ#?jXNQA6-D z)LQ6ja=bA9M7#hW5niyKLjXrQUea#FZEOChA$S>RDR@ne7sj867vO_F znBJeU4<6c!_HC`h4EFKPrGFZP@0ocuZXMf9UqlYW5!{onH&OUr) z{-JeC^Y?eXt?D{V)3|uPNDe%npLL;pr-8Gdd_MjLdG2TOv+kSiS%3(tKCO za5JW1QvQMcUdEr;j{!c27oJuCM?5B8(yn8$_Z&O$Vr|{7sx7~o_nI6pjK3N$sc{mH zi*TI8{R{T%#P|vEVr!g4KC7m7%9+#I-`~CD^!guLJmyLBD+(z;r1kf!ellDqnX&udv-rHKdhT!# z@mIV5gMKOS5#i-o+%Lcpaf5zoYub@Dd+V6+{$^`@A@QQtNoEW$zGb{H{zSY09}!-j z175T|L%gJ2XCU*7rB4I!qSi@f3@_q9d(XqG{KEJX@dA8AczGUp0giZ)iI=nkv0HV1 zQR^gMe7UUu!ML|p=~~7M<4?p3@DbtVMc@TEVtb+gl6stkcFg5aIL~8~kJLKJjN!$+ z9YYJOcNu>oUVx7XFE0Tvz!Cil@iHTAx$D?mCmHOsVG}QEon*%F;#tlwj6V@Cz(<6a zmw^}HNW)9o?ykg(o#)`yIwtFQQR^f#h8N#5UKoEOUVx7XFPnfD;HVrghotSkSlef# zA$U>iBr}E=agg2qF5^$c3-A%)Wi#*s9BFt-J^o^Iouu{rqSi@f3@@%_yfFSmyZ|2& zUS0!UfTMD}d^mOg#aUwMv1X?M{at5D!Os|8cwI~-`@4)k5ih_;gqJPA3vfh#P*10> zk5qqmPFMG7rfXH~uTzoZbwlqcj5Il37=P(Hl^x{8|Fe7wUdd=a0QiXT@;dMW9F^l` zdg}g*!pjLA%g&&^w6Y<18F*_!{2^Q8FKOFP*JFNR{H1u=9$!{dX%Sw4j|eZh-v;AW z0yv`mFuzPQ!prf!XVaX4w7u_>%r674=UbW_FN{BtkARN|FZ%*7z!5Jj@M6SAu3Xzh zd+B8Z@Zvn5cbgn9jK3T&=d_R6mj(EU@UkE90vz$W0xw46FI#Q@W#F-VSCiv~@t5+E zy7puGFTh8Hm-hiLz)?9~rl+o_)p*@j+kbKH&3jFb7sg+Tmx}!t;3L9I3-AIQmE&ca z5ni_5{>!cT!6wHG<1go<3j2fs9}!+Y0K5Q4<#?H%di+J@m#w$|a&6vka=bA9a=cXN zzW^T*UOouC07vC``Ecs~i+rPCYOK+RP&Qz^Zs5E5ktW9r<1fcch5Q11M0hy}cma-h zt-}89!Kv}0_Sx8K`@7CXdGS({kG~-P(*BDYr<0%Z_doz25nft>7vLyVaU9?!b^k@- zWvlJKILq@bO^z4FpO{~Oj|eZ*fEVDX9508Y<`jjOt+)R&H}5t%UKoElUMloofR6|- zGk_Q1s2nddQjgauyllPo^z?jJljDW)m-11?dK&nM@Nx+70vwg&<>1uw0ct(N*4uyC zCGRykUKoEVUevW8GhPRLM0hzAcma+yycpz{xm$7n<%#yeCdUioFXy8Q^%3w9;pH&k z1vo0l%OM8!(bhcvvbx=Ga=bA9a=cXNzW^T*UJeIdfTMD}9Bk0v-J0hE4sRc6a=bA9 zQa-BKe*r!syc_|%07vC``AF*gLObTN0poSff|=rvO+NmD_{;N41wH~kBD}QzFw<1Zgh-QR7^<$F37FExJ5u_5cFoK?5CG&x=ve`$WDmv}KvFpa^>bL+e&#|z_6#0&5d;pI@^1vo0l z%STev2oG`ys)kBAr31k;fGGVm|OmL|sw<4?p3@DbsK`#u6k z<#?GoHGPLStfx)!;y8`y?_OSXn;b8UKe4|Hd=M|hhX9Uv9QJpoPEGsX*6F#~z1>Ut zoj#|tk2cfD#^jglid{{P7sg+jU(~p+`jn0DV*gm;MH~|HQTWZ#|6)Jo)cxJo`6r#+ zn)W5+qi#sw!}oA{w=G)ov2z_~^u06TzU?Jnt?kzVxd-jgwFR$<@iIlW6yxW}Mn+2;2BTbGQ z#$PjTfRhL}M*ug#lZKl^(iYrPx90v$+hqmur{*1>QT-dnABP*_AnM-$ClPL(@cjw` zc;fe&Z(36VC&10tns0Ke3N1~J8^#}pn=$fxB*Tg+-wir z08hMN5pGh>aF34n(PBEeJ;rauPxbMeW94XKicc_pb5X%-V%(_rRWSb2@jkR>`SaJn zM}!vvyZ}eM0uf$PzTl)acYJ5x(%c-{OE1ImK4EP?c{$#<`oh9sljDW)C(b7T9}!-5 z0A7G2Ue^dODMyHbm$|f;UN!(P179xqO^z4FpNJRWBf<;bODBLMUe^dOhwv};$*Eg& zei`~wVWi3N!uS*M0(=lJM1cT~cpTv+vH4$G_<2=e9^=VJ+7rs}4=b;_S$R6e^bbHjNJs0+P z9@?Rd>|q>Rw?}>2^I(tXp&iP|9>zCyd(@{rANE|v{paxgsAKG5+)KAdecBU$hxSXd zhw%{I9`$L@g*~2!eo;p8qE6QBQJ?la*yDL>eC+Y zTb_q@C?k8|iBfy&{l0vkFW>Jg-YCZ}?XS*VzKi;OPFKgG&OWtjK)$K>*u@>Eck&yx zNvSn;{#3bpoqEgfL9MOz4&Cn1_BYPgWafG;?)|@3*ZrzEAm8n~W7YTjs<`58r2G3}MY$Girqgy^-WeK}=RQClPoAmU8oA)5 zGnD_)xI5z3`vbaO%GDl`8B={4nt=EFT3e6e$aWjJIp318{(v|j-TR0JE)1_f+f(5{ z&DSvgxN)%X`vXTtxWRow+z9P{q5XVsPp`>>HB){1G0`bZeB&Jx9kIuY0scqVF{M4j zpuD$!o_8~b8@5NiGUtuOjp|1-{?(Ej{;5?!GjdiRDbl8 zz>BSMFh}9#hJ06(;AJQVFO0uh-Qi4<^$B>^kHOXGbs9KQZh46xiNT56;h)ss^iSHq z(f+7D`$gqv82$HApT_7azwi@$pMGxpd)S!U+96ZzP>%0=*B^f*f6DKT(IdqZ^0iWL zD5-tqoj>|1{ddJ9s{UZT!TQ5@wgmlh)+N;5IO%&@{c%iR@A9Sm=bB~y^9y@AWdV|M znBAEuCO8u%GyW;A{@4}u#!ohf^~DX4H-(apdjB+ZSf#qdXMMPT*dKi8mpd1{zx_|y z|F2$uFfMCF$j~VTHP7QXJLR3W9ShFDXA92ISLAW!Pt-3!{OlKq-OB4OYUB9{9@Z^$ zx!laUl`1GqMEzl{AF0}H;EuePv3`Mj_0bjaSfR5=m`_FgmHUw;bqDYf;bjW$ zAK-{53-OZnu63LPbGdffGLa3zi*sXsFk^V}EaQdoC*lS8i16}m;6=+bAzo5Wc1VDH zASY97llb92gEWX&rq9e2wt3( z`H_s_MOcVJZiWvj)Db6UQo$??MY6Y&CkM0jDH2pnm6 zN!@{w{TDlMvArLG$}i4QdAG^&!uS*M0(=lJ#D@Tmc#Qm#x&w1S!4h0pPum)25Ad>I zzAIyRaV_^>7=I#OFy2JG2yNVnc)@zG)cu#Vvur#+rRwimoySvSR`UJaUdHgk_Ar&v z_zU8%+}|x(F93WHFFd~hj(7~bOiMeyXmK7d#EY%`5{z*^pC4>;yfA(}zwr7iTm|d> zFh0%oM*`#2{2s^iBgye_;ED5Wv`2l~qn&6R9P5!Hd+aX(x25*fd;;eWIG^B64CfQ5 zPy4p!6Xd#|*7?Uet3ma4_G%V@em-hjRAe zEA#Kk{f+E{Ri95lT>YI(mUW-@d0I1&1CPsfOz)Msc{e$aaDqJlGjf0}7dvXA@DbEk zh@bgMpdEBi!v0U{^2!PMtW`H#_p$Zy8`W-Y`xX3*W0L|*TQu(FYR=6>G~M4CfpZV|NhwH2a9rDru?biza6VL zzJH1G3F2iw5l@8i>)s%rr0#GW-Fx~`OFB;Nsq=9S-3_^4I-U=>DwLOLm*vEju*yXxxZ4fz6$t=@bV1sqU9Oj zCG9YVbM*AW{8^nHefgg5rS)R1{QH*oAAoVM$??MYwf>4+w|lN!xqI%p5g!2`5ne`s z7vPB33V2C9f1vPkv<=LxkNsA zI{%oC#hvr#EbK_%k!ehR@tYhkj6V@Cz(<6a=YSXBNW)9&0bSXDQFKIesb!=3yCY4G z7sj91-vvG*ygU!Q07tyA;G>kg;W&=Oi=-o3OD`LR7x8M7kIy0gM7#hW5nf&l#}Nc@ z#48KDq#n-=_Cc^vAvLN#YH4!3F#g2)2>6Kbf^jDS9BFt_Lwcz`GZ&xQ-MOUS7%`2) zi`(RQVf=}B0X~Qqf8yr}&(7(e&d*iE}MrFFGR8XneRa2~+d*3Edwhx{)7g!dob`iF2FylW(orSkyF z9`$KYv|!&TuJ?E@wBv7ry>DT^o1V({s84$??D0JQaiM=M?25JUZ)Ip#_mBFt=fNJ& z!}U1+2>j!7vbX*`ST~^Cqdx8Vu;w9oORp__y}AAzro*_si1# zqdx8Vu;Fp z#riLCQ)pL@m-@8l!5+^;JG?GpE&RJF^iQ`(ecJP3&t=@$x6IGsKE{4|;=C7v>!RDE zKJ9V;AD%~ShwHlu*LO9p@AcvJ9n*f;KZy2R9P>Q>U&40dbM;~p>|wts-5&L6&x1Ys z8N~@d#ra{JVyDoqZjbu3=fj>$yT^v{M)M;N5*Ms`B=fWP(6WM{EVlcELeo`4P)TccU_IMt51lM&leHSJd-PN2{@o3G&sMfaecJP2kLMX< zZ$0ciSJ@u*Y0rl}mv(jk9)P_UE8C+!?TLfXesT65guRz4+oL}1xvBkY6r|>Ayga_QX)Q-je5`ohWa89r^F7%KlNG_FUMbpS%wKtH@XL5bxua@j`vt z^I(tX@m~nzjQqPC{;di9)AKX+Y0rl}m-6Y*p1U6Y-2gs+qH=zwKJAIy(SD5E5AD!T z@hJG{vd~Z6KkCz-3wt~d{qkW~JOz7?gi^mhs84$y?D0I_e}(?Jh+Dh}d%N9Qx&I7( z+VgSD^LT&IuE(js-<6fG2lZ)BtV8?J&$~kZXjg22e+w$xqdx7qu*dUwcjLOkuGk2B z4~J5}9@M8j5B7K-?@7c$XM>Hbll_B`0*dBmfkJwFe70`^u_ zwnu&1^I^|r-2V%E^m8)o?GQ@cKkCz-7)JZi?*AcP_$hXUz3nU8qdx7qu*dUw8$x>? z{1guC?Nr$w^=Z$8J)XyXB(&$!&q=ViOJ#f1r#&C`T*_a*Na75syrVl(Vb4E@vXQJ?l)*yDNFuXm3DUM@wvS69X}^=Z$8J)Xy(6x#7#4*e8s zP|v(OUHbK)KJ9t1$Mevhm;!rzALxD0R~&DmKJEFi=Q3{8zwUmp z$M+e3wX%QIr#*2O+K=`SC$F>cP+wkIxxS=6?YXeW^UyC3*IBH9y{jtQqdx65KJ9t1$Mf*M<+zS`AiQtI z#L9T4KJEFi=Q3{IzkB2U<@@s)xlj*mPj9)*8Dsq7#1Y0rf{o`<+| z1^q+&U0vB8^=Z$8J)Vd5#161G5%#XDY>)c1=fj>$3BO$6MqC@(5j#}2M}688_n`gg zC;ak&YjHj7ZC}|Q^=Z$AJ)Vc-e(o&9%YE^0tK2`JKJ9t1$McM_hy9?%f}1My2lQ#r z$1%?%b`Je=Ii5WPyom6+==U4-X-}+2`_a#j!XD!t2>Ti0)XM%*pY~kX<9UQ`?>yLB zRM{T&Y0rZ_p2t62^X~%KJFT)k>eHSNdoKOd?Rl`*RoNc(X;0jX_M_d`!hFiO#kHsh zKO5TBuLt#M&xJjnM{GfUhM&R#p3kprkNULd!5+`!?W(n(54-|aU)1D7|F8zdGE^+e^>|I^i9`$KY+>iF7UEH_+E{OMn z@Vbh1mE)y8?YXeW^DytZ?|{AYVegj8`IP#!=fNJ&6ZwU_C5932ZI$g&pZ0v%b1C5$ z=k>&`xIb>HY>)c1Csv31eHSJdpwUjEwsmW6vxBfK;`?5 z`n2c49?v8G5Y|PJf0Mz#gO&S3)Tcck_FUT4?d<}4S68-2ecBUOp#5m?K&}1S5bt%N zJw3lrpY~kX<9Ympfjjsq=EB}im9Gc&Y0rZ_o`?BBybpHqzAABX<$82b77C?8DsBa*z2imkNULd!5+`! z?uP3NKgD|7zh4dQ>erY0wCBT~OS?0)cxS`E^D5sT)Tcf1eY79!Mb~#9TwlCTOFSNv z|DaEME{=H~0XvLa450qKyRtp%)1C)=k)Ny=4uF4npO!c*j9b6H)Tcck_FPED>%AZL z@IEbZNM(D}r#-O-?WfuE4}v|sPfN5{wnu&1b77C?iTrDYJ-(Oo=*sq}PkSEh@jM>w z05`%7?TA^G?NOiheAsj8C*owD76sTluChJq)1LSN+K+a5U6BXH;jni^WqZ`8Js0+P z9$r`Sk~kFhrd75_ecJP2kLU4k$GF2 zd%IQUOX|~}4|^`{!jAtG>`e*nh<8`EM}688KScY%9_@I~z}{Z4_nyl3s84$??D0I2 z9kiopg}rAgUk~cjo(Fq851+&5JY4kL`tz0TQJ?mF*mD^-_NnqQkHqJ|#j};|QJ?n2 zAlgr}7tJ5>xvVvn?>Fkxo(p?CPZTfbqxjs;Rh8{gpY}Z1<9Wu|<8y{rR<=id+Vf%0 zW!z}LC|*7neR*Yj)Tcf1BeY+fJw7+Py0Sg$)1C`^JP+e_F;Bzw<>IBv*O&UV=fNJ& zLwf@AG+ciyHdVGqecJP3&t=@iAM*m&!M|479`$KYV1IX>M_`^YS}*Xeu-(LlFkk8Y z1M1VB3wt~d=NTh=m%`p7mF-cV_B`0*d7^P9?k~4PXh&ebI^93&)1D7|F71+sXm2+1 z3*Jkh+oL}1aldn(N9guWfj#V7uiK+O?Q#E6o+lc|rhnW=4*Qzx_NY&L9`-ZkdB*s6 zBK*Vte7ZgA)1D7|F6}a2uH$9%J!&FdmilZJW>169{szxvOVh49+n?FJWsUFoA#E#zdOg?zim=^@E>jr#%cGE zzsqeCot*qppIq=?^`8mOk6NGkXL0^3!S|v+Yrj0PUHAvJ4%(S4*Fl$jU)jCyzWd(T z_Oq=Gwqal!2DV{f8wR#vU>gRuVPG2uwqal!2DV{f8wR#v;IA74C(Lx5rE(xZeE-+M zIKs!|n1C7=sP%Kg%+sbX>gn$9oWHEAqi@mt&PAu2Zebdo`nU2o;fM2i(H~R%!uMk< zIrcsAkwLXzy>svS^+zblHV~JF>!Q@()W`j7I4%<&RsOF$Phi7w-ctDs`d{VA)cA}i z|IT>jP)+1R>DM{$UHUhZ-v`mYU1x;v;h?Rz^A||^$M4fW_ZQ{YNBP&cXzBcAo&EjY zOHQwULt^c`wI0$x`a}Ol;2-@~{w?g4o4qXQ>`VKuoLYS<{T}_JKlIPPCu~3Zt^7Ob z~ z{p0ndf8yS-{dwJ$fBo{EG_~4I`d-)i&^{%<&-}$>`p56lKmI#q;9qx-Oy>*xdV6~K z=Y~uA$M&LsgJ?gttMae6SMAf()4fdYyo0UJ8-B^@AN`?!eka~v1V5F3k`d=G?&!DD zX6}8!&%*Nje4u8X{_*?tZv^_KUtikSDbw>Txl?E9U+eqbdo}bcPHPwW59)^><=?LI zpj1y`^b@`Pxs#U24n$7A(WrlUU#GKRN5(?m8B5Er!gDf4)z&t1xp#kP-+QP$w!dKz zko1q=kNkU}Tu*&{iBT(uCv+e8s=lj7wPWf1uKb%M|5mCO{QIsS{5^edfv@!4$1!74 z-=7(tz9Ih=F;?jx{h@zd{}r|^{Z{_9$Jns(=Oq8=5B(DlhW^oS<)3`fPs2Xyyp=v| zKl(%e2H_w5R{q7l+^dq|I{&8ZSNhOD`a}QRUxw{Rzm@*X`5iq=yE-bFG5*_IV=T}= z`a}Ol;2-@~{(?Rv z$T_9lGOd!KI{)T_yZlGO^H4pGTloFRzlY29l)epaIW#4=lFjyKU)Z)?@Rh!c z{|Zxm~KJ=Zw(s%c_(#9hy(j(C z)$2YMuY~(t)v8GU=nwt#9uM1(eyjKvcP?38tKE9Pm(+grhyD%zU+5qGR`<@FdQV#A z`z`+q{NOzNs;Zw$KWsmKpZ@vK=XZnl>sWRMk8R7i83p=Bf9PM=#xOqmt^8Zo)qPrH z?vD6q=^y=}e**1Jzty;OPw(0Bh8pxQ^pF0~Kc0?$EC0IW-rxMYeYtsNC7bk*_XGX& zp9-%p?;CZ0%&lY~<=@;VfFGQPX5#J-exLr0K%aVV_WePB=%4pw7$5z9v+oc3L;qUP z?)3Z3zCY*>{o{3|-*5K)!TW*!u}{SNMqOXkKRB(o&(;tY?xSm2Eo$-`NJl=9|@br9bq~8$oV_pSboas&W0W{pb(}vo z=^y=}f5bHXR{q)K=6e03KlG3K^gFn|Z({CYuAzV8cOm{*KL_00**|}2pRLsqY=KY) z_iOo|f+JpE`a}N);UE2`e?98mFyprJrKC27KlIOi4(*4()4$FoXH|%@aerd_(I5IZ z0{_^K^iRG8dxiiKx{i8qh&-*>{AN-_$XLL4Zxq-4@=|lhM5B+O-KJ<@%NB*_W zPyJrTO6TX_lKi7T^v{QX^qc;1&YpH{$t3^i&;QTf*TC0NmFZ7Q!6PCTL@1x;k0@Ei zZqgQniZsm~%J5YyEu|FJG_+}xC2c~Q@+E)C;s>+RMbxT@h(*zjdU9BS zS!BC@{rMqimhEC!u~w|`KWFB7CikA)xpVKFb3@0=)$nH0d)|59cb<8l^PY3&4DIXw zZ5Th=t=ex`-_^0IYjx*_-ocLGK9-BvCd)qBL;FNaxaNa)?+qe{zWg5TrXR!bgZ?Q$R1P(U;^qWD)cjcS9GSw)K3Y5d zdJt2znLaen4t=0+^x=}8Rf8sjOkPSKirdBcK%4190Y1<-2`A^m7Wtn#eeSyRZ*i}d zo`5l?J+!ZTP8eg_9oT2Bf-SW{9o=#JF%M4s>v%tn_Rv0YY-k_t4(zkB=%Abt@^An0 z^{-d7kM_{MVc18z1N&yjD7WzE|M$!HR=mEnhxU2Lh4G`^fqio<7!sr6nWvw|`u@@{ z5P!6X_Km?l+8x+emmXSZ&sT<( zJtl9pF7!WLaZf76-|B}S6=$_pskoi;<3DAQH70*}9cVA@ABO$B9;%I;JCSpHYp8ls zB<-U;w9jh`<4e1heQJDZO>f@?oxS$WRQk((XdmsNePizp?W5gl{NLuYn`7|b!+B_1 z3x9#6ef&P{^XG^56@T5v+}_p%e5yDW$5Pp+`dY>9f`9+j*0r>qw$k?I_Rx0vq`tqV zj$OH`+&gXkYUwp?$PFv@ggn9qZT1CwNT;H_I56bbV|aNE4HZgciKmLXx}jGqus^!srkox&Eb|>H-7)p9@^)f7RHZu7uzSZ z%;3sCyOZ=u*O&ItzA@NGyLJ0IR`>MUB;h3cXbfqyLJ0|H`ugJzpCTM#2@XU zea&Zt_R;PM_VukAS5n8{XdmsNeFfM@yLJ0kbq#j*Ov3gLw2$`CzV0)__|b0NzW%O( z_5Bv(ru3Kl&_3Ej`^3V~KH6Pu-^$BY_I3?k)^D>Xon#;Fp?$-!k9L>Xr&bSG&d^Er z(H`38y*rE_?Jl;jzo)-T^05A73+L;GmAW?#6)Oh=FjJ8Vq3sPVyaAKFKIXx}jGqurJ4voYn8bbV8{BV$ZgKWxLHlSA?Q1?Sw2yWd*=K`plMTZ+XdmsNeFfM@yT|QY`?AE3 z_RzlW^TYVj?jrkMmiW;g+9&=lw2yX=+t>NB#Ei`~XdmZ9Y4^B& z7rZR-qdl~bHyG_MvhQVyALpuRUw0?+ALf|V-1Vw~&PzIaJ1?^_D(-gx-z!4NcoeVu zR)1rD;rD4@v(`?1*T&rSSjxHU;&$p(TT0Nd%4`u_U0$IVgA>hTHeDWjON zr9HHdU!~ouy_`|vpC?VyK4Ovfi3>u^5VLB1keWF(eJ){V!nIdp=*8pc%05*$7q<&z z9j*nX{j`_%k72J_`larza8K$ME3q9$d^~MW+hW_*iD)0cPy6(C%0BZQb!vBw_R${N zM@_U_*;k(@26?9PlJ@a>>h|%vk6&Lq)Z?!T@!yQSk!fAr_2u_zpWg1}zP_}F_R$~O z{c>Ml?mtws=U&yyzF;J75}!#{F(UqG5A7RX6WT|+m3=aQpV=v&KI@UZWcm@% zPf2|`&(J=8kM{BVl!1NyofmDW_h3Iy2ub@GFWTpIhw)=vm0vyUJLD2~O@XCDJ#JJ> z`)CjC8-sncTeX*)t#n*$qhrRC7s)+~elPx&_R${N=l6v1qut6r^?ZOFJ(LjaSl!z> zIRjv{kM__$zKer)EBvjNb0-({^<8+%K;MS`VkcAl-u(Bt{~)O%E2;}-tvONY+mk9dCH08f$J zfn&(=R^@*y@ZIN-A3FcoeEyq1&dX;#=F6uj+T|1M@~8fvReNsCuiEp2`TZY0e02YZ z4<1cAqr%g6c@63Jr*S>w+MT+t-)I$=X?xl=RqkdzMgC75ygkS#3SW!+R$kbpUPF^& zAC6Uf`Z8vRjusN0_u=_>7wIjYnAg(Srf{IRkp6Eji-Yj~5AcHfA_*_=-Y{qc7}NHQ zg~H2AubXNeFJl?Q3*%ubi5L1`2`|ShTp=&sP!?C?d_rDfJ`%v0;%fC#=T-bez9Ih< zUIpF<|A*g}?>4f|Kk0g_iTtw@d_(yHjv?t!oD_E~2>UsZ8@3#qZ=Ltxr1Q_#_iW5> zea{E;U3X3&?YeWH>iGwLC*>1U{xEIN`0qvj`NpcKe-rZ0sq#Un+Q+@OzQ>m_+jms_ zx$=HJJpb+@#aVXwhyLF%#U&WLq3V5mWOrzA>WXH{8xwk!}j#gI{&n$8_gmAJRev8>;m6VzKCN; z`V%KT@D62R@mzQC51-3TcK!3jgCB99cyOaTbNg6s=JxIK{FOgZK7rp!`J`tzsefco zD6D^O)A?sXZ(oY{Tt4yOH8N(~a$d&rNnvg{zEk-sC;uz+3H|?^#y^sJ6#b0z5AKU3 zy!7oR^^d|!z(1Dp(w#B9BqO1^ZxAo^zY<;)|1dAc@elcgQfPTt=O6M7`Nw-r$UkgP zFRb%V%L!CnlT75FA@C>VRXB!BI++jtp=>&~%{_kMS0+#Pq|xP zkT+ezC*mLYos>@k{+Zd*lCBDM99#8|?eVv*M_(sn_LrQWv3w#}y!3mgyBp^=P5SuTA&-CBJ>>Dv zxR0H4Y5uWuy5;#ReY-%0tzls`<{k9%Xc{yF6F>t)RP^M#D%6K|2-@i+QksXrU= z5AKU3yqNNbY5QWl*sOnum$8iDWjr2czmb3Fe}7XkKA`hZtJkB zV}6|G+W!8j-+jdW)bBRBOKu;|FS&hl_51_Blk!PW|I}tu$+ve`{`u7Ju8}djB`$PfAFw{iTl5%yDFi(^Ro6DK{ymvY;` zp6)I>>8SR}p8sjx`f0ay>u20c|88mf12eCY=db*U>L2)>lurWwNk5#j+m64rZoOW{ z?BaGWWBJ6hJpM-iD~+cF{Db=<2`?f4qz8;G{;@s&M!a-q3@??lLG}Mi{-OVs@Dj}b zB=8UUgi>gESmz(|4f)60Kg`!`Pfx7#PpjGd&kJ$%r2Tpe9 zyk_s@`X^3d+P|Oq3D-IElkShEpOgR5^i!&@f8cjgJ~6FdOxrUow%5NoXKs=)dw1T? zSU&OJV|VDVrUkkh7<40x8X66eS%O}3&_1E;jQhzq!AKVv7croP<)Aq%93HZm-^J2uySjO7OnBiJm`gP4_Z3^3R{*>YwYu zHksZ3+fP1!Gr7;79xm4(94^-%O#j9Cqtkz}torAF;CE6! zG35`__T%xlyZ+#Cx&C1KFP4vrzhrCvM_68eK>sU^=Lh_Q`yvT1ru<>rz8Ehy*B=ls z%^AbXcs$I0BmdC!_DqbH z!cmY<;CE6!=~2)Bq#w@TZRdZszy4$yvp=_c8OtZ!-$lnkt;ftK^uJPnHoyz+izK}C z1<(Ja2aGNLu|5AoymV&_FSX(#?)$_G{jY?VVE!k8f5<14Ld(NC|B!FUKi6gQQhzq!AKVv7cnSHZ27qW^wZ%WSpFbsD zhBJm2Exf4@$v^bJ5?+G&p9KCPpHK=d59|Cxz9IjJL&JQ{_H^vYX`kO;{XV|mU%K5g zdB{V&3cx@`Cq;RX1J@WMQ+<(UvKt*PH< zBJpx^@cKoXkW%i&{8DzmrW8t5UUuG{7cXXPeBbi=Ci-8zUS$fxsbs`Qzz6ZdhzsC| z$G}T!LXvoyzqW6K+_TN}V|P9%%rE`<=8WORw>%$2|10%xgL(-4H61VdRSoNzj&u)^ zOJ(-@FLw7M4f}lkTfB_nMZZ32k691V|MGkk=9geSLP9;n`i4@lJ^;@2dWiK8>!HG7 zVSkA2>6fkXxM)4XoOG#=<8gnEtA~Ds{v73_IEJJ@aZ=oc??VoKwJraFH=iMEp~+p3 z@Z?pS@=sp1F@NM?pUfS3nA(r7@+aaS_??tb0{*G2vf{s*wx{wba;qU#5BU%3`@t>k zS~*zzhS*PDb)AgaXL8*c%O_rkz4h2LWN_*K=Vj-F{S?Mr$qDX%jp?|WX?yyh zaHG~G*v5^YG2Ad7rc&h(g&X=`4Q>=4F<-{6Pr&#Zc}8e?S?4425BbPH0{Iwv=%;-? zN>{oi^3h|kpYm}WL(-o(>4AqR5B>c)`7^)s#!2U+B|E;9U$WzK`R8w1lY9QAORDE1 z_??tjO!>sLJ>zeikCyDXS;nj{H=MD&A}sR}{jVmk1a%Sak0jif@`-8tV%*r|BjToz zG2Ad7rjmR_|Es}`;v?qCI6fl3Pzo(C>wHB1As=~7Vg6=&`e~hyTFv%Lh^>#F0RK>K z#W5uPiIYC~i1K@GbAFG!;)BVpk2cM|D&M?jFyH>zJ-PPBzFj>Z!SAHJ(zBbam$S`B z&18}U-M<^kgJSgn62AJPA6 zaHIH$c`}ZV$S;&a%gZ_+k$=cX;>a+6vpxN?&PTJAH?@CQAN?_IyzZyqAIhKO7&7UM z1@IB&Em!%u{GLCXbUxaVFXVRQAI+WR9_gOtz9n|u0{w}`>)>}%UNNn2Oxx3L+w;*o z@(;_H9pyG>EU)4lSpcLSmz(|4f)4^Gx9I$AbMw=e_G7;Plz3ldkXebK8<5Y`V%KT@DAlCmv7$k zuGbwX^Z(?I$H_O=<)6Iz$t^!Wu*3cNfh()$ANZY=PkR1J$K#&7db^BSr#qand?GBa z-<~1CP5-MIR|&@BaDOD>rthzGJdU_2WDGZPd92pIb3BgzSA!eHN6eFPd_;bs6k1-^ z`H1{OKJtzZ^EcbmFYA0Xt4@6MYw!={7>*(7Pn`6@N0euG|6t4T%-2jhAGKY3c)so0 z*XDP9Z=t*EduLV8NANo-ub9>|rtKMj+w((h*S_*bvAp7+V{bf8@e%#6Ca(m1 zg!>~2H>P!sY5QW_*j%qb+=$I#zTkNpMUs!`e>J#Ke8fB%$4BHBN}=UtosY;r!m-~3$ZO{1I zUN5&(u9y4aT|@40#`1}3t8xOCe);VLVJF z`G@{j!i(Y`=EXSvA)inREf4GbL%t#Zcr(L%&Gz)qI{(a4-qikK{S!MLw*!1bxf92b zNoVxIKa`t0Ka^j5@#L@9?%)66eERnu(Emz!Q5lpKJ>ze?{@M81hh)5-$TepypLi?mtxpJ^7lQwl`m+K5;J!%0iz$DYwlBtu&H9IU z@iK-N#=}&Sf9QWDyr_)Lycown|#cwszDCHaT`C-D#SV;ujGPa>)1VV!@- zH{>7x1IX8?gXo`q{xMq*7hC^Kh5eM%a12R*;-m-Oq3l2OvfMi#`oN^~&!)%k&24)8 z!Q9rnzAJxzSUvy1@1%TU${(if$K!8z{lTWkzbWJOz1(od@`=|KPqz!iykn?adt3Xvm+w_Q|G@90d}7KUrtKO3 zdaOUV>F!%Vtbe&g%klH2(DpKJ>zftdDQE_cejk$ z%v^WI@=0N(J^q;?gG>Lbd9E1EHxH07s)Aq%LKz=B(=P(^AY)neB^%w`5Sc+{j|$%ey;lGf#7#iUNPkp)Ao$NZ9Zy~?{iqP z@J4qyV|hhb-XDSfSCdx)KEnNxgd0;nF>POr8=HJY+!Qi~8^*&_l8@+rHMmiH#5@_t zN8}euq2*3qcZug*I9)9$RJKT|y)!SAHJV#+6`?HPaDe5BsLI_v1`-LZ`2m4e0bIn~dl|JCG` zfRAv0B;m%CPfXhv0|})5oMEn|LU=WCr>&bEtBtGT_)eZ+I-L_ z+~$KmSv?=Y@1(q9$|t7nc^z!?(K7k|)#igXxy>2NE52nuqW{(8m4J_MeEn3#HKVvd%~3AM#P*qhbDLd-`dek6O*< zk7D`g2=EW(B5&@yu9UnFNq^#`xCiq`kZS$Hw>Hn6bUxzxg^fEu;%?lzv3fp&-${AJ zluu0CGye5hzp!!VHEwst@``79{{;G9X+ApOA>0>9croP>)Aq%9Q9L9pu3u1i@iT@O z#=}%{{Q~{3gcrp>%#U&WLq3V5mWOrzA>WXH{Es1jqb{O<*7@hyI*rer1-_wNf@4Vf z6DK|J4y9VZFyqJbCY^t{e&MX2UF)9pv+JtoANZY=PfYp4v_0c*yB<>W&}aSZqwa9V z@`-PG{Q~{3re7QI5blp8+?eu+Y5QW_*sO<$n?lBL!+4lV)!R;CE79>G>;u|J_5^-R_QMEU$R){7z7}C*d>c-Hg};3M20 zNx13zD}Mi-!i~74!RL$Me>J!X=8KRoy9RL@87J1MW2);Ff@8GqaL zk$R8WHKz@`%^Axpg{5}achmoB@=Cx*xIdC`V_M&swlBtw&H9MA@iK-R#=}&yA4C7E z!A&qNDs-BPFcT!$4G^GC>&arF`TC6ZcR*7=D1 zLq77a$NUlMB>HKckLH-|zYx2Ap&k4~>EalY{=`WS@uht7g6a9scbq-xe6(oOiu|HY zi}K%i)#u%Byz1ua`3Qa|TNI+vcN1o0iF#ZFYwwI*a+4}C-_Yo}s|4@23hNM4n(nowLXZ-xe{NlUwlfEC_QK$Vjf7EHe$)EIt>F!BC zIG}nyg5ODb#gtD>+mFZJ?tXMfo%Y`{X8XHi8Otk$E_-~W_T#4imG&14cnJ4J5?)Ms z#I$`eUK9@rOZ%Y`FXBs$J8z`$LjNn_C73Tt;2-h{rO@)Q&OhWE@{hO?^F^qOc-^h@ z&#`l;x+a;pe&ICm4dod)hD>^*5c%iyORjQHzvP3}^AG$^$|t7$ zVcLHDI@sr*(=Yje+nlj{;;pjFKlHy+J_+~-_eBz3O!>pKeKB5a^N+%dmodDI$HVM5 zRR<~lq5qZe63h=J@DKTfQfPTt=O6M7`KRzX%nzXsqIdTBr%vnV7J_dmx8D=a4?)tO zI4Qn?`60*+Q$C)5=7)18oqt-U{=a<7)c?r$e)_|1@2CCh`3HU{Fl|2`f4ltC zGWBONW>>r28OtZaGXK#3O8F$JVf!|5_#FRfw+mFZJKL5-(_)vE^WBJ6lJpM-iE9H}b ze{f$U;l-3cOxqXZ#Ww#ayc9Bqm+^R*{YL(w|CR6(%>N|t5BY>rXn9!YAMy?P$GaKx zKd6J~oqhhP)BdMBz&DgTaSTa+;-ruGQaZWe{M&x`HiGwLC*>1U{xEGn9)G+1Gqh@#jM@9$v5e&t-*Wv!|10H_fPZjbB;m!BKTO*f2 zpG`CNk} zOECYFz(3>@N}=UpoqxzTSmz(|4f)6aGUk7vhu+!epLbAoO)`;xrh;!Mr{Nef>0};whf>u)Eprc< zbpB!egk}Dr|CRDdz(2Sz zlJH{6AExb#@nVyIh?hdf@G>3`v){-+^uH2b6#pgESmz(|4f)3##{3WJ zAbMw?f9mx7&tBjgN`YfY`V%L8@DJrP@_E!vKYn)7*B>mC&!aAr&!gUX=uG#{LuXY# z{szC3@`)*bn6_v9Z9k8?Og@i#=bjSdUkz>)A2CnH@e%ojQfPTu=OgkD`AFP~`5@Fqy#ChtsMYLw zpcmra$GSK8hjJerL(-o(SpXkVp7)cBazEMezDci#rmgr|ZrY0bb4`D`y}jvA4_99g z!SAHJV#+6`?Z@M9w;r0d;vN~Z2ilu6mRJ0F_VzPX&v(%OO8wh_hj3pc;l-3kOxqXZ z#b!N3ym%SI%XmD@eq%jE|104|@elK29RH9{D20}Xb^amWkberdVLk|T5xuj{KP}3e z+CPcoar=UAD5v8XGU<%se#{3!ZYW%oJF)$X`N^ISTDJ6Sxn)c5&n^Ge&iwLUZI|b- z{E6m+;CE6!G35`__T%2z<)39s?~yTkKHr_OeBxQ=ANpS@p9K7a`yvT1ru<>rz8Ehy z`G&wc9_$9ZtVxyL^Iy9<^55&yvNqhStAo(cyuF}ODLLR)1QeuD4Q&R6~(#`KjqWGW7&_QjHbFV~zg+%O)s%DDQ2{wLNSzz6Zd z^9$gJ$ENjzX?xlsM`*%&)oT6GmGc?|FLCt;{ZFhvz_YK^AFNfBe5GEI_vb5d*sbbU zg-QN64r>o3$8%}vZ>p|HTYs?LVErM!hV@^V2jQ8l)*o|%`eTk$`}BvCIR9}3>J3Wg zTjBGVQ$tCAqWO=HRjxnUWc|_f=3R2$q5AqG-O4svM#=i)pqw-0R$qU>Z@phYt(2zq zgK2x(QJ?x_X0AJ9{Q|Ml?)(S+ue$!geL~y_?SA3)`s=PgPRRKg!ws)Xtun6up#O>W z2k=3>@caTe;<0J{VA`H`)TjP!dV}>x;pwlRSW7q#;{EECHv^>mpE}VZS-;jU&yRrTkdgz@k z{t4C(%OYChk*aHweEy`Ef0TkZefmG%`I|2tI!_4j4dvcAhDYPzZgeK<`eo~ejKA{-7oHoB)pjNhiQBIr|@EP z-7oRdoH4vG9;T9bq5qZeqWFh-F^+%8CzMe>2F`T;A>WXHynC_!3w03vv&BF2*Iv-m zwN5P(Psc#z_~%!Wclaar0pC#Wi(^Ro6DJGcAIjT)x-8d!>ks7oOJ)9nUjg@|^Gvho zmYZ_UEnm(({+-v#pTn!?ANZY=PfYp4v^~AG%|Fg9Uy$*7L(a=sJ`qdo@(=y5luv^C z2lqu1UQGGJw0$vNZ1NBB(w#B9Fdn9o{6qgM;YINe^I{zTkWVP1d<>lF{6oGW|A_lA z|BpI|{yjPE^V;)|rwsIM=;uFIEpwf{D;M;wsrvi+7Zv}gpV;>SOb6c_0(n@eq(1-B zkzic_k154B@%%mH$g00-?|b@V`R(E@k^|zOe^h>L=@ zl4EZ_%gbl8+V9@$ld(J$)j#l``9$m=`d_SB{T}c~N4h;pReR~>$?G~V=&kYbSJhPe zSRQ|qadSrY9rZJoPkhVu5B;w+o)Yj6@DbtV0NgLY5ieGVms+1zW^0L;*>1V_c2=tqyo`4jLWK7+$;{yZsgVUy2u%@6_6|E3b_53-A%)7U$b@9kPA zH)iNKrE_gp$KsWp>4~Wh`DN(n(Xou-MOelQ{V%~w(4W%q0(?YxVLuKyD#c5>Ib5Yf z_FohoQJsOT171e{c2wM&t?^sG+b$o`{}Q~kUF=TCFTe-!!V4*YBOZtOCEYv7ln#j( zNk`OXBI|$`=lId)jNzqV887s|1TW6z5-(0$2_K;z)bXNU(Qv$^BlS{liI@3n`!=jg zH_KOS4aWOzJvTKZYf9%2c`svlDUOKA?;LNT|D|{dH4`styoKWdapNrduwvM@vlG(~CV=4;`lO8x-zr#_v@v zRotAjV#lSb)-%apES#OLzcO_A#C?N;aTHwl2nR>vz5qVx-qOC_4QtcGz%gx4JN9te z3`MFUjZk?4X=*?o_M^ZyJzKv>$=vj=O1d6rtQa1 zR|xZmt$ryK`wfDd6>prFKh!!%`mgs(WuH_&;v0^`-X|aUWxtXANdH?{w}|;WUME}Y zMsk;}lskLoQt$1_btC^1*N=P)_>!_2$B^_VPI{QHqrCUptK3B=9VN%FE3X@I4E@sW z+3$%h?tV{)$Cpj>gsDw|@T@e^>q9vrhKnQ|uc{J;68#4-BO3 zbtC&dk(V*MxP3Td_kZC;yYFqF|C{AKuAb{J{S>WR#C?&3m%gCvOAnZ^Y%H}R&5`YO zi^NMIV|YmuyK-$fjzRw`;YE#OFfYc9V~|fMg_ei)aSZYe`N#V<)-7T@gErgcpVp@N zPP#P<s^p*fP3dRWOD%fh!H>94Jh;(4 z>@#0!KkPFP_H8>#u(Emz!QT)Ta7{@>46H1}w zVV!@-H{>7j9jseK9Yoh`@y}UZa=GJRm+VNTn-WUopPAqr$~GKB(w{h40RK=n9oy!P z-1^VS{1c}z<=?j+{ZV)8(I0c0hW@*K`pBM%UJB+!slB3Hj%*ul^xkyo})`Wm=igjQm6YE8#`)5A$Li|Bz28g_ehP z{vqFxe+na*$3-1PgKe#wpWU>muV>w0(-~a@{Q;WQdq~z-kL#&Z!*%n2imQLx!8gB# z9D{r|l=R166|-*sTVX%QgM8bxt@Gdc$@>!Laf|(O2IT9Mnt~n1(hhG+Gu4>i`{a42 z%X!?r&T%aodvX z&R9MvoR@AMSHEz~C-lEkJ_+~-_=xbb0QU=UMExONPT*n9a=ye%rvXmJPiTAHnY_=2 zzLxVdh8J@B$o_;w5!@aWLNGm_Ew27we;MtXikuKRy2b-BZ&o z=nclLcD8qC3@_rncJmAUzj5OFry;cfG8(S~J|etu+!8n{#Y=1I9*7!mZCXriCbACW zFV4N~e#Y=pSYa10^gl7b03XB)ucQEucnm&DH_0oN1bA6OZ6>lFc zl=~M49;E2b-OKaK@7>n;ivAP~Az{}9Hxv>Vv3;nN@U(|fGz&t7Eqd9L% zoN#_Ql9*Q_o{HzAgY~_dzDN)L9_hh4Db8;)uNCXNPd#6P`E1T_`&;mQ3EES?t@-WX z`I3%VPFmufD#H2g?Q!$l+fYxu0J#hD#Zb~8|NoYs-}Vv50^}KY?C0+M=BMP`a^>fg z=~vqOopwcXXu0bQT`lLeKa+Qyr`nyi_qxvJ55+#z9pxwZ&-^5wEA^ZD(f{FL&9bRU zF44B|nd*!>HuuGLRNR~;Tf`mN8t?NjwA){%|K<6t==l=hBf`se+%LcpFL8*M^!51L zo0{Z3Wd50o=U8p+qaNbr_ASjB!;5(&Lk;Zz(Emid03Q)veh0j0c_ze5x@S0)Wp8bY zUCL9F>-EVm&u#HChL?in{6hZ|@dA8AczGUp0giYvL%gJ4Kl8R&X5<;Fll93jGxFUT z!%KD1O8yq}3;j>T3-A%)We4yA9Py0kzof3mRsW@_liEyVxUYh+^?ZELe>oxVH#lDC zf2H~=sKXJ-4`#*^TQ2}7y6%w7vLkp3+qJSNW)9&4vg%- z*ntcCyH@kd`|^bb#|!;W#0&62ybvD(IN~w#OX?2H+gwXr zcnrMEO1o-mx1CQ2#yFpx-`wDMq5pb*;q_Oz3ZAdl#{W4^&F^tMpHgr<9C#`o{|}y* z)AUhKG!BmWfk+?wOTcZhJ~f}f`2)@;c%#@a1bQO<`bL;g7?P=%BeVpOfptH5avP3#eaWw?v{TOqlx=fB`L1)->-P%4{}$$@yEG~ z=e~RN;<=~G^H=^Tyan|Y{MPf6-a6?2=zpx?*tGrlsqC(&xZ;fu$(Wrv>SZiHd8_UA zf9SuSpNjXZ3-E&bA_*@cpN(I&T7NTbKYl*D`-KoM-5JBncs$I0WB-T#SHep$KaTv! z`EmX1_5DJQOV=|a|GXH-KhwZBlzZVAlK#X=5Amf` z{BzgGkA2zrXWGnv9Gy1v>gxFiekbJJpZJ#fhyGW}CjtN9 zzDUB0DSw!@FUE__{i+oID7*}33@_vHF#C=CL;ow`C0I|Dz(3>@N}=UpoqxzT+A zxB34#|BKHYGy1{@m&pnK`1fo|znTKan$mj4Gg3Y}|ACcv%J)57H|lKu2gyH2wLkEy ze~w*b5Y<2Mv$}kee!~!ZzS`~2IzuvMP5x-1!Sf0Iuar;J_y_NI-v9m&v7QqBP@>U# z|8rKlsc`l`{~UAwi@kBbQ|^OfNcs~eedJflZT~yZU4DJ@r1w8B`op#EMSr-?z540* zk6!)s<<<8;;dj#gZ`yw}ZO{1IejfIsKYUci?26H`jNSi*v+Rz4(Esw|`9!8eqPa12R*;$#8wr99?GC%auUj+}J!jr$@AFQ)uq+MWPV zcnSEY?DO^M@#19+FN}w& z6J_L|U2*l#S>PMWB{+tpKXFog8}q-A*PMTB{^h8Dy7%0e@80u+`I_q=_??tbO!>pK zJ>ze?{^{P+mod9yv^!(@L@c(;KlHy+e>NC@$9<867gPQ)ZC{KRoAnRz;%5vmjEAWt z|Iq(RcnRizkr(6Uf5|75Ld(NC|B!FUKZPG*{2g@={j<(Lt;(C)KZ*Ra6nsOu49Ad3 zXY>$X$_-nN%`d$E|4e%Qv-Le2^IPBZ!Tg3*gQFW(^;cj2!0)7dV#*(;?Rgz+*FRg| z$ZBK8eV823t zzwH;6?pL_9ORW%adj_QJ>08GJ33AE%3o>Sxw~u8kpA^>EtAA$57}0;e=leh{ZWGqQ z;{Hg&jVX_qwx=5kH;RXB<3>1k-Wx?bvm#agP`IK0)!;_)5%XjmACX@ug_f6fJ|h2+ zkG#h)AB4Jy@wCN93;NbztGjet{gRJj*TcRS{6jfC#Fv1iKXI}EKB9cvuh!@D-~6%M zW2y4{!=+#08;jx;*ZB7p&wew%;@Pj~_kZ~C(fuDjxcYhsekbJ>Q$8_m&v4itk6ZEV zy)tHpjy7j3uXx?|_-MKeF8!}Gz7o_!xG$3MV#*_??ThhZb3BfC@iK-N#=}&y9-{x1 z@S^yKc`=TE$S0IS%fmYVkZ;I8;&IFep)R6-7WwDob)6UVc2RMSGLe7w2j5U0fMdv{ z(}@Q$9|WoRXU{bcCh||{RFkBkq%&0a@8lo%k?EuEBl}d(Kkz##pP2H8X?sS&_IRAi zC+;Krj&^4(p9stRL;ov{uLS&q`yvT1ru<>rz8Ehy$K!|>KVx`dJWM6|hyGW>i{c;V z$2k5WpHK=d59|Cxz9Ih;FrY;i2T$0hIfzlzM+Qa(cyPeJ~8DF)Ao#iJ?fv{H=H>-oUwdT=&@V> z(Em#P*?@m=UnJqhls`<{7vsft{iE8%4x_H0D^$76G z8UvAkhIgGeI=t(g>gyl)os>^Z`NOn5<6jT{8Qyj7=vc<`iTHcF{6qgM<&%Jaa9yx(92WWTp{PCi2e_;2X*&977hVD*I~z@ugJ!bHpq)|5ADWC-AGuz%k7l z^3U5JS~L3ghgMe4Kkz##pP2H8X?wbBdp&|0PkH-8U8Btz%O{>i{+S_zOaH5xR}Odx z_eTQ$8_m&$!sGhej^`t&G{3qum+HE8f|5>mmAIsec>r5bld4 zyqNNcY5QWl*sO<$7e8ZoVLVJF>mmAI2``F&m>=W#hkQaQv^=cy5BY}tQ}{XNgHRXI zKl}V+_IzqA|GWi!L)naDNcs~eJ@5{tGxq9{YR2Q@^rim$H)em=`S|s1HIK)^@1%TU z${(if85i69 zl7HxbCA=v9VP1^mAM!~gwLGlz5BY}taB}gJVeg6DNJ} z59Mt?U6woZkt-6{!^P=K{r6jL$~m`uIrqY6zMFsHGxy8$SN1U{xEG% zZ>;mrEnko^`*waTWBJ5iVz>UG|CRDdfEU~sNq8~k57YL=c(KYqz>Am~<_VssQ6%|? z{#U|_;veS4IQ}7@Pzo&%>-rY*PmybC9tf41GRF}LlGO}YC%cz6E358hrq|G@90d}7KUrtKMj+x)Zb zj_YL1?#ef3ET4Fm`G@{j$|nK;;J!%0iz$DYwlBtuP5vQXyo}+6@i3L-ANpSjFTwl| z@?#wTkWVOumWOrzA>WXH#8a66K^;W@tn<%ov-h*a?hn@vzM*t+3`u|Dq-eqSA=UiP z%fUaK|EZaO;CE6!G35`__Kd%6{!!!kihsH@mQMWXH3cteq59%QLXPNZ$oPS=VRBmIX8Sa@7z$s_#6CA$|t7$VcMSY zx6MD!FBgtDH+(xkoUwc&Y|sC||4R8J;2+!2EL&@1ILg_C-f0t z$~P?j()?=HV<+jY_1`z|`o{c4FCN-n^LlLfos>^Z`NOn5<6(O}_U2uGoUhhnk7X>M z2;2L^!T)O3)doC-`y&ZAraWTWz8E)(hit9KCT_$YVZPvb8bvA|njxK~|JC3|@e%W6 zTs=g7p%hwP*7=D1Lq76;gZUuTMZ6xC`DkWK%R8vLCP_Yut%nwZe<&B>7&7T(1@IB2 z;-i26ia+V|LFA(cUVJqFz>9_I=Y!yPQeH9T6Vvv*4)x%p2VQ(Q-<+|$;#uY+`d>|6 z3HS*2M-pyK`NXt+F>Y-0k;09aG2Ad7rjmR_|Es}`;v?qCI6fl3Pzo(C>wHB1As>nV z!u$~GB>HKckB&22pB=kC;VkeEsLJ>zeikJSFz-pvo^yEB$oe9L@9|EtL>0UzQ1NWzUNpP05U#*IxrB5wSQ z;fC=rmE)A2DCX@e%ojQfPTu=OgkD`Ka(L=8I4#(a$HReSUxSd$3R1z{0*& zU8fB6ZRqDeS1r$8>TKwj)ls_D3UdDhF(ueT;iZ`OIp~InrQjDx{=5H<&`%!6$<~QRvyUp$&I|$bqxgln)TFPy<{GU9Vc0a`@R=)9i+QuuEH5V;(a3} z$Nam8{-_VR=)_IA+rB)fO=4?u^T5zAbI!<{T$y<#u7~9Le=X17B#+B~qC5cqnFqx3 z(0{#E5dZXPz&Ux{#n`iK&}i?nsZN_SMgC75tiRVK@|Ho%&-o*F+g!qW?@?PLY%QGQf((O&6PQGZMXRT3Ufd_TTFGH^x z71PS+Rh;&(Rw$lP`Gx*7zZ~@EE9ZUpJGptG<3sZzJ_0@>ysQ9TkY^aE5HH82?w1C5 z2@?!erj&KaFC(uXZEkS9(Er5z0(?Yxxd3XL@{4oWsMp|lq5sS;^0KJhf}f)N0(?YxSp~cRN4%UNUQ%~oit(~|WoPQw zu*fltI`ntjjvDQ5aJ7^uLsk9A`p*7x;+q(ha--N4!|TOS+fUN+m)6r35rJyv&qF1hNiz z8JROW+~9bj|A}}3J|evQJ@5h?@lpXVsXH*|p1m~Jx9;Mufx)KJ=Q!2B_m<}$mvz94 z^RCfCgX4w%7vtrbr=LD)LVf{0BD`?i5;)>@0$x&gV2bgQI!Oh_)B!JTCy$ObI9}*~ zF7=Ts ztv*K<;N=TjyavY${V!inJ5Dsd3w%U)83bOmJVU&s?ZAxBAEm>|cq`z=79Rz8d3sBC zgX4w%Ps}f2J_5s!hFW7GC` zgZU#WGm>?{%g`fvzrpcB|104|J$K0GVffr3pNruo+&Z58h7)fGjrF!+}`CcsOOdDJI)7k zPSd};y_fGyetrr5Gd~G0^k4TYoZn7cUCH&om#ysW>c|;90To(gecwwNH^-Th8_rmM z@=vf+53;_Z|B3ZD@DbtVG~6%15pfgZWmZ}`177AE<3-M#Iab$01b7)~FJufa1Jru=tV_i9ur6V} z!sytlOJ+AM>g!oI*mOqMK)=(urYm@Qem&2UEY<##>gP{!b;;(ZgL*^U4S6r*eWBzT z{8i=mRVbkD6SKnm^1^5CYQJXv9Ep|6`zn<9H6R@e9}2F)Gg?NuXU-YAO+NGeTGv@| zwLJd;605hw;x+0wz<=J?;tQpIQ+vn*>E21IbmUrEoPkznap&6p-mcWWRk>dd`SnoF|yf}a7 zdKtq@;at0Tq5p~f2H+#Y%a?%{EzgAcCH)1@$sM=`W+A^AbT;dfUq+U=-5JA+XF0#n z|HS+Pd_;H|23~+8-q*lOYC@VX@zQC46WURi{4#Wg>t_rv1{2!prTz3vfhWAitz0r1=sr zod!6e9d*es&WUazYk0BTf1&@0`33lh@bXpQ1vuh$0$x%Ntmax%LyaZ`vOfKn+3r}@ z@X~3wzf1oU^9%41;pHyi1vuix0$z^eajkN`CA`!nzYM+26~fLqWvy{Z`+d(cUg&>f zegQrrynG#a0gmWTh?msq#ld)!GeCtYD=JtnKhU*6<4XACd?QoH$u z{@*CaSmpnVKSM9c#kbLT9q)#rxP9LkeJuAecyL;*4Uh4aGnzkGjJ-lcLrFxY1q_#j?* zdI22q7%=oh&qC(HK+41H7HZwJWv?PqdJKJ-Q@%YUN$1pk?z1md8#GOe#dK1)3v5t%bp zzCXn7djozU=PRGc6*88egynTk^uLJD%I~`id=M|ZFakK@G5X7?3-XZ9%< z;$`T2xv`Al#XH|_f0_PQ;oRD1bh%L{E`5Uc+CEC+F1d6`2~2fm0tq9yqIflaJ#LMQUoAy_~kH61O_P|bED;E~>8`VkKs-(K3 zqcd$!d(`{vRDaaB^*%dC#%<(pT`yzze<9`g?aC@HvB#Ka!H*p|3W)o`Fj}4SK^SV zI1t-PI?f{xpD~X=p&JwbD{pCezrXa7lG;bz!qKPr-xZIj`h)cb>ksb_*oOk+;%scS z{+J!qAF1XR6YGxx>J7?&#qq;2^~Yx`*B}4=pOkr_Ac;Wd4 zaKvNN`oXk4?XX{eNW3@;U9Um#5?6oF|HS$OJX=fsp|0I4^B=F&CAf!QsY}8@)Hx2U zJ(R3}{lR*J^+#bRo(I4@2(GjH>Dn#>$SoPu3gT+MN~Wxz6U*^87c*;~yp0AMji67w9&b)(@ubX^;K- zL&dGr?ao-gz<+1DdMR%HgZ@`tf8ahLZiIHf@Oqin52o#DhyD8F*X_>8O4rXAZWxbR zWnBG1{}byE;DdPK`2}#qW7GPCh-lKXAH829|gPf>4- zK|Tw4+A}53AB(x6pZfVdJnt>$g#E#jZ*@oKUHV3M&V6r^&wvzU|G#-c4WR3=ay;~j z(QP;Mj5f0>=%fim)2cukLOEyShGBPsWaF&P;;{h z4W?kfCu`4t$hgV5Dz}iaet~#by81&8D4+kJ|FQLl{(cwWB*M)vao+$>JWq(5^iMd+ zhoqY1GhmB*E>AQ1Kr0+)FQ?53o@2MQPng2Z$R6%k#&9zp5wqVEZq)N1^uKtYu%=LT z={{k=M}(Irffp^`nC^Sf(zImv#f$UDoOq3$`_}C0O@3?Qh5jev1^9^Y@)Ym_9MOXi zFR8b!bXs@k{4(_GTyulth5jev1^9^Y@-*-Q9F^iF^|l8RFS~Poc_QaEI9}*~B3^)x z2rs_|UVx)gytJyVol<=kH!WV-*=yE!2~Ujvi>>DoRsTiqtJ2-zc%lEL<6+@ko?2HJ z)k(ldgcsI}z!AZLIw|#wW|r*EcyaE@`3;U2`k#mw;DdM}J_K;Y;}9>iQg6I;^199o zdb{4ediDCQLF!B+>rx*L-I5z_aJxO1>;V{i`W+Ok$x?)4^Qg+vdkIm z-(Z9kT4a0QN;!7bc7a=HaJge*unomAG$H+5~eh z6&cGq;Kf<)jx{)5=zk(!fR6|-ZQ=N~o@a=cwEKK5GsX!O)B!Ie?{URG4L<$?{}b^7 zd_;I@2VQ_9UM1os?K2#^b$%H-)opHYywLwdyZ|2&UR>Y>IMVTweguY^Or_<01cy}r zWxne*I9}*~B3^)x2rmnO7vP9jm-!{_9u>Cck7Q3h+^5vq_>07gbAsF5;CP|`iFg4% zBD{FO3vi_4CGCu(t@)$6;AN!6^&1>7^gj_Vz(<4^tmhEGk&c(N8)w^^KdK8}hML{s z2FDBiPs9uGLA($j0yyF^`6%s-qpkU)y5Oa)$t^TEUg&=%yr{__uKVJ9K76bLBTl$Z zj#6+w65}&d@kKTMr}VKs^%bCx=b;|TNFT<5bbV}3ePVW4_wqc{LmBBqeW&YVd+PI` zkLRHt%19sj|GGZ5r#>J0cpmDZjP!x;b$x74eFff`!8o`-rU zBm0mqbbV}3eGyKQ>_c8E)_0%U2M_Bmxen9Y6|PUDJ=AY&9cHkPcT@VOL8glEy)b`@ zTZefD`g2c1{u**Dl=R2{N_FprS#;v2+~ZsNb3g8WO~rMXrhd_`NDlonxA1ED4g%*W z`F#A{^4!19E&M?h?}dT?Gf#p}C^=A(g+2rp0KegTenoiHDrwtMT$ zUwc7M*SbMt#MB2bN9M$9vo)Suu#6Y_KaQ8u=P082Mc^aC%TvIMmS=#M)WdTN`qnr$ zrWftcN2~lYCD)uWyzo9Yl?n%Hy)OMvoR0=RBD|27fg{=jyrfl^UVNV}IYyc8DMOvkOZiLp~ zXLF9b@VHi)vR69cG*g{6yYDL-QtvCfA?IfdHxmMr@(<)C`k&a30X~Qqo>rh<1Y z!Jc(%YJY5%<0OBH8z*@d{r2O29lnq3c*sSeq(9kqwI+wo8J%{?bh!ro{=C!nFRnAPcy!u34v=%A%^j2X% zp0{pLZ{|Eh2;3LAzbGUziBjN`A(w4L% zYxdSL;eE^2_(I}Et&_|cUVO`Vq5p|^0X`zUYzJPnJVU&sU1uQki=|H;@S@g9?whf3 zHOqLR|A}}3J|evQ4tN2Mc#(;hv;(obb$(InBr}E=agrT;vworfiFg4%BD_2gyZ}d~ zcsU{UI0^Nb%aL%N$0i@Cb&?swi+LPF4a5umPs9uG5#ePA@B$pst}wsMNn7qZHrGi8 z`)t_6i&`g{F}!$|^9%jg@X|ivxgg*p!plzJ1vt|1lD4}m@nYvWc(snnI$qQ|$&BH} zw~QD1pNJRWBf`rIzzc9xikIWkc3-URvr!kksCAMV!%M+3Ug*Dumx<3E0v{1xb^$NI zk%pJl<1aSXNm|b@YMo@p@FM2f?eEh6M7#hW5nf&dUVx)gyu2fI|HWBn>9J;~4*gwc zhC7xqyzsi1O7?f@evA<45j@OO6&K0k- zbH6fPS&_sG{V!gpqI~$Xd z<$>IAgX4w%m-11WeV>4j2rv5pFThbLUS_ARrxjjy-~P+(xk7{Eh5nb~rA+??_=xbb zFYp2!X?QWpFS~93#d#z**5G)d|HXV%w*LZrM0lAFyZ}d~czH+a{)>F0VCvjN8$wx! z@w%bU=ES4nIA!U%{`!xi@fY}CnqSKB5%3Y=Wq;rWIAX-Y{_e4<@uK$G*lqi}&NaE_ z2FDBiFU~Kx_NDKE06rqT900rkM;cyI^O3^KZrk5=Hsrhp#|!;W%rC%4gqH(>7vQKA zFUO_k6or@Fx4*k2*WKWFq5q|Lxnkn_7vLkp%M9QJI4Z@|yZ}d~csVxp_^w*du>1C3_RkGBI9}*~F<#WQpD{yZ}d~csb6XKH8nf>o&KKH8@`Ae<@zd zjMo7l5nh^r7vQKAFUK16cbDwO{g)Hl#lJQ9_zV0m=A*Lx7vLkp%aOnfa8!zy6H@0F z>M@sf7_W0y%x`XRywLyB{8EOGfR6|-M*%Ou5wCAJUiXgF{oR(PTyN*ve&fd+>$0A~ zx&FIegX4w%7v~pV`;zw(0Ur@w-U7S;M{EPUq#myWUe2Yyw6Z>US+u3Q!SO=>6Y&Ck zM0jZiUVtNBSKuXeebmx)X3xMt-+*a?sSjRm-QqVmUg&=!UVx7XFK-22fTL2p9G|+s zOT3sSnEK#l+m_)5#|!;W#0&5d;pG_M1vo0j%L%FRLOtfP9{t^e@`VP+3;j>*?*bnY zUSz!9%+$VbPgu8&%G>;CTX`LPDa3;j>bFTh8Hmlog!IMVQvx;_G4OzFs}4Cp4;SK9)Q@l8Jd4Bq)e0PK6h5je@ zcYzP$h4>J_5s$8x25-(zI$VcHf$N!7{lvDS2TRP5O+LHDqLnzU^_ri=J}?P9of#h<*(4#P-~WyCr4MH^5DLQllC5 z!OiAjx6t6Yq5pBXneaR{a1!C>B;ZENI}vV`;JBgxak!b#zX47n z+$;cYfF~U{Y5OP&H)-3_1|{oKPdS_1?gqyV{jVA~z)6G~54ZuIc+Hq^S`G4z!5|^c zs1I(Q{HW_UIBw{F)wlspBHWw?+yGC!U=eOo&Tx;9_fcayxfjN7#5eTun^WazVv0{N zeshgG+`za|@57=0#p8X5X6f_Sz(<6aGk_Q1h*u!OOUf6Vv^1U3HPGL*nEKMoaJ)}g z+fQDO_iet~Ei^b@=zrpT0`L*xWg+ka9PzqFcu6@z47@C%zVxyVcp3VDJJ#TMq5p|^ z0X`zUECODDBVN}CFURpOwaM1qIlqj&-xZHH?l_I&Bl@3+7vO_>YtlQB z<9lOy9_pct^dW!i`q-ZOc;E6o)I%BR15Xs|Q}6fX`+WI+-@;3!_bc^pZn|lI_50%P z&Q)ClYSn;zQ}3y3JJ)pa8`VkKsszpwHuPDi@G&&|uVVDp`} zujZVQQF-pS$>ZtsbzNg0{@sPj{%G7Ce(U`KytMy8@fN| zWvo9?cxSrzRSaDnUVp|@;Xuvv(f_z{u<-js^CH~fJ|S*|cE3=6uCKSxWWkzgd)hJ8 zai_lYx~Yyhczb~V@pVjT&oC_St?%TzGlm<+qgL7EPsEL?JLvyr$qn-V6Fw1MfDht@ zUlhO*kLUOHcX#q2g*0tHeoElQ);O4>@N##~ZxFnU#NdVgSE@UlX|kUIo-M@SYWzA4 z&2t?7NDNNh1OKG{rhn4@jrzyivtLwthVg$Nw`oFKWfy*e@6*m#{vHPNl{jQ74yE{h zqUsOU8>~P4DKCco@)yH8gsq>P_Ia)T zIAx%3LqGqyYMHxiWp9@(KvE8~J5$9JXR2hzKg87^%TRB;Wk={oGvr%CNkjerJ2JOi z-QlC&EI>Z~@B6v_|M`~e|5vU*=$Ex3WMsLk=6M`v-<;F7kLwJ**L6ldB#+B~qJ9DV zXTLx!FRi=S8qZJgux8oR)HJ{5Mr9gIJH!|!pr%%e}E(E5Al-ru63NZH#N0Wmx-(kUYvV!g$Bn9{ZGUT@DbtVy}*l>XF|NB zoa~SQd25qQxfVWk!OPGsxv>Vv3;j>T3-A%)r3rit9Ptu|cuBb^Oe%R>EHm;9)yb(C z53@F|q4>zzloLP6)_khCu(ZEaUGye?i+n`?6Y&CkM0hz8cma-h2J~N2t_E`))qiQ~ zq&5>d;#hq@chG$+_+Z#|!;W#0&62ybvD( zIN~w#OX?2H+gwXnnkRz!1|Cz2lsls7)pAUr@_YjP8thuPzGwAi)Mg-ueks>6y-DWg z1LZuznezOUVa&|+g}bi{CL-EaJlU!^2Z z5l?#mmi<}wZ*@I9w$;B~ys~Ru*P?;G{;q++p04#&U$xxB3D?WK6w|-e6^S|M-!3Ta zKZsj?U$%d%w|AV!@^W3K{Hff(o!D-2{}SaB_{)4Ejw|(>Rw19H?r<#VTXXWd&I@{L zd|ZR4kEHee2cWsT!Sf0IPuzb1_=xawJnk3Zh!=|d!{b_|#EX?7KDkcc?)V-Y@f#d3 z^uK(6rD%N>@Dbr-DFov^Ww%f6=t8*aN+tXhw)=Ix`dH(?@A8v5G(0{GJ zBG>I+DOc`Zd1b^$z(<6a6M+}th}Q~uNj-m{@Up-LT$o>MjR(WQLWARl{wLxE_=xaw z67T{XX?RJw8;;|&_jaw551w|M(z&*)WAVz)^c|V{cK}Tcf)ZUi5E#n z)Rtb>3op$Lju-l$h!@}^!ix*M07tyCz)R}!++ZIB3l&nm>Lahg@k0L->m%SJ!VAWo z1aPF`MGfht`pjQ@K~LAZL1V03vwwaaLK;{Eh}62cuk(w@R^V7#dPHRwP0*EmqSG{tqbN*W&4VQ?P6$1$6E z-wvO5Exch@_}pmQw}R(G#f{-{@jQUi$M)1$fIgl_yf$p-9|V0LfgCBXkL{^XoPd3! zpx6IaXdm^8V_=_OULV_2p9g(B57*=PuZCTGPIjogKDMVmANqKn!U*EGFZAt#eH+W` zV|(f=K%Ym6>)~&M-@G0RwglH@FI+g)pH-KOCNicqzOJda(XW?AmvMdX8H6m+h&~gFc>zdU##Li=iIz*3dp(AKO!(4}Clj z_uKM6hUQ)SyuK6Shj!E_P6Yn&cmD{q$8+^! zD~_>Wl&+8Msn3Hx+DShPv~yYLr+6yVtLtNX>hqzG=PBGD`WfM`8TdOb#GkH@?WwN- zeID&Z9`Fu^pVvZ;hEl)2Y)^gSU5Fp`LJ#c}4@2Ku%HxIYsn3Hxo=5yw=x<>suJ6+D zeB!6&uP@tEpAUUJ5A_g-;#ur(hW#5S#1HMMuYhBoXM(tlQB^PrFCnP6XAs7GusuaE7i&xbyqXM#Q#`kpVZkL{_i0DT_q)csum zeLKqQV|(fo^ANu{eIE4fEU%C4sn3Hxo@au;r$OHf<@K>W_4&}p^LY0H$G1WrhWmHl zdxQL^^+Jy~41Lo>J!0?j`q-ZO#GMe2lj%$*N4ZtKDMVmANqJ60X^Pppzj9A50=-*_S9E^K93T5qWt$^==<05`q-ZO z#Cs4w>ce&LUqJl!!S#5mJYLwI`aJ04dHm_29g%$>hkb=m>iL=Nsn3T#o=5D3_K(26 z7r^IBA1KeiXit3w9P>Q>4?{h)Q!EPgi0jJR$M)1G&O-cXC+wnLu?+h54W*73wx>Q1 z`gk7iG5ATp4*-Ac4E@&iu|4(q(8u$5`-gr-*W*)&=l9F|%l6b)fIg3Q{vfoEdc{8Q zcT;(NY)^e+G2%zP4~6;)&?}Ze-`=6r@xu1h=RqIO<4uFV&?|NTFK3n4$M)3cLm$uM zKMH@LS4_wCcs|st+sF3QSAaf`dU0K&yh=PzFQ2d2p8CWR#1H!XUm|{A52a{>eInGS z+sF3Q=RqIOQ}}tP$G;o;j)A^?%Ijl$>hqzG=kcC|KG-Q-=$jcz-9EObz5?`l)caJZ zk9Gz4W+gf!g<-#5 z98n(6Y)^e2^zl6Yn{ogC0s6+mWAUS~U#a7T?Wxa)KAy)rI&AO%9{RRHU!lA{wx_-V z^m+9A7})n5^zDScyUOchd+HPCAb!-#eXKtLeb_%;ED!50{ra-~|7Y)Q;OnT${PAfi zIE$#IycG%(5h03VTMDbFkmg=+c&n8btiYP4P1;1#B&2D16(S&vPyw|)00{fZr`dFU&9Oz>`#EHZ6`>zew`aI}!s2B4Fp}r@eZ)16VEKhwluE$_KT{rv^|0NB^E!K?-8~W5ISzj)PkkZP5Fx^7>ew`aI}!XeaC#q#=Cp88zqqn+NzVHfAK zr{Vaa;Jn1!8_QFl2Yn9hybI-N-<}w+9$(%*mZv`ZpAf$!eS1TnQ(hm-Q=bEUtjE14 zX5W6$cVc;cEKhwd^s%0C`u2yulgsO4dFu0^&!OH~0nR+e@loJ!MxZx-K3Jam?2jOR z^n3rHd}!z6&^NQZK9;9G2l`l#^NCpecEjjptLA zr#=t*97^`r*1;}5|9HRh`dFU&>=wi?rq8_!`uH5~z02!kdFpeZkM%gP%forG_lMrc zg7Xshm*uI?g+A63+6CO$GokM%<@K>V^?A_eP%ql8dl~dR6P#Cjm-7CyJoVX25x&F!ANsypULVU-p9g&o?fgQ_zCYa`j2FHh=!@qUmZv^@8R7?h?j3T{uw z^>~|N{!YXB{cT`h94{mmN^n_(ZHo4gdn@$u zxvS3y?Kti)%Tu4-j`+p&Ik!O{pUe4Dd3`KTeGc@o9_k5kvmN--AL|MI zWS)Kz`d%(?AInpp2Yn9p;=FpugZ4J)d#=1bmZv^@1>#4&IIk{v$vzqR<@oaFm*uI? zfj-vbZVAqV_YBU*RICSd1@n{f_Qvwm=RzOrafSjt)NAhoeO4gjcwu?!^Ptb6-tPzc zsMofkZ(4bMEKhy*O2m(T{{;4N{p~F1dn#Cei~Gy+)aO7S>v8`x(C7Uokah#+cTX%o zzsvH}=RzOrp&s{X=sOwu7L?b=^3>-+pF_W)$N3%fErh;P%j;u#>a#l#Kk9`Z4{@{? zL*E(Y&j-s>p96iYhu7hU>u~de`s^9y?PGcBbD@v*P#@QkcpbR?k@EJjJoS0d=TPFl zSK<26F|coDdA?+M>a#l$za)K4(6?WCeJoFX4)n1e`WxE!Ug+DqygrtvJ{S5}&p3VW zg1#B$^|3tldC=!j#^ZN1^zB(*AInpp{n6m}tcUh-ore3%?Y+z6h2^Qwfj-tlecped zeH3Bee&zMCJoUNI$9kxbdBHv&`rcSxAInpp2Yn9h#5!ZRUtrfDZuZIL_Y1H*_3{4S ztcUB2p}yBc--7b`Sf2WLKTg)ed1CG>zZboq>a|9$zrY&#!hkh$%g3#en=i3OZcxY9uC_)#xyl;3s@od*%o=NC!-dw! zO&6>8$E=YXFAC)6)$xt$_;cr3BckWh71qf4AF)RI&#*?;$ooudWbIkj$a(){jeKmG z`uj?2iF#1K%dkvc8Gqd^Hb+2JNlG;=LdGtKKZ-YDBnxn^4oQ) ze$g%UT+kA{FI=kXQE&O~$A?9`Wa9RloR1z3a~njyGOr zjokhTYeb~{UA~tXiQiYN7`aNX_;pE}s!#bQb^GdrN`*YR#5h=EbPN`4g>&IA~b2*m!B=+LFNWsgxo0U_|T_tO*uwQ1wdvf;ou^ZIC$JsBHO+`i;a}bV)tEr&}Yd7F#3T z>Mfto`A{Hx)aSk>qZm9_*&%g_%@Q;5S$-?OIbUH$&I9qbLDety$~h1leEh4r<-1R- zI0=r#2f>=?6+fhIsZ-wFrv*~%li!G~B6&^*)Hx6xzOBjzu}jViu_*OPUG!h#;kP#> zB}Rfdv0vVTd$EOf(0{Q>>Lm8%cY*<_TQDg25&QfYsdFaZU#-roU|Z^^4I){;U_oq> zIEk$ynJeTRihrV0-eQl$S=u;%C%E~fs#ofk?-@VAhhS6wF6US35S-C}u|evVw|tfu z$a(mzvQ<8dEtjEP%lRel<(x_zmEXwwI<{F=kCc(vh>a2#IUka9M6cK&zhAG;e;fm} zLB5y2e_G`q!LHx_)p?M%B{~^n(J5_9Vj%Gq|K%;8<($Yllvs$Jew@_ru2FBXRcwgI zKyswK#SXDSa);=VIt2%UBk@~wijT}uQjh$Nzma44otz8SE%iznu}y3d{ZbEey?p+H z$^o}t7T6%R$!{fo(yrw#c8EP!!6(rt?Nz>)^CDQ6^DcOk_)Fa7y!+TtW#m}mBQcZq ze(R;dTWpZ}B@f7Vl8dB`MCa+A|eSl^uQ@RQ-PZ)!+U2 zsAKt^*dV+jalZYEAot5>wgs_4-crAuUx}mOpY2@y6CCh72tLFf|2Ip6I7!T;PO(ki z@>|K{@|NF9{o>=7Tx(>LdW+9~URHIAlvqgpf)nwRHu!By#aMi#E~#IBBYLG?X)8SM zV!y=5_h0!g=SeU*7VW?Lcgh zI>iRjFLjEKV!vQm@FL&K-{p7m{mrWWFJEPi+<8qPB?eNr;8NPY)Ghdu^CkYvc^4j( z7|2`jDCbjj%5Ox!{O)pfEcJ;VY3ouK;~?M5TktP2miT|=Q$ZXg9#XI0PJk=FUKKO{ z+^PB~1z!?NsbAtEZ#nk=uKp(F{Q4yZ$`7$2v_r*8{F3+z_lpf8<$TNc;)ldl{EcEx zJ`2X8b;@U{Q~u_+KZSp31JYI`?xIiHztk<~L;M#1rOnD`!J7CjQjR5-)OVqZvE+Pt zOAeRsr9QDu-tt+_fz&IU(EFi)tA($HpXBfI7M)^;#6fJ5b0xV!zLz@v+^zm5xR4kU z~vri4`?^Jb*9bJn8yU5dGGwYGha(<*9$s_DL zOZ|c)sZaWDVuSofz9XlExd8Qx{vK7o^p8Z!Igmbre3r8E7GM4P1^Wtn5(|m5)FV>- zk#i#ciIm@pUH;#3{-l1XJN&z{DmKdZl5<4L@5Dy-Z~b=R5%jO6@_9b%817x7nYk+M=w@}bx-Sd)ApoGx~d z7o}ZDzewJKMLCxID8HAsB7R6Lq(0HjHZJE->N!X1SN{6-t9XhHlAk4>;`bHGe(_20 z&w4~Z+oa?PY5UB(A|*G-Z$yXGC;H?qb&7s@`~EAx*)Nv3(>6H|a=!ex(joQJe~E#7 z7XKvrJ|qvzvGn~U_EL}FQFQt_NYyR%$g#xU@1HBY$+?ifORU6JY4eP;@PVHL zkO#?0a*pKOi@#F0-xpE2Na7^Fk^DhS`B+xE1)Dtgf^%tWg8yj!Qbv4~^C@u@Uqzo_ zOx}V&(JgID@`Ch7L*7^MXY84eB(|bc`WPbp^RC*N_`XWjFKs}+7u)3R*ROn)KBRDp z*y8ttlpP}dHmK?sdI7W+;+y|ue@RkU>W&u(|1zY+CN6X#cXO#AqI+7~Y;_MOK<6DVmP?V)`% zfp&|1=kv=6l(diMllIx?1o7v27yJ6vGf+&K*3ld2r=(uyFCNoA{*LzX@07lMon7rM ztC#onbanCTx=Y%}c+tK=#E)?m`+9ohzCc}_tJR%eaI5XQpK{tqdqVr}3i2lH7W)(< zwybLHHxe_aFF3z8>Y>ti@&hF8@N-rLu%((?j!XUOQcwS8_pC)kITRO&VA z5AxOjAHULa}jKkx%2?c?u5 z`})V0lb?5MMK-ALT`BRE*hSm8*f&jm7cJ-iz3HugqwS5bm9~30rcd(w`9bw{`8R5B zv;x{kduU(Bnjp5cTgo>_3mX0`_$>FLeYA)6*=qy)Xt&s>9wt+_S6cjN5A7R-eY9K3 zCq6*RfYoXC(H`38oEyZCc1!vBEv;R>9jyke8LuLmkD`C&`K3LyZy5H`Zn3X<2iiw_ zXdiPH?H2nAJJ3GbL;DzG+Aa1K>u8^FL%A2vFS&&FbzBnQkDL?bmdrPHj~L*AyS$5o zdibX#ZsG4k`z{z;PRg6$7AGUOM9ay!w3hvw&DeIpR@!b~7}!pq`N? zv|H@kk=#OiXkR080`2zkSI69#7C+iU`(JyEEAKDYwOZ#XK?Hh)Dv|HMqvM*k|=41PX-&EY|7gtF8Xb_U<+D@}`c{;zxUE-(Y)SAMKX5v&fV&N>Af*;0N_kwTz#mFUF6*r+psE^S6Hd zT34UVW79He6@m8A9@^K@7WhZI#lF=Yoh$0oI+DGmeYA)6*@!#smbvJzo^z8G)#)#^ zkM__$R!6(Vz7BPNX?|~BzBs>}PTI%zK>NIo;QX@PNc&h^PC>@+oE5+i>Yfb?d+(&HSM8&jjICtXgAJ%G}IIFnen4Nw9kWmv|H>m*>|nhIod~iXkP~~ zO}oWDlYNI;?V~-kkL78%e|~plZbYu3eS z&*=@?2XiFt>yqcA)L}PHntil~@f(JHj3e!9?_L{sv98B#AGC+|x#uAN!A{zzo&??9 zR#%J0DyMz4hxRr0A^*kfJG;F;TOiWTFYTdy9_*vtjNjR_TQWbJaBO789;MkwduU(B z>L7l!oAz-}!C3A3M``xa9@=O32lml!DZgfQdrMpUiqKLMn9tE0zU?hz2Uys`g>Ak&noi)?WP~Y@Pqz|A1asXx?v4x^dnlX()pm> z^ut{noDcdZeyE(*vRpj`u01=fEPHEky?cQ6@&6{_Dq0SH$hp9K^nB26`q6l9;0OJq zAFFj9!K*56Oz}h3@1kpXf|uQ5<>Kdqn4-<}!GjO)+19T!3Fc(&)si-c>K4c z{YctF`vzej?e^_6u_>aQ5$e1D@9ST$XdmsNea;0z{Ajmt-w_GQ4SfCIzxqhU^GkbZ z-!SZ>-M)SE3>cE2;_0WJ!ZinDe?a`v9@^(#7{rfu`}WnPhZflLmBGe}_R${N*LYE2 zAMF0*SdVHn{_*4{AdsD^I#wC9%J9CPK_r}*5(TBqdl~*<6}YmXt(6> zF@4C4J%o;w9G=9d(Q-i!A5iUS^i4l#H~p|L4*Z~h;zw)nY}lYLoY4Qi| zIP)03qy046O+NQL&?ekzC?H*%a z=BL!hYfnFB`=C9vujA4nezbdxeVLz%o^DV47qpM|&_4UJz&_e7d2&V1%8c1@wAR6l zc`{lq-e(_^Ct)}J7{oFC+gTMBKYDvscj`RZ`Mi|16X9=p^CfYX>j9$W#E<_{gREio z=6RsKwBNZrI1fA@Qby*7l@C-sA(Hmd9@;ky`)Ie=C-X}yyLy(jc9}O*^p|_lKH5Y3 z+%E?4qunz9Z}NIl_Y;Bs;oAdA+h+3vB<9aU$;ZXkM_{MLD)yTBlaz8U2cAR zT3Y;Q5AAb48N`ov2lmx3Gp5-`duZPAMK%i?o~njXm?}*-t zUXKB1ntil~_BCD|*hjm^*r!H1-R-R!Gr6O2OZ&w3L3?PQ2m5GuV4t5~T2`-8R~73_ zZk91BEq=6z_I0ca;zzp!`<8cg_VyZF@hM|y>?_8P_Rv22Q-OW7JFst6+v*kl!Or`Z zw$A0jPsc9A~q{L&uU=UyAck9NoHYgy6RWs-!`?4v!jukpIT zKH43(uWOA->*8m1^qBagJ+#k*eYAU=eLZcXO6vHD_R${N*YW8fezZGoUt4>BYv%;q zl7jZp9@=MrCa{lo$L;HF?_1q#Fm9s1+>7?n9@;ku`)GI6zUAjH?`rQqzt?0>I?X=X zL;IZ12JxfaW9*aN1BNqnntil~_6@^6+8wp8x3jlhdNAeAN7nDs?4v!j&s`tHk9J4x z^RJp$vpuVNTl@0O)ZsiRP(E}^GkbZU&r-9{Ajn7m${=pwe_sMZ&i=!VQ`v#w1@WDHw5<4ZYe)% zTT5%(+Scyn?QJdX-K}a%Q2n@s=a=@-zCqYWyJPkRx4micGhvH~B^Q|=Ecc>)w1@UN z8-n=J?n?HVSaL}_zqE(;4Z}X#E#+HV)#)tfWF5a_{AdsDb8igdN4v$o3tE=1>aC+K z#OeS@%%cKi4LHlSA z?d#YW#E*85+P7+l#EN>_RzjT*hjlZ?Q7j3@uNMo&%v4_?T*;D zL*hq!Xdl-^Y4@mo%XUcoXbU3>^qSEu*NQH*KK{R=eBgUo^N7S zym3>YzvD}RWIUq#zU4dS7yh31c_`0vB2BDaZ^*cI9W5v4(%Sax(01BN+vziXlHadh zb<{j5R*#o&PZ`CGE$yLw{3-30@@hqiUr(5%eZ(T|8w56qS=k>XD~Gz*B@CvVdznLz z&ZCQcGH#BRlUQB5<JFi*dvZ3Xwqo~=IVznm|l?Ltyx)OPuf_VM?$ zZ#Y&??9;#F53Q(P(mvWl`>26-i+%OEVvseJm$Z-PllFDo8N{FGef0dAp`OOC1o}Nl zT9mzC3;9UV;X`gd9+6V53F6Y;u$*jXQ-IY9}eYA)6d0&Nn zuv_d?{C7&Lx_Ym(ReyLo4F4%K7C#pBDPffTCjML>{sqx}Ht?gZh5peWw=QcS-UOhRQG z3F01C=3cR)Th5c5=~LTPqU_IrNTn2I51&0Z+r?s2Rg`v7@4vla)WY9A|0tRLhueSzfccgMxb3|JAnhx>DQDmzQQda=_4x zNA?{`t5NW@P0lC$z5(YmsoV+Oy;{2nb<5MPsp@X;Q`CRo+((v+uHT_zE(Jjwd z2wq0sFx5C-hI57&#zR*UFZ90>USt5tym(VtT#fPxd4>7N2F`@5n#w;XgKsDo;24trBuN+iL%C+lk)=7uK0M+4v-N}PN?Sj8d8z$t z(}&u>wp;c51HaSqi7tQWmS_BTA^&`{E$rU}{Bwf35U=)im#rUkRm@&LWdB#?`$e(- zSBkWEH_Jct|K{;|Vqj!s@Kwbp9$r^GeA{s0@NL^t=Z3?40>9JpN#`qM{G)n8!T9H{ zIR6~q)sx}buTMODwTjuZ1t(|u#M?KR-$}z~+TWQ^=>HdD{G+Hx=x3CF&@R&O((?)# z{|H`u{xOV~j-25o4F}c!op_=DmGC0`!@QWpKjafiJC=vz{6oGW|Jb_){KN9}!#MxU zem7OuBvbjPAACc(7RQijmD#KCd&q_(n~LvR@RbSYpRI>pTikl+r;CgK{FlO=FR4bC z@(TF}ey8OVpMMUYJv-Yd)Ur&Ce@xH6Z9Vil6|=t;+??eTd!||bq5qZUQ~dciw2L&n z1pJd7Fs8;orsv;?m%*IjB_$nH{b%wI{jY=<;UDJ5B>o|vP};FP9OobM4f)4=UBEvq zPe+XN&zx*GyCeU+m^A)55Bx!S0gfT*Pm*-NJCx^r@1)|oqZ=lC{%yaINK zK6GB`u@7~q`YXRe{(;|V`9zmLbjy!=V|M(r-{Tup%z8^+&hm+KpjrN*|CRc)KL4Oy zq~S%EKXl7S@nUlPL%a;<3@@Yc(ECLGq5qZe;;;W8KPK@H`6QIFJRIjA@(uaNeFN5i zFb<-3#`$M^(g7HrVgHYs^%0I+QW6toB{Y;E4NxabiN_g?te^U5| zd_rl*@^GAg$T#F4XLqdsU>rni&GS#TnIH1c|0eOz0QiRTQXE6lpCsuazLd}Y>q*6h z#~j=|(d$2Rw%$;jv-QT}dH-~J^FxPUt?IA*3dcY2J1w91{F8k;sHfQSw6|=R? zPR{a)V|f0J{#Tk$@%absA`LGA|6~V@DgH4%|3N_g?te^U5| zd_rl*@^GAg$T#F4dk?JtU>rnGjPuVNz4f1$lKAIx@D1e^IEJJ@Nz(4d?;)*+jw{Z4 z?XKzLpCpA@zdz-(MeCH$6@N1QL#3Zge}DDkANZY?PjtsGy5$)b)BE47Q`W1PeW2v# zET6d3&F+7r|CRPL`TT=+k%kvt{?IKS#f!=PZ^X-B&hWx`=t}Yr{jY=rpMO!3eA{pZ6R-?K8?T&&FCb>xFBIvtGEac^(booQKd=xJ}{}{SnjCdK& z8D1Cu!kp1&~t^e4D_aD&zO7r#m^A(&pHSMdJRIjA@(uaNnThoujDzT%DgG&NoxVWL zwMp_%;{Jn2zZ=}2gYq#PL#EZ{A-?_9zs$?eYF%!@%#G zr*GalHClorKcB$ww0zPj*Z*Xn&VR+O|7_diI2E(MHaj`XC%nH)90#=?GoR4^O8r?M zFK8EOc@dI%=*>PPM1_Ye0WU;-9VHn_odbIaabZd(9K$?jtCF za}Zz3gV&!{9QgUYn=NZMH3pfu`@dNY8;jP`2i0|_m&w}CcP;DoqBZb9;&rIu_y_(o zpV&VO{1@M%FP}eJvh9HvJw_I}l%A>9kY)1zZ+_gY*Ok1S0kf22QqtO_^Y zk^8>^A0b|Tf%XC%$+?zSfR}80hNQfyg;CS%g#lg;FAe7mFOK2$Li!)Ui<~yRB6tBl zLcB1~#_~*nmpPfAr=#$4od5VwnvhZM!u(S9eoYyaN?x`;P_loKv-y3)`y$UOl25il=Dzf8@?h5HfaWlMdWkNa!Vc<9&Y&rv>wV@UdwBwfUp za^R~?rOV!OvKk9b?0$qNFI``H^3rvsgZBSi;h_EHesq;zA^*Vdw0z?8Pi2)A|EgP_ z%BQGX4as=OeK>wUxYOI0_t$?be1PQ~oTLPyT>iStHt`>|)L;L`tFRp*5L6vkZS zxckDPeWc+=cV11mJbe({$i4*AxN&oa8^%LdO8yYs(En<1BYea>nKVB~exbBuc{$EU zIK&5jS4WaKm`$O7ao?uLd{5N6eE+d_;bsv}1WW&PU`Q@{#=}>{q}z ziGCXAqd9u_OGq3aJp=xsd=|%$^e0K$+wgnH?-d(MJC%eFCU$(Z{)kIUjVt?0&5zw* zXnyS5)$|f?<9Uv)>)%rd8i2hfD8{s47%OpM`zfjt-yd38v@(=mQI|%z1FixUh#`)+7 z@uv0{$44(D&DZ?_d_rk$3HEbCrq$?xhbT8)>J~~n|9ryv==qXYc)s*#;ndYCa+&5UYwlah4Ijpk~ah|^uH2bBx5r#Ch-sXB$Tl{9OobM4f)4C80$qC z7tufS{F80zGnId)f^R6N;TV$sBuN+iL;0mUE-2h;KRV(3vwizF3){DUr*Q5r`xVdK z<&D+z5ByHcC%XKhTYfbDX7?*>-~KNuX8RXAa+XgV!~8@4Q}-*NU8Lbfmp^pNNAY6v z`c>k^%^6-s*6U^2#T-{9^Bx;xG1IUOoT7 z@3ef<`FA=W_vDq^RLok7gE`A5w!!_|GZnb$e>L+e{(KzTM;dN={!ZuPh#N0wxJk-m zwSLd}IQm}=ZiJ7RCzJSy{6cBR@^YMy$Uo#GyAkU{7#Gnm<9sx?PJFa0_=j>g97EEd zBx(N<^Ldb`b^Kt<;Nh>Ga6W3f=73VuHLoje|K5V)_V1lqJs-jEw7jA_p3yDO_?uoI zYPx1G6|;rK;hg0acW-m^al%LRznZ+_^AXxd8g6vQHM-@axG}k3fw-}MHObe9;D0r^ z5k6wROyVQ*3#A>)%W*y;|B#Qow_<$=<0PJc^L(T?KbJT@dOi4uaypJ7=}(e$z(bUK z-Tc2>u0CIF9-ZLv(e(S@Q<{GNVWoxNIHtJp8_m`85&TZeE4qB5Tb}VZ%}3MkKSIT< zso0payy6+=Bl=%WUh(+|?IR60x_qKrK8hQYd_>$hIl~R(p({B)qW{(4M)-(%GKr7K zFQJU(ks-L%Ao8A=4^z!AF#`Ui82r zvR`0g=j*s$wCB<17WX{*!s_`5ey8OXT|Ut*KYAX_uNUok^!de(oaGhI;Ql#Tf2RMH z=Kp;jLc2)Ai!P7omXG4a^m>ut#myOBM&qIPDO@jt|CR6}{KLGM#6RQ{N;{T^&oICh-sXgwl@X;W+=0Z^%FPJFz~5 zaS;78&OdX-o7!I-|0K@G?FYW0+#kn~X*Jr!pMTIU((t0oAG+lU0KtpTKV|P9mK`tle^1_ZAsH{z|4Mj~jLrO*#6RQ{N;{T^ zxzF&LY z=YLRG_xYa|mhAtSdjG8Y>sR4-T0YU`58d*Nzv=PMy3hYe#p{VeW6tu4bD+8X3I6p$ z@V`=j*5@Czi!{9G@`rBuC|*pCe~1?+XLw;ebS1|>^uH2bBx5r#Ch-sXB$Tl{9OobM z4f)5Ni}fFjgXo`m{;AXa+g$JsHSImPqm z#p`>8!JOq2+wk~@{#RO0_QyYH7ioCW*`4MCn5t!Hw4BLC3;N_g?te~=fG_=kK#X~*(# zoPWqShQ}4&qBG`wu$L z8*HBF{ny-oaLawqHhhQ}9{7mzKh*OadOH?Q`1L>=)$<&h)bkt` zFZg_M@q#Z@e?1WVPRlF0e4<;P@i)y!P3n0Lix=En9L!l>u?^oJf&N#MSA0G~`$)r$ zE}!U@kK)E89}zcR&Tzwc=t}Yt{jUZ$!bi-LNqj_pp|oRpInGDqAM%m?KCBO6oJ2p3 z^U*xL=L;qB(MQ2QlwCN6q(4d0{u9=RAm#b1|MRO8C!CM?{MEUK-cX!-=#AC$5&TZe zE4qB5Tb}VZ%}4V5)wzdmC=TZ=uXqOM=cJ!Y|EtL>J|Cfdq~S)FPjt&iabuE?h#UJ& zlXsm+a6|vA!Hw_{^JNkrkzXk7SYD3v5&4IF}5zY^ttFa=j>#kGjD> zl)X5HOsmWR4^cL#=dT{wf82!g(GvCi)g|irtBw17w%EAO=c?x;_??zlbooTLJkNt^ zK3bxlzuLIZ`eI|w@``JikLZ6jdBx`=w2w60=<qm)v)Cc~d?8h-A{YjE8_=r;W zFZ|2KqbHn?xPM{Yi&quby|}J=K7!wAc}15`bjvgT_1M3#?!~K%9XZP@j^Xo|vP};FP9OobM z4f)4u#(ELPMfA@&{~TGT`MI^=8_M%=3`u{IqzC??l>G}ce|qeM^AGngoci-?il_ek zy6X7{ey8OVUH;H5&-j}j56L?8sXxEAIGD41;u_w+K>w@h*ZMq!_K}7gT^`XbAH|Ky z@epz2G?Z;{+-~)K4_A!7s3B(aO1BR zAx|dp5&4DEj^*VzACZ5^N8WK*FTyy9_&3f+v+FcJcQN>fasbDW^e0I=h%co)|E_KM z(h27yKL76O6Te)%`oynP&qwe(EwAW~Z*HKbkLK2ik1hrOP+pE>Ncxi`UBs7Co`3hlW6qp#KH~H5_UZXzai5+qRnJH8 zJ1wv1@`-MF#@{p_$#cy1>Dg55$XQ--4Dauz|JCFbpO4T!(r}~8C%WaMxG~8`#EqLX z+%O)xl6*w}tHF)Gew4yTD_-JasR><;2%mC z$B^_VNqUGc<&(>%mu_u2ZNm9z;rgYeh3glVzWJJ4i{E_BZPoJ;{7%a&x_qKrp7A%$ zM+?_4Q8C+C9L!l>vEO8Nd_@1N$tyk|p?##`Mwd@?%SUlzl8=ZRFK4)6Jai@bi2hfD z8-M*Mg^$QDly)pH$N7l-Lq4)k!uk=$N%Ye=A04H)zdP}HL|1`-DA(Z_lKvz~`+2M% zLC*Ze&80>6l_vatbO)dKzommu{9WmoA51SE^MgIB=Og%?mREH7M7R8C{LS8v?%)%D zuVOZ%IGnS*;vH;`kK}&b^uN;m#e5z@yGX-}E|2JzkK#pm$ToC8RN}>c^Wp= zN_g?ti;x!+*NZToA+Ol6JRIjA@(uaNI~nUm(8Kd?oPUm-N7XgS)cp(BfNvDKPR1gS+Ox^`NVm% zS^lB_mGX(tKWGf9kYM+^}kEA zr~YTD>xL_eT{pPZ^AG$^%O|@0p<8}5{$}}S_SB!Nm|a=y$XPzI4f7BEuar-G{z1D) z!;3C|=$4P-#U%d_FK*88G8zxPPvjr^UkNY%dQb}gkWVP>SRRh^5BY}t<1EB_5XM3D z&OHC`~$z!@`)~g z=$0Rizj^+dx$msvV9xT1Yk2;R{#VK;KL4Oyq~S%EKXl7S@nV{P1TS9B@G=??y-(yH z`d7qI>V zX%z-bhyC!a6F&ZFnrjUWw7po`e9uM2Cr=-!o`2wXT0YU`58d*k@i)sq18v(?%q}ht z=PaMNhQ~kjzfwN&`3LPH4KKRhQ}4&qDM`=hUy9$s+pg!9k( znfB27nbU?2SleGbVC{L;^AG$^%O|@0p<8}5{$}}S{mfld%+?kgbCyp$!~8@4E9DcP zf6y+{@S@8fy5*yIG08u~i<2|FjK)Ln6URUFzY<>j^`8{}A)kaYmWSi~L%t#ZxTj(L z2jd`mXP$q=o7!L8e~>u;c02fnaubdr(`s}PUrHJOocUN^^F%)nkK>=A1MX-ZI^g@N z{>m@Gk)KcCcUnHt^(booQKd=xJx`GWXH>|qst?@<)gR}9y0YjR^rBf%j8`LnyG?I|Es}`@DcN6 z5+9LYDD7BYj`I=uhkWFnf%PDai+KKx^U)l=>w#WMdLHXn!9SGu;uwjNjK)Ln6Zwb!SHg>AZ05xz z{vn@G+Oa$w=O6M7`N#PP)`Kt(qIVk`ZkZvU7j?9@wf8OPX=`8He%=YIT35F77u88s zYEH{sYgKPo`&{er*|TeX%FwP;r&!loQ>?`C&o{s~ln>ze!9dbV`=qD*`{&#L@ZbsW zyM*74m#@9=FIzVEoTldEc2jRpjYAsCjzz?;hDEL7S3|ZtvBv9ukK&vM=37mlDp;Gp zsOr9Ri)B4LuI}M0o;zFY5BUdvr{$B=+n4wE^u_C}{#ds>YnoyWsk1r7*u08mskjYn zC=BK-pSb&HyC1^9mBIOEJOu|c)dBranpX*aKX7b_8?+PR#*VcY>M!(k>A=R)El)e9 zTE(e85AD0n$G>ExMLo;UZtu@p!^ZiRbxXm^8EzPlT4jSf9yc;>rvDqKSgKWye}#Af zK8P3o(gu!rJin{Aqm>64q;C1qDuEY6_i?f;!OLe0!;=Irn-lOt|10%dtZ8cA7Ch@E z;A-?d4IHb+dUz`gPTdKAlJDZLtlv@pX!)se)&BA5-$!j4S61x8+y6c7eD(Vvrmw~! zS8*7N?;k&M^09meZjAp|cw$7oM8;mK<&VCie-|EkKz+gS2FD+^HRAWnIWA#oqvMYw z{PD*Tbs2v=gz*OD!#LiYF#b5I^7!M(hQDlC`n$KP{(tr3k8F4PVWcTB{uuah!D_lp z)$f!P=Y5xdr5rc@fZy?c0e?@aJATkDPdn-|{;+xr_96LN*YymKKj?qe;}5hG;>M1( z7oM-Iy?ayTsi!{Uj|&TpIl~R(QL9WEf6)Kb@dxlhys&;7IO4JH_(8Wk?NBo`!Fbi^ z_@lkxOcJ~#jX&sr>i7dZ`|9|EV-=CFj#pIsd^HZQsPU^{l5fl6*hA!KE*<+x#uZt| z9~^IR{NYUr#vdG)uqLD9k9q$1W1dy}@`shW{;>t)4ay-Le?MXTaa`r`N0SNEa$ zb763j;3aANLH|?7AK=+n#~;$)=3DxC{%3(HKP&m__dz^fjl;ypL1NB#{l_01Z*ctK z?i7qaI4+TfAur?mf9L4k4>NK9m51>L<-g(>GVmt(Ul03#DXmA&DcnE2`;a;(^DFJY zO4gY1FCYHrg7x8V6{i34tfA?@T%zi){0jF)!0&j!AYNK`|E_NNQG3kp|Fu4Rzlzxz zLtf7M1)kykzx2OSzrf%Bi*}KQ7v254y5*yIF}eSjcp1(aUPj}g_et`G?7O1>mGC0_ zf0-8(_y1!4io9aS@-X+gaQ&TpL;i7g4)}-V>76P5@%Im_LA1gnRo5hW{YjL6M8TVH z_|NzJ?n|?dwI2cBQ2qqRkTq4Ne*E& zWSjqD94VPk=zsZnjL5!Uw2L&n=<kY>ZKkFMgwVf^Yj#@B`&zIEJJ@)ylhmwxrN| z=MU6+NoBr(Up`l4^DJi3rdtZuraKCcf9G}TeL(em0l(AQziz(QEl+Pv^M$qPb``I^ z3Qo@2zrBZ9zM%h=+P^7rwu*XH75vT(vB;b}c`?XJysDkN;5kLf(n@+kYJV@GHnC$4csR z&)a--x$6q;zu_G+*KK1@IB#Wh>eXaKw`p;HB29fmvGN<%nX-g7((F zLRV+)Nn=!v`cwzJSo;hO<_s@RquKri{U3`L$#=4M>yk^t`~rN0c=;Ld63a6IUb0_l zEqFQJ1YGKYm!<=Uyqw|1HH;VfKL#&LpE+Lf*0E#o0(^vc`33L-9IX2Us4jmfK8D4C|c%lDe@Z$HUVt4^QLcFja2ON#XOSUyq z(V_Y;LPu1mA?tvb&F>tt8}l_k>K|8=2l2uaX#+<*4)RO3XMBkc zg%?Ff)TSfrfEVjsLybAZi)R=w^nVOqtP2!gtfn!1gz;b;FYz-P%x|=0-YTu|GJjRi zn(l0?Xi;m5!F;-@>yif4n9}-l$;laBq7l*g%=r=eKNc^6X5vNGb2%T7w4TfPlTdR0 z0XU1V=W>39^DXYK*iVFcdivJT8NZ)XfXGwS6hmKUYZrf)Ci#1r$nIU!-=O-{X+_5T zy;;q*T%_K=Pr9G&uhE|y4&<1^84f;o!`;Q(=DlBGwDR=~x_*r_t#`_C)^)Ex&a(c{ zYz?S+mZejVvo^j?9glqt?;pFL6Z~gBv7ag*hed1pRL z4&(2tmJ&DX)WmtIs`X6p54}CJ^;ZTC7=K?Le;x(rJ;cFp(Jp`wx_5d{*P2z?VPNT& zryV<~by|O2-zW~|!Oxg^o$mzt~&`2XcQm`d{_+O~46p!}DVUPdr}S(YgHW?)KHI`9+OV zxBO^zUXVXb^-H1Hog}zfdf@o{A^QyJf4pC+`lRX-+F%}5*6rADWIxi`4f_JIe#i4< zYM)2p{N?J-nT5>v&g4Fi|4HgcJ_Ej_d=|%$^e0I=Sg)h}#x<7~7antP>OK!k)33Na zyFam|xcd`B#q<8@^yY^SzuKQakN+lm9L}r5?|A!<{#HJBcB@`|hWoNok3SE>0}W|< zpU3V`lvK>tHV@{k{d=>_J{N)hZ&Ynu{U3Wp_64F{q~WE=`A|C_~_bmtK^^g4cS-L$6EBn!&eobcz9iL z{~N#3y#I|qte$`1cUnI2`DbjEH65AaAIq9%wEy|U!&j@AeXDsmXZgh5&n*AY|4RK& zf4&3lA`LGA|I`GLF+VoNKeBJci|`NgViNz5PblqJ z9**-5`G)-Cy#f0cF%F_@rugU7cD3EHzg=~tvMmXv^3QYN8_GZ77?S=ZNe}!(*>Gf2 zar2#DPUoK_g&Du!dg!&qt%rWP*f8+>=INVvPMr@7$3O5pEuZ|oj(@fudYy{dUz;0q zmQUP$&GHZZuhgIQ`3LPH4KD%z{QZr8h!-bkc*&Sn#uX#~(Emz!5&mIbOyVE%Nho7^ zIL<%h8}g64JJxYA4x+)P_RSyBu&}4IyT9S&_P$;p&GMX&)z#yA>eOK0{9lsBKhJ}2 zcKu!O+@0MZUmr;N>zH2mUjk*e?e0px>1K_@!kw4{Mf%*|V*_Iacr_B8@?x z>G`)HZd(c+Im;*Be%aP><0p>!g#K5`CqDlGA0b{|Li+)Zs6W8VyLni%oUicGs)3Wy z3Qg}jQ|)Zvp9^lz@M6z0ix>J|Y5e2k1^5W@vK@Gd<(U94*-v;uJ+ZBCF7iwE?f2>$ zE8xY@b^k$rxvemmGrYKl@k0Mo^9%41;^k%F1vp~623|4~(tL%NRt=oc4)fRLNPfAl z;N=W2o?*Pu|J3{fe1v$h(0>Dtc%A~hWIy4BIjaA11oBJv%QfnhUj_=pIm3&c@wpy6 zpOoys(Err@0(^vcnF_oBN7Re_l9`a^E4;L7;DmP6CBIlL1^aFJn!j}n{2 z#LG0`1vuh)0$ws-m{XXO8EQ1am-Xqt98+k_8D88sneFe=|J3{fe1v$}1$Y6Dc(Q<( z%opa&H-wk^u`u6c>0ZjU3&%&_Z0nZ$ zNQ^$;_JnL3di{B;7n?hBh8Oz)v-ySo-#mW*(|~M%4Cm{Bj}R}Mw*-#H;$=?e9*E4h zHY}nx9a)F@7wa3%ZqD%H9cUIW^glJf03XB)&!i0;@fduRZIM?g@$s^l+H_<+@Y2yd zm@~XM8J{~6k37dm^gk6ZSpOhi?ASU8^#}V?S~BMs-RG6i4%7Q9gEf@D7QCF{h4Ijp z#0&i|-``ceMs(N{{B~G}$Olfm{7I=!TNBjGGWBRCv^-vEb*EgBhqWT_?>r1en&Gl_(4_se@ zeOA+QItvwxsp#=@?JE5pwgkV4ZtQAnA|$vGVKNF5>G!o_x>l z#TOsEUac)xzD}8bWo_@YE0hCg6s>_P)w=eLCCmDCv(@yGqP6i8i5GQ;`3e3rKiM;a zID~rf0sWu&*Hs@kG^j1w23}LGAd=|OB1o#N? zvM1UNaKuv_;3fNb{2dJqstxJCrs6tQQ}-zk@N)N-#+>0rKazn4_J8PqDqet(5HEWJ zFR?rm;3eBN9Aeqq8WOki)Z}`7^2;B#I61?MXE?vm|5UsHA0b|50x!T3PiBCZ?E7a9 zOJqjYP@Sw#ewkV7$QfR$i&pxtm|y6BDqet(5HI@yFTfFNME@o8cwG7~4XxCsBZK=Y z*ru+J_xmsJF1eE&FZ93C_{txT10Nw?_6J^oBc55{C36Qx`Y*3syqr-QoaA_+|EYKZ zK0>^3oCqAn@RGR$qxvsq;KKf{(fo2@$(!VOq5r9P0X~Qq;==}xc#Qm#xdU@p(GXlX zo;He?Yf8g8!;Aekv*T&{pNbdEHxVy(Y~G1@dF8Ap3>m#&LojF6-)z4$Q){HuKKwwf~m1o-l;<1Iq8?7&6UR`>%M;4CJDZURl`mZ}yP7zqOh_ zPkzo!n%-Lfe$jzHC|q>lPYY|0{=m@Mqfb)xSAGfJ{P7k1j_0R%X}|vy|FVW--SVSV zncYuu(SbiwF*{|*$yt7K-eR`@L;vIXDSE#;A1`PZX?O|vZ1k+v`boF^Xnkhy7ec&r zdrjNcxi`9mJPX_~+iw9J#~zXWHSP9GZ6cmDTeP{7%a!y8NMAel-5( z`DfbU?vR_aeBv7BANpS@pZNTPc9Dh`UH;H5AH|Ew`&9}52wnzrhL_QJ=zSvp(Emz! z@%K}u@DKSUl(9S<=O6M7`Ny4!`-NZ}MDI-Pr&7;(SkTkCy8Zap<^4SwE_M+9k@rXf z|Il7a`w{RDWcdA=KPda0P5zzoF87o3zxedqhhDmTiCW-K9{(u68hpnZvU?vOXh^9lX0 zluu;-gYBK|-`NlQDbWul8jbfq=Vn_9XaDoB3GLth3EDg5qd117KS|O>ex-c&kH;3z z*w8rP{m*m$d`ieJYJFWfe_8)c2GybNphdt-d*Q%IZG&G#E z_V4X(cK(C@m!Hp%?59M#NW+V6|53Mm6fY+4*G;_G@0jH4Kk&a2Ui|s|l>R6Agfh&> zz*)TiNxmWf*!yGt9sN+Ack}#{?bbA@{PP(2hVpS7L(-ol=^?(9Z~w`0#rBy8O*sGD zcE)Fmx1I61;)a9Q3~f00oa*@pey8OVUH;H5&-hoqUb>$@t6JW6#(EXA)kBRr%O~D+ zv;0H@z9l=|DgYs@ZzukrtlB>gwl@X z;W+=0Z^%F10hoWsIEen4=bvm>l#ze7Cyjre0N+q<#W5uPNs{(<3H)nWZJai@bhyGW>i@*MhyqL89OFju@EDy)|hkQf+aSz1&JH|ou z&p7|g5pQaLrSi|uz&Dh?z%gW6jSk{Vxn|3er3D+_G~wf)tsh)h+WNuEOKaNtht{<9 zRzLoM-)Z?omp^pN^E{Xy|7`uBt76tSG?=q|;us$P(Em#PS)YH(3RvL`d7ZO<4cIIEelk=bxjpUD`(e zc`0f9^DFQT<&!vuq(4d01^-Zf>MNfpT>X|qn*9-t3X3m(q_FUTGnyOE`jo1_ z@+(~bh2LrUM3+Bw%hQ`FxL={W`?j;k-mmcVcG)3N?Cevrv!|N{Qsm-`Jr%PHnul|i zPrO6SjelmU7}0+|=X>v1+{W#LMf*s@jV_PqmZuwn8{r|-xUmnPyz4-M8~R@jZiJ7R zCzJSy{6cBR@^YMy$Uo#G`^{Jn!nla%-xMDm-?I|8y32N}U-D7ne%N1we<+{AF(my- zk{QJ>!lfw956KFk$tNl55e!W zyrRn|y5$)T)AMmlpZSK0*{q?)oaGhgP;-1VT?Lo^SDIh($3tirX?W4)5#91pyqKJi zBVL@G;f3+gl^hSz|4Mif{$XBB;vez}r5($|asDCSkbk^`u^xnR5&bjBKgV^qF6(Ni z;u>Wt|NItwLph9N$h7M0zhONHQut@*l@F)#PvBI8qM@`Js{1?nr}*RPL&YEORz3f~ z@3efP%OASs83ohxagtApKYsmCN6zwzZJ2-Pf2H{qpMTIU((t0oAG+nEcriI2N4&T> z!wch~E6G3fzY<=Af0!SW_=kKF%2*zb^AGuk{No;i^&pIc=$|S6S=7UAF6)*1HaSqi7tQWmS_Cy!9RoBKRh&?vwUJ3 zzW*`(uar-G{z1D)!;3C|=$4P-#Wep2UhH>H-gO|EuciN$@ZzukAU`JY5BY@Bj^*Jv z|B!FUKla;f7y&pm5Q{M5T_Myg{B?vIdof5_*-Ka?-x7?S=ZN&9822SE;O zy7jx&%*Q3^%liG&f7xft=Cxn@Zq4&?@H;K9=<5;>FDwUKkHu$@w_?UkNY5Kg^Fw{6jtoWh@WJ z`G(i;AU&DG4uCF#rj{Wp*J zuJxG>O*PNQ!SA$uqRSt;#{A2xM!Dg9X8O&KeaSihi{jZcyeEvbZNW+URf9RHv z;>9HY5HDWN@WOcLO7ai=uY?!jALhj*{vn@G+Oa$w=O6M7`Nw%D)`Kt(qJQT3r%w0h zc^P~|Y5g&H-Yz8lNs=!3hw`qUEh(JxxaE zPR{Vcc<4&<5B;x%7k~W+`7w!q$S0I`EDy)|hkQf+@#bRv2jd|6XPkeI(0e{h;{D-v z0pC#CIEJJ@Nzxv{`VXY6|Lh3<;rdU_`~$z!@`)~g=$2>vP4kb;=L`RIJ|7dK~kVLWst`G@{j!i&HDgS?o;Kjf28#`18Sf5@jdxc!^+7rs2Jx#s=Y@H;J^=<A-{jUZ$!bi-LN#h~%3#A>)%W*y;|B#RDcVRsU<077a!+do3?AiZF)ip`-QQ~;$ zAn*_6!8nFYtIPu*Q3@aZ`&ZlvUk@T5J@oRUrH5Yjs$UO+-)VV8mrr!d^E}jpj~;sY zky2yM@`_`akLZ6jdBx`=w2w60=<>G(aQ+&}vh zXHPsI@&4J)ZI70m+iKt=_??zlbooTLJmYVgkL3Q@&TWsBI&zj*T*G`s|EtL>J|Cfd zq~S)FPjt&iabuE?h#NO&xM4hWCHaW{SA!ejBj(E_J|e$_GM1O)d_?{sAGz>-Kd->g>helU*3)1GPg~HBgYc1`R~~NbF84f#nrmo~nC(^^ zoaA|h{xh#6#Zhqcz!Wv_f_Be5;Jgp>_UNCoys11;=utQF>Td7z`!%bny?V(!kT_5B zcC`B@$Y#hTfn-hgg`1BS+{IrG`lBx7!uPH(+;zviCWWnu%>x6!Dp;G}TvVA?;d(&T z|65gmgE}t%3iAN`XCAN*AL}PPgj>X-yx z?uzrq@m)QwwLe$c61+6+G&DTP@k0N@Spi*pTAym?03IYI5r6Tz_B480Use=<^eCj z5l)j8;N_^y{Zbz@44ZHwHEEM2nPUa5G z$sZ^-9N*Vk%OfdSbxhWQj|Sd8;M~D~BTLMQsPrys&4onm;nUj=n zOdasjbllMJB*zQ=kK*MkgN@_y0(=lJ#D@(W@i@TCQQ0oeQc4!|bgpi1I9_#Nda@3U zU`kQVC#m^elk;^0rwrL|&e!~l{T8$L<)Qykyhy;u*#+RFETb7Gd==7LcAQ0 z{tIwKbBLF$9hlMeBWlbhWjrnG$i~)>e7xMg#hK)Iq5tK_)0P#^?*bnoUL4>hmS>2U ztR0xq^`mS!87&38nBpTJFHddhnB;h&|KsyZ5cv=j+d-_WODt;eE;RNk~himLjTL>m&kem@Dbu=A@Bkm#qcsO>jHHIFWT!z=JB$& zG(5@iLjP0o0(^vcITd&Tj^cR9%12|C0;n{TtV4fy;OdfnaK7eWGKH>8A&#f%f1HoT z&A$L2Azl^(FTfG2K!0~$*7=w5>qpdFtE>ZFteZ=XlN>MfKNT;)M~IixffwM2XOnoz zI{y+~56E_fAT6l_UIy+iIg=bO^gk6Zz(~pt)Bc3JVC2M~-ikGZ8DzK#vc(J}+ z>X_tsq5r9P0X~Qq;==}xcnrK8nYF*`uOCsFmaGF_27X*}Cpli|ebNw3Y1yk`u={Jc!mZv`IVLjAC8S2A)PgI{=zr^d6c>R)nEbjAy>zb(F z)b&drIBoI5(-u=}?eZX8$M|f*b&U2I;QOVJ%f?F9Xy5)sRo5}z;$B_c_~_w<4gYxN z#9qJD^l!zkGhUMGmF8R4Wd*C@--}%ryqJFd68vX=vd;?qr{9#p`gYdQmD>M%{_?K& zmV(9=P=O`J?|Z4@W?54TgE`Aj?#%M%iRY_Y$?+BaPaTf~A0b{og7yL&vEBeLbF}wV;^gotg#_zX6e=Uv|;)D|8tIYeYg8Ok$TXwkQjyd7X{bg zS={%X3)aA0>YDG@6|JRLs`~d-SlyI}*RbCJ|JknX6=VHoEddYA=3&jUFnhMuH^*Ak zx~jLUJ#%kW-7kmzOjGw&uvFZd+KY`j;{kUcv-@u8e`>!0_z3aR0sI3;1V(_Dth2Ie zaINsts(};QVZ7fUc(MMe=;RD9-b}N2q5rA<2H+#a%SVBiSe^;+lKq4i)E&6`<|4mn zbT;dfUp6l;cH|5%j^X@5|5Nh|@Dbvr3wQyJ*sg(>%!D*w;iXjrC$yt3`DNhbqMI|k zc!u#p|5Nh|@Dbvr8+ZYZc%A~hWIy4BIjaA11oBJf(Qv)`FU8_u&hTOz#tZ#V%`d=5 zh?idA1vnaumpPdUX}-css|HSJM_uxZ_1>bFH@q0`ztI2G`~rN0cyX)xR0rT?k<1^5W@(hs}2||?rfLI%KXcl zi;X$Mi@TTE{6hb4R&%WC|LALAL~Xte=j(uv5HFm!1ddn``6Y7?MCMx?7EzmyG`ueC z&%ewnI(fs3;rv4XQ}YY(LA>xx+Q1QyftSo%W_`S9>>r{Xb>XAUGm0H~!^?qY^9%h? z#S7Lyh!;Dy4#M+3oG(QN>$bA*)fBF8d zYNhIT{(Y8#58{Q@+rSZzftNX1XJCxn0@XJLcrkSytKene{Nmsw#|!Bzx@)k${e05;_Qe=a3_xBAd3hk|k9&1>`)+r-@3V#d8@^wd z_xj4~+wiNuy?b@%it|~Eh8*~1VexV5xd8(Ys`j?0THk)Uu=o=PDp~#&<|p{i{A42z z@lv|utANikFGqytOtpqo|KH?u1AeL2E1xKMIm=JB;eAf@Kf-6_@4E|p5HCD2HgLpa z^p`Ua$OAsp$BRY07~?aAmx1pUhI57&XO`LiGX1Z_XMX<&`ILCEV|kT$LH{S~WsR1( z{Ic0>e_74lSOc#q+K1+AzK`ccSF*oM|0DTjjOvh&fDht@KeB-%9<#rkbpgs;egR%g zFBcjoIbP_0EWeC-E{XI<+5cpJ)G6XQR@iq*yliZ^WrlnneV(1_ft|2QZ7k$3 zs*|eJ?3Q_!?9!WOWq7RJ+f?7>TJ?S@sXuxJ`k$08j;|WqAGKfjjei}O{ow~sDEB-o zdb9cZ3%C5|g8x;0oYem4?1o_XVMFFgE>`NxhqhSOaI@9$HnrdKNYxL$MIHZZ^O&Eg zgW)TlJ6r4z+duq{xBqxK-RIHimZv>a(7$j^JL zV5T~t|COI-7rCDg+6i%E$Jz_^>&~m`mZu$RUT&()}2?=El)dCh79mxs-GcvvEEU1Ckb9QC*Xzt$NCv#uJ5s? zsp~qxv)=gi$I(;de+uraEBDq_#jGh)cf#N0`}iyCccXPs<5YeaBcuAGW%$|u@tASG z`i6GC`h5_~SL2YYI1t++E$hdRoO~?bfg9uhmHh;255b7Y*h`vl_=^5r`YAI0;CO@M z5BqrBhXV8BENpcAafCnq$h5YYI{sLP@do8JIKD1n{IRO?_~ZBgb-|Wdzn-f4|J9E_ zGC9UThZ5tDCyy>#4ackcs~ms8?|8o;RErO~;|JaHw5KlPkAbG*V9xplPR9L4N#hUt zU-kF{?S#0oW9^0KOLzRBTb_2*W&F`pD0(@=4dYR(Od5aC|J3mZ@Ikz=ej7OAvF`Xm zw><5r%lKpS`-;Pp1TRVB5Bi@v{s7OuI{xs-C+L&=eLTOPr*QgeKRsxyuf}1A#z8R2 zcm2m79B**^;k_UCo4`5<^S9CQ$6SB>k!h=1>iFX`7;jLn$MN+EPEzY1r>pvJR>zO1Ik&N|aqA!OJKirCTgtL@#}B&Y zX^;8whl<mQ4XjXA>& z<58p%YBc!T2)_XJ!IfOQa@d&}tfV~*8+UjLfD8n<4IKmPb_v$c77(ajld7>`58{RO+rSZzb;l37MRbv%JKS?7NAt8va2=ZPJEaJ<3shjS9H|G+v3^S7z% zkxx6lp}BQ+=W6P$Rq}q@FDG69aSO&9cSC*^virF)&;7BF{@a*i+Tq}OZ+nlR+;Mjn zhmJk(z~a0I-mIk>PsI!H5#r?z-~~9M<^V65Z(C{2c_rtUf!`JyCpli|e=1&p zj}R||zzc9R7B87^d!X?0O3p7&6r4$p7y6%y7vLkr%bmara5NS#bL7@enO=(;7A z((Ahf6{G)R>Uu=!zo`4FbWC!*(EsRs*chbMD>Sz`6~uF*mYEirxHN;P-Yw5;e& za=g(0Xnv81t6OfXD`qblz3(>g5#nW8fEOD$;#uN-o3bXD4^xr0tOH)GGm68L953`g z6)(U?h?h3tC6;H1m#p{sTB3~;DyRcqHh-{azipDwzrg=gyZ|2|URD4vz!A?9@sjl# zj#qSk891TXILYxs|5Nb-e1v%E0A7HjI9{^Pz)+K}G<+Yy0qMWYFFKPPFZ4eZFTh8L zmyZH3z!A?b^GnuyRG3;nQa$zHKBdOyUld-fcNaS*IbP_0Dqet(5HDT83vd+2OV$-f zQ|m`{!OP~^MR$_ph5o1F1^5W@g8dvea1_T&)*EM=T0g1_UIrSAgOeOD^gk6Zzz6X{ zeAvJdkI6?_R~${PAJqjfO$|kFlH-N`SHg=d265jPpY!3yo*Tk_a+EgLBQZZS6@ZfY zKhekX)aOAT>!BXXP#?zcaeXXLefErCeT(%_4`rwi|n zdZ>po)Q7wj)%Sqh2M_x$xewDm1^2;&pVV(^AEtjF?}qGGgG{x9=feCYX&>gj=+8X> z`5@#&fuuj~SE_q1%)u2kS*yM?<(DyT*B>9aAl=NAJ7Mzn}Pmp0@TyJwv%R}t z8!`34%RvSEut`3j3;&6igSU?y^G5Zarru-l0(^vc`3CS3%QL`B=IOcPdsbQ|mKV*h zM@xR0QfQpyc%lEP>(RhRh!^rQa1_fgnfFI2yqw=4@H&#+ zxV^CFxl@fP5IotQr%UQErCsB6{aPC1L( z`};e)SJr;nD(6Z5mNZZDF#7HL{onu3-q!%uQI%;=Yr!KTmjCi=R#Bp8O@BZ@rETs7 zMt*9g1rhyB(>84)X%f=3{K!HU5N4%|tXs7zi$zf*f}+c>B8J|mqgG@Q*?#^lpQ2_F z*)EG%u)=rF%=1j82bJ_i=;+vJ{ zNnG5g>K+vK6W)8zD@W$<=qaAD`t4QcNmx(T?BKgcrd>E)?m@q|kP8-vwX5BQ`Sml64|>m(DM0pJdMXB95>- zPr~?9`2v1KeDT2-@Ti#BB1w7LDlC`@l z`C{ijc(sqoI$zX2$(-@Uv&hcNced ztu)=MVt=2CoUa>xWl_8-U-K_)7gI~VF#h;H73KRc@-Fzjq>a`Cz>kP8kAg4Y5%Gk4 znVq@+qWE$~?}c<{V6kt~=J;svg+g%X>1w3NIf-gq-#g%(i=r6mi z17Dn{3T}h*h4Gj3W&470<7x0C;>*v#7x0Mf8uDe1QGPkIea-pwm(|uqj|N{_>}+tp zF#fn6?SV#8OZAZ+fgcfHegVFKM{HN*7o+)?UAF%+_{)OV;Cx~HalWXwAJ=~YKO(;T z3VZ>NG`?gWPpkR5UAO;oUty@h`NH_i^{B#gpTLiZFOPvQ;88hW=42jEE57Wy{g+z{ zeuMLc@t5=m^P|FOgY$*)$MvXU{{{Sr`0_aT0v?s~ z@}FY=9onR62{gtiXzb%UQSh?xyO|AP3-^GgLi0zV?Y{0@8pkJwgWfA`qTd{NKY z*k${>&b5W+2ImXokLMS(effJJz>kP8qu>j8r12%Q9x1-;vi)6WZNY7DzA*mO`~rSN ze0c(V0guZ0a$IIjQGD5T`@2gDoej%Ou3wTt{mt!-}@2dR_yKetwzrs+1^M&!p`J&o>+$51#hV*^{sr;J^{8V11^kHkvM2Zg z9+mUugv|Mce#~th=IflL3z{38FO0uDzf{m8@FU`j0AIi(wr@CJ_m<54-Ik_8cl+u- z`doL0A5%Fa&@C7_#8So|Zd>#1m9{S5_>%*5tn>!nv zFN{BxFW^VSm%YIk@QCdSzGNOBwKSdC)!*OSZ<=80!_!05t0PqDo()f~jd<4Fj z%8^qaJ$g?`Yzx;x7;mH4=>8+bpUM~TBjU?J;0t)fdP9E6JU*JWOZRs#DK$4ZUl@NX zU%-!uFEhXw@JQoJ=J65vVwzy;l3xb@spK{|Ul@NXU%-!uFMRGJcvQ}pS+lZtc*F6u zDPNqr+&_I|sk6cP!uV7ByWj`;LVgJFh{vHG&6<_ zUnzMF&KJfX&o63TSAELnck%pK@QVU3vH#+E%9;DSEp2C?(~|Wi|gWp0z9YZ|2`nY;JJgF#aUokOxu!20V#)=n7+?77kh6&yKEeFWwZ)+Z=8bwE4&#r{_n|h+@4p5=BEAfV?~M}R5nCYQ zOU4(Rv^1U3(cjm!nEtZcaK2AidtRcP@7r`u(Qk0RF#go_1n?u`%VzKeJYu^>e91UN z48AO(zwEXSd>Op5INIQRVf?9l0Y4(X;JtJLJYu^>d^wJPnV6lmE9aNt%ZlRZ#+|28 zdc^os`2v2BFJyrLk9ZvMCF42*__B-UmvzPF2ImXouf`WOrOWqMeo8K4s&z~c@3SON z_`c7`;yr%?>zq^ZMK#Z({INX!`FuYnY~<(6@V%je{;*!5`(t_f69y4K6hxriQAIsC9I1u%h z<`3g!-5<--p9_CHPhz|nKk5Ehp8h=e<9WvU!*j^lzt;V+JpK9b=h83hjh6L?{+I5L z<>^o0J+C~^IDGU6eb)W4JpJ*#u{=+rKjd%SAIsBUbln1HqCe_}oZ~o>x)INx$&(ihVH~+LWDBtb7ch&d% zs<@JTWc&MxCAk-DfiwRr1!s6fp8FViJbi)gYxL@;&sX@Pd3VIE_XqTH8Fza`ZcNM5 z(G{bZ10yDye4da)~DiuTIXZ@N%LUg_Xp=iyuo!s-U#h_ zq5nc}cdyBYHPiCMG1Vzfeeso39dXFEfd6Crn6jQ>NM2jtE_CLMH>{6|+9q#2Z`8Ph z@o$paApbw^6Y&N7AYb@J0Uq&qL3dwgI}b8g)AD1d1Yc~;gE@*XcNDw^;mdFWUl@P2 zafdTaj%T5>egdz?+G%i}_C+pwnf2=(FMdfE0`}Z+S$z0Uce)sJmgE(tJZPe)YQ~UUnX`c@6WO| z?ofPj?kxB@TZqdDV? zXF0zx{#3qz9}!<30bjr)HgU+8jGMxwlVcK`WlDPw;`Y*dIU!0W%x54?s_*3};enfoXI1xP3_>#E;Bl|CQ=)(T4 zt$EX+zk70_v%&eo_*3};evmKZhX9XwjQovaYi6{IsgSYjqt@%~{F!xew)xFRTw!%l-@FuiW2_?H2$) z$QPbpfJZzAUuI{WU$nT67xKkcehKC{pDOqb&KJh7=NGoW;#IKU5A)L8f5dreevk9{ zw1V^D;1k!`=#S;;FY<%)&=0L(e+j&e`%~))TtDD?f>;u+C$K#I+geYM`+i#5-r=;& zrsE0P{jr|#Y|?tdV;E2T8uoG6--VW^^R9ig;{2^RINVo4yXb8j3P(1*OwLwRUr#_> z106kUx>jDyvl!UHU&(z;uaUX=Ai0ikrab@eEmZvThz$MmdhT{+?l_(8s~0R?!(W7F|?sAuMU zacuXO6A?OfEp>`~()+jU&$553`{A*z{_W!B9X%b3`g{92`Uko?*3f;; z_9afZU*^Sx{;lpvjG}-0e0l#?++6v&ih6m+dAKC^Wy+uG{oC>7CigED!&(Lm*y*^M&zO?yto5SAic9U!DSAv^)d8WSz!vPMK3|TiDUwU+C`Y zn<&@Hzi;{Z18_dn;Cx~HT7O0E+r3=w+`atrNRPmeh%ei~7x0K}1-@inKTv!*#RgrN zUu?|>BS62w`NH^9`2v1Ke0dst0gp7kWPBQqbX?)2%p)30@N{;9*v#nQuSNtho^K+RiP%Fs!7RI02-vvJ+ zzB~)QfJbx>J<9kr9LJG-k#anXej=8Jm12IJ@R zH4f66CO)oKNyEiH46XxsIA$@i5B8}X^g{StnrD6&+J_zp?h}o#11NtiPk%oA@jU)3 zLO<>d_`B@c(BC7K{jog#i5Ylq6#edv`*Pt|Yy-YaL%%vcmZv`#{&*hl$8q-pKHeug zP}v{L)1L=_Jdd|8>hG2CH@q#3cd)WQmZv`-{#^P+d$?~8{R+0nd11ZmiH1}CS=Ama zPk-VN)F1t#{vv;@zxP%4$MW>&!XM8g-WhruWtIK0JpFm_$MdlMB7B=s ze@iR-V|n`X;m@UIyP_V&I`Hr5kT*JCSf2g_o`=KpkT0G<`(po>=nMVo?ZNW&=fWS) zLq9IsMf3yTQz1UxAIsC92Y);dpS$I@0w122CoZY%kLBslhd-BbABFZk740j~z8k~# z7*~HNM}Ok5@OwOu`zrWb2!Bt8c|hQKQMx~tr#~0|BAkfR15R-%^1+@VPTe2N)1L=_ zJdd|mh%4gXlkoTc%JH&1{rT|cGH&L9L(v{rpnbQ7aqI2N^7JPTNBt2e{1B&j4E6U! z<@RNH`g7rr=kZSneN&dRwZ%bu=EKh$f{P8^F;_ZRI2P^wy zdHVCOE zt~dJgEBj-4`g7rr=b<0}0O0!p@U0K?j28QWk5$|1<`NHz_=fYovb6>B~I{}c~y|lk5tZAEKh%8f7BoSz8UrR z65yPM{=t^e-?;iidHQp4%=36}3jMfyz@Gzu4^{TZ^7QAyA90FV@CTeiz~9u+>iAfm z{(SgziF0=7k2uBN@b^OH_GNkc69=IFi1Q7I6F9|owC|pk@v%Jpx$wvH_{W6)eBcy2 z;BT+W{#c&=Jow{z{G))6IG=>SXG5#!1D2;hAO2j%{W{^lxi29>n zjH7)4oXgN2zpl(@mZv`#{&*hub+~>{fxo>mKKf`v{h>Vlc{t{IM04oREyCY)_*-Au zAIsC94}UK0n}BZ~{2dN|1C{-;JpGA-P=Cb9es~dn@%(ggSwj7xJpH*i=6N_?^-h34 zz7KR|Wq&MBe;)i1C;j;+!ylfSLN{~%hR7Y81=`v zi3{y4u7baPD*I!3`g7rr=ZSd2_Pq{#?hdVfy|Fy~dGN>c2=bWzHo#wJWq&MBe?I)V z#L0OB`ui08t*Gpe<>^o0ehi*x9KMgk-v=uDV|n`H{Xjg=xca*u{(36=V|n`XfRE=9 ze;4vD+DGl+dc%D`CeY8&*Q&Z^EVCtaDS2RkLBr490LBqudlbq4TyJT<#<`1 z{#^Lud3fD&UPp9-&rekD-?KdZdGN>cMAz?0xPJNmy#9pi7v<^C$1%_2!;i~6H~@Ty zR=(a?p8mw4s6XNakNwvJ-=(O({VMxodHQqVkLMBa=N$uom%!gamHn|i{dw@m^AHz# zBMtyxrdIaH^7QA!pUb$33%nLH;P0u*?aT7?Ck{jXF>cKJ`LBc?;W^FX*~;z9^7QAz zAJ4<*b4LE~JZQ1KvOkumKM($R9&dKo4$*w}@rZXYY#04{V|n`X;m>8dHVClfwe&&M&(!+a{<9^w>y|8Y-W?_l|8w68e|!)32P*qxdHQqVkLMvSwu|UP{r#?Teqnj~^Wcx?Auj(g;OmCJ zUsv|W^7QA!pG%y$Zr!=?w@=uv;>61B!SeJcUWNM8{P`{Lw>SLFuI!KH>Cc5fo`<-Y zx5V3!ua2wikLBslgFl`p!i9A`F&F-htn82F>CcBhm-Zcqll{N-Xpf63=TnxaKhcEx zW88~Fe^I`_8U94&>y72<&xJpp$7_WS5uXSB?F+4beXucjPv(l`0KCikLBsl zhd-BbFVyO9BjQ~b`qT3Z%hR9uJJcWjzB}|6;k*_8uCDBl<>}9bKc0vA#XA)^@xCf? zb?A3o{h>Vlc{t{I=*I<4;Q`+*mHn|i{rT|c(ytS?Z^V}o_?sH?MaReT^e0}8`b+Zn zUHF?;*&oZ(p9_CHkN+0b8*qvh@V7a%di%0G{dw@m^LS^6{-St?;BT+W*9XhfpAUa7 z{UYCc^MRA^L0=d89an!SM}Oiqs6YIjexkT90={LH{jog#x$sAv}9ZKc0vF#Od%ijD4HeRrbg7^ykB$OTX01Mew&7{ytUNAIsC9I12Tr`4eZsAKs@W zZmjH&<>}9bKc0tv$Q!XK^dr7d*&oZ(p9gCcBh zmzI8xhrgrX?{$^^u{`~Wqfvjv2|uhy(F}jTs@xtdPk%1_@jSc_pX+eZee1ug?2qN? z&x1dnhyJ2^l}qyCco@xGm3Rrbg7 z^yk7K&%<~le7w)_XO;c2JpFm_$McNy$NQomt?ZBG>CcBhmwxs7<9)MREBj-4`V+55 z{b~N9bsFBs@`<6lzE=0J@~%RRf!!R~&4Jw<*v*069N5i) z-5l7>f!!R~&4Jw<_}k{dnF}1JPfi4gFZ?{1M|iuO6HxO4wSLZAuyW3d?yiB3wt@bx zmA(DTJKEN)?O)lx-1Nbj62KqjPxHTp>qoWXsq{U*k6GFA?YjwPI_TPsPzl-zG6X!#DOnm%4 z@#*ChzKd9B5-sr&5AhKKaVvZ_UcW)VwOZn1dlFysJz@K@-4(t8`3{s?{ic1-yF2tx z%kS&CgZTJ8;^X&e1AJZbmG5ho_xE;p^Urm+#K-y~J|FeRdR6#(d)0G+y1UlMC%xcN z+jVbp;v*j7YrZ1Po5Zc~Nkwd1-9BKY&N}Z!`~E|Detxs&o%r~D;uGHp%g4Xo*WV%2 z^FsM#$oO9;_WL~-JYIF(;ib}@`r$|66Y?NlPI0ubcFjQVYG(!U6EE?*!y$ggrRvva z{vJa841K%2o?b@au*ApjNBF*3UQT_z$Eaq*6Z$FjtLiR(jVpZ9+=#~VKZ@evR4dH02NOWdk_YrLT4-xWVAeTa{Eh_CruAwJ?( z_~grE>h?*iKjI-iANYt{l}~(ulm*mj_=t!2I`0qbkGNI&1#Ru!eVy$V(2REx&qwip zW&08j@d@Mv;#T-tcOpLGAwK3T;#T+yI}so85FhK9xD~!)9q}n`sPtj`QcH->`)bjTk9dfWIg7Xh{_RA3#6x@}Dscz= zt0O+1Pq(~2s3pYL{O{rQLCsOxVsqTz{Jqe>_fTkwOYg%HAHPq0KFYJ4vNp73G^4h} z%c-_>mQLA|*ol?cJN+sHMbo!72oQPp0#>;TgPejM?A#mZwc#yeFifhi4f0#<_#LBuAKMAq3 z4#>@&)psQx;u``!;zrx6s3!Hp`Xe6VbHN$nR`_i84QmaO_=t!2$Z6tM_-tzPMDY<1 z@v%H{2kpBPa}RS3@ijjhULPDk2in{*(AL*)YexiYAhf~tTK=cti0w-}#ODJaaT8y+ zdjCircDtnEBOc=G{14P0a1vif&$bo!*5COZ_1R*O*1p6;eD41Z>yNl2d@XI6-~BhPa$Sx$&`t?@jjP_lTQu_=tn?sW?;)Hw?q^GsY1w z7sfF-?-O^tJlON8_JlGY5I5uK{6*Lvj8DZObE#<<&S=Is;^nHf2XQkF@yjp{#;4+t zIjwEEe92lzc3L^&+3${U^2<%W{e?TE-40LW(=c? z|J3Po`&ZwLYqk6YtYhLKKJP!nIwtM_pS2NeIR*K&fe9e!A_=r2e zXJgYrB@ps&|MvB-SH(v>#ODJa>oLGLC&9UeKmX^i-e0wSiHG<)|6f>t#2w(9YXL}t zi{C!}IQI0He}ViX9^wh@wvYV>yNn0@U8ALc*EnwLLollA-+-IBW{($%leQRdkCE=IXp>EFC}JgjHNr{ZW2-@O|4g)_$CWsDzMa-HnEyNlqo?O|xDr0sWJL^!!JQ**i_u1p)S>k3K%}<1JFupxxVHHPT@0u=? zHz$k!>i2^v{Z>ExsCrg=mEz@89RF7ivPR_(+ktqA-v@rirOL>)6S=mximoTc5+Csp zU*{jf`Xz3KPt7l_>h4|E-fbVI@?Ysge8fY1;*#(_BH~u_|2FT}6ie(zT`GL4uN5yB{QDX2Jd4Vm za;3=>OS~$|evjjg{{!(65AlrxA908H)^xV7Ft`yceq!zSGvqWcBOc;w{_hYUamVm2YhP}E`&U~15fAbCz(?F6zWQaxGJeW%%Ssr>CRcU?z90 z-qL>K^+7zu=RO_QA908Hg8b69X0^O)*JN_D0;sh5BOc-#1wP^q@h$J}>g%((;!^>r z_9xaK@erT)zhV6mcZhHGiZv?-!kz7HE4l_c?MX?zKNg2be8fY1&Ci7Rh&zt2f7LR} z=;DaVe} zZ^TDD#5W3j#I567(J|28H3^S=AU@(DK5u(if5ffh>+9%W(`T{Xl>bT};v*j7Ykn@o zN8E9I%P(Hu-7#=+pUs|h8b0D7J|Fmqy9}S&JzzOQr{Nrg$I zO6`&LZ)y05hxo)_LVUy>#~0j{E@yjI_qF$11z90D@{f3kZwUB^JC5&?HT}!ibWFm< zEAbK^@erT8BdkB-R`^u!s;$3WPAydk)bLMf?MpnwHwt{jt;(ypqkg&dtfPN*ukB%Q z8b0D7KJTw#{Smh+KZdQXeZ{)=p5+}Y+B$mL<(8oOX$jkxc!;n0g%BTcYxu&)%CrTU zu+7Gji<%#-^dUatAwD1Yh`Sm-8%r)}?Mpnw*ZE>tf5ffIx3|mYtQ2G&|Hk?w9^w;y zm>WbrDtwo;EnnSNM=X_G6Cd#q-w^N-cZhFoU;VCxO6X$w4|s^ry&$YV;#T z_{7=}A8{*u;Ui6#O-{!OEzbHQ9^xAUKH^sR!o9(LHsls(PdCIzJjCa&3+s=#WB6>y zZ8|V~gZPMt_(p+`xX19V-YNA*JjCZ+7}g(g$MEfx`Xe6VYrZJNN8Drh+ILF*5fAbC zz(?FMd^@H7h==&NCQ966_?GRI`Xe6V;{`_CF?>6v{gpq#*S`HDoB#AS;wN6>_ko{r1?{iysc36oJJ8$L-`h7i zRZM)uLwrM*hxJR`>e>&VligwkSm$MEKb(h7<8`b4MtuA}@d>S*!e{=(AEKz;5+Csp zA3YGa!dIU=8hNJ5miXA7#OLAp#%%Yo_O&C8?qJxyqp(Dm)V};a@#*DucKZ?!@i89a z-r4QT_SEsQ-Glrh=U%zjTyF4L9d6cUB=xc6AD`Pzd_JDz&F6co`U_?<>u^tZwaAE% zc!+Q4D&#-lRQRO+o!Kt$-s@^NAD(tz8TzLsM%7O75ApGP#25dL`aQtc*M7lTON%7} z@ze5rN%;7^Bzz(NR>{Yn4HW3hrqyxLH|vk>Nqp{y!un^stMXlI+T<+^ENR!K;Uga6 z8wEb%R^{cxblTS0=y+EMZI23nQ-5Op5fAZsSBLdS+zOw%|3l6W%S)tfWq14JOmGq( z@em*1uR`4F`dBH~#+LQ=o_}h8@7g{UoWZC08t?~}u9EbP-zPp_D;LMtLT8g;S%1Vs zd^|OA$MMHMf%}^l%H`03{*Dakds-#G>Tgda{e%4b@CmQ0`fST{yH}t1_RD2lFa6Q^%7!Qv z$R(LT4&CpZqWthPc=KTo9CzsV3;x--j+TV~?tbC<0GIg2E6cvG%BgE>FFLSn_c+jT zPFViIhb+4d@~7H{$@=`L3}PbuFvAnx*ME;ZA?tY~`02entashNclF91)lRCV&+3qg zav%dErBjrh*)luZ%~(@qE$u0P{`$%>gunUxVe|MSc7*S7kL(LLh8-(a`8W5N?E%kd zKlHw1OQmo8xFql8Ss-hxRX(9W{?z}oVvqHu6?ZOFJk zf%Z%)_l}-Eqg{HY<%w&md|LSw`9E>UwjiGlXZ63h@Wyl z7tg<|Sofy!c`XYz#RH{X?%I-+5scNn3iWT@+d!YN!|M1)Ld)DX0f1FT11npED!!n*E>p_2L*KR(xG;7}dldeBo-?hH9^<7t$I=(u6q~oi5*RDT^ zJ1w7>>W680*8iT=pSxE?{hLsK-XU*voA|oM)^~Zb&h{A*f3E&KCZ2y+v0{^5{bBq! zjL#E;FTVKV-saRg{~)LsXxyojen*=Z)o?#F>Kn&eCSVP7oS)h_|w12 zx!K7b|2%sChl`KizrHwg+h}3twr#0%!%;p#+-dowYZn>+$evI*{`s=5Kc{r}W_Wk$ zqxWAc>+H#bo3ni44~6qPY5Yw4cjgnu|F4?;*Iz|Y}2vxi^nhg(xmIp)}udC+*G?$uj_x z&%co`LpkG1N;;_dpQ%5LzZzeZ{xCl#=@0cJvRWS2^@n;x{qf!(>JQ5^5bOFgE8D~5 zs6X42#y@*QKWO*CF)ZUrvMzLo_M-2cUR-}-)1=S89s0;8iibY($>PKBzNqx@yF2Ci ztA8T>LELHi#8f{_%a284cl>kcBO7I%^_BdbN|`v)`ycjK3ORg7qKd$0Yrsp3n*{59|6vy`lcNOR@fgaS)@ku0Ji= z9;QqEc{)jdTA(+yvvCZ|c#^D#`la=U={=Mn?BcH1zAKS5_Z9$UfiT(ZKPk*@h z@u$}pm)ts3T5{{A+VuxV<-Il}?- z3FEJpPXhhHb&tegNW9?{$!i^q5k}LlK#wv-q0S0V_3$MWPQ{x?UO$^y}0P4qgp3>{b$zJ zPZVcu{bcc?|8q|3eKW6>=db>W#y^NVEuRGXlYKg6mz{r`wRNMcvvsX*&hm+CdH#*@ zSDQ}>^as~P8ec;F$xaws`eS?kjeP0M8DFYrgWCU<`os9E@g-RQNzotb39Zobu&zJU z8|sh09P2+A2Qd=s`ZLRH{pa~4{W%_bLwh2QVHr=76>q}#VV(O zSKH4N=nt-oG`^VXhiUmZUu^DwBVUGc#uwIysipof{%U*))_;%}ljh&3Cy~|iu&zJU z8|shOf%PAZgBYJJ{W&#w|H>)7tFqnRA@B7H@Bc~EpSM9jXivg1EaOSCF6x)|sAuLC z&;7~h=Ctuo7*~@FtSMt;<%kaZ^L53;{(OD$iW`qBU2)^1uJuaA)X4~~%g52pX}eIwIAyU0L_C+T^&eq*{{iE#HlH8p53Y+ezL@HVY56!`Z05Su6Fp`=Vf@wlvjJalU8M1)H@N>NJ7H|; zkL~pz@})Cpe3>XOlD<#AF#c+M3D$p7^oM#vE3`bU>ksvY`s059>pvI=5w~^y$+%C9 z`tv_Y;~y7#Lwg#IVHr=76*KXD*qf#P)Uy9A(w~fR>3E)%`tz*Rp9$}OL)>ZkB+wuI zq!T#aRmVTiO8rs$-@KgV6VLMgH^yJBKO5)|u8TCjg!(f9f@oj0r9ZasKP6v=a>f^} zdNUtVe;9u?z69$($cu^VKN!DISA>>_b^W2E7jW11CI0AqBD3;;(e&m_y_SbpNNHF{EVA6(2urkd*GE1 zD~nvx&s1l`vHASBpx&HUl>D6K6Ymzg`wtj@tUo(XRyTfP&wm3yBEBrb^#UHLwpO2z zFWL4Csq(fKMs2SbhJ2Y>8qFDBT+8c)j6cQ~)ol30_yT@Jd|{r|@=VB=S()EgBl&W2 z@On)`$Y}RueyRAprVLJ1UUuGD63^#se&6!`CdMD%uQCPIscfW2;0O7_8W-RZkHMGB zf+YE}V0G_W`OG%ckKOg4Fu(Mbnsde%&+>W@K(y-6hx7p1ZU-b6Ldd%?<Unh4Kau_*?zDUo=udT*RsYqrJe^OGj~Y_rA@6?ud2r`+ zEFYNo1F;{w;(A$UpDc9dET6cy*?S)83|YC1|1+|4!hQ}oe=R+8+rsY}xw)JSqvp2~)>n#lBEUyU5dc^o^$t%IQ2-im%Z%p;Xw0xX5HuZ?S z@pHx-)`zL39x?t}c%$@)c``|ls4uia%geeRQGcjM{sY*rfN>Jzw5~_9%$}E!I6itm z^oO<&$FPhi$%;4Q`>@|BHkV#fQhG4C}^PRlE%;~UfR z#BF;$`q|PJS!YKTn{$>|yf4|)BlZ3|#$S2mrRWrsEpZ@^QY{ynmH^adXBO z)`zK8c|-Aq@mJ%E%Gk_{N%})Qp%q#l*7b*aL;Z2TgY_beix{7M{mHiUnW{hQpf|J^ z;TV?jBv}voL;LwJTvGUqcxck~XUC4a3p;jvyKv#2hZZl~^T^uu2XUw66I1;#Ek9QO zcK0jn*zrwSXNMO%bCyqB%lgCkQ}-+2x=7=TseYK2kMqUm{j21QmovVM)rZ+{)E~xQ zjW0@nm=}}uhk8OQv^=cq5A}xnBff|AA&i3PxIaSY3NlB^H? zq5ar-n>N4wl?TcEKe_X9@{M(+$F6y7^Dho+EB@l3<+bY%;!evaU4NtVagSZIP1ad^ zaVTf`L|ELvJwuY4@z*l163oZp`bgtV@89Tr9C_pCj5kSnY@&bXd>rGig*Qr%m?x9; zi26b+w7jhA5%q_9ugbRG-r9m`@FsR zIHgC7zm~ib=n<}uG~SqwYfQ_>d1G_G0(m2LH2C@u;;)4_N{^T?lk|xC5?L)T>v}}} zp&ofZ!1@rzNo;@ndSo^~mpDH9DD;GO1CC)CPm*<^L$n9p@ZX!Sy;yD@o#gS+^gG{L znttaorA2q0R9tjdYwdc3xYP2Ash*gYXZ_pOqv?0fk##n|*qpPx;#<}u#$QWb3G@ip zM;dQT^~AJ%oHsW0h`e!g#v9g$spa^H@z=r|rAN$@NqR(mp%q$Q*7b<`Lp^f0V7&c^o!v>R~@n|3k}dPJ+%i|%=y+AlD<^L1P=I^e_$iwB(e z!P@l*ai`@KQ#~;)Kh_TR*NYA~@#11<&hmAEuW2!}zQ5Md=UoVv_z)PiTdfhjsm--cW!1A7gz8;~>UoU4Le)XeR#Q_$P5b z?ndYh?J$mE)6OXV0pEw+)c&E;;&qe1U%PL=Ev3HwMoRZ@e0A~ujT6|fjkweDiK%{= zmS;Ouf8Sj{zgDyD+s~JEc2sdRXZgglJpN()@#jII5(i(D4_8omC(s{U7ioMk)eqD1 zB!J>epg$F#AC{dj;;)UnE~LiGjK3ORRK{k0Owu3fNo2J=tm_Z;hWg|EJJy3R4r04o z*Ppp&`jdFS&}Qfd?Ff!x8BdaRp*ytVTh|n>|JHSrzF&L&r@vQN|LGqW&OQ8L`SY{d z?_WjSY5BxdKTONB{%wzc)_?kkvc4WIH0LazxL>iiKOwkZ2=Q0z&j$K~>mrRWrut!8 zKF$}L;~(J9bB{R!58Fb-mT_VuSu z^KajU-q89uhGjfS)`R}gD*c)D>=$;L{+xEfvxUW}y-)_*V#Vtn@X$80}b;`rwW&>Pw>W69hvHG{W|6s!--;nk7ox)Jg@`W}{@)_*V#Vs!TPr%wCd9)#Y|wmcWSS4hAzo+K--KzUfDKOMjQ z^iI>C8C!o_n6dSbwd)V!PRl2z`e9mrtp4rm&y21ART#}#KJhG%e;9wYd=lsnu8TCj znCgdV`8Z!}>yP4#c%i}9e-M8)z69$($cst(Lp_PCmWOryq25q`yscRO!8nNRZe4%o zWP5iO_a8i;^t`y)&>PyhIEH0BN!CUE(yILjT^9|tPWJw5?mxKkjwf5+dETD2>kr~i z%O|G#VOpN`UyuC`VZo-ww@g553Y+ezL@HVY56!`0{yYL|3LA@ z%^6=6|zUVHr=7^`S?!Kb7xu=<8fG>GuO|lJ9evFW={|WZ|caOBViX?e_yA?zFsOswbx9 zS^u{6Xuf=(!;*zJ6o+z_SA^x~BQXA2@=BmbxIWT&W2z^n<>S1usYm3EpEKUDK1?n3 zi1F9L8>L6glSz6+eW4XvUe@)9`a?bPe~I-WjFT9rbv>GE_I{y6Jvs^cLpvYGu#6|k ziYu``1gqY^`o~|LHtBlA_pi=A`V+<3M}M+*Jwn`RdBs#uOv|(WZR?SG|LW|cHx@^8 zmREd>^K+`7%lK=_D}f&2`bguAsh*gYkMqW+9+5ZV#l~GHQoLdOweUvi5%Xn|9#LN+ ztL0@~kElP?Bkw=4UW9QH+uyz(wb1p1EZ2(?^{5s4LtDf#Y}(0O=n!p_eE;gP11C?q z9-S-Szk05G|7!EW|59u|_+z!}5#mnEE2es4TAuA-TaV6_?_X^`ctf!{XL-f5tVfK$ zmb?<^5w4Fk-k9o%Y56#BZ0Zqt-}ZP& ztwW#n^N$pVa+Xg#%lj7?e=YsmK!)N(w;_-o;f z(j(@{Bt4?O&v}}}p&t2j~M^`MHJAAKFDYhD|$}xC-k< zu3YQX-~I6VFBgA!{cW}D5#mnED_wuX@4x%u^|uyBbCy@!FFhaJ_m;-b zw0~z_Vf?k^l|YYheWdZG_iy<9cZxS+X?Xpo)$`xlzmqqNzZTvE>qW?uNqR(miL92F zbv>f~P>;OdVZ8|BB-XoiJ!+}b{M=d4AKE22hGjfS)t}EbFnjLdBwH7znk&bl2-yf!u65H8&f?oEg$ENO+6xSyqxid^5tVEqW=B*tl7kLH>^e<5-I!g3Xzi!_v~C4U0;5zw|T3yI*=!?Rtc`)AEX`o|u+r{oB@~MH|kQb+)NE zl(W1dZnrx=V*It_l|YYheWdZmR8LIH$9ZE@kH{N8XS`v3m|E%)(4&iKU*rNwuY zCjEJIN1gWHrK3*!ed(m{O)sAGy#s33BgCDSS4{Q9wES58+kGD0QK$Vu*4ci=(VXQK z|KIHCk$N6CF6x(7>Ce6I zc=M!>hp0cNUwB3F^b4=5U4IaFT0Sw=57Y8v?O-s~zq5io4 zjrAdngBYEC{i)Obxs}ix+D;t9GM*&sp?+!CPWfo*x8I*T>H5<$^*>83Q~#sX{fVoK z-JkGk*B`{4mQPIe!?gTZ{oB=_mZ?9Nb#_g$GiUikSk@oLUoD>m`h)8tjW4G9VOl=U z7n}M+zIZv~%UFGw{YL#^{MGmptOup&5A}prXn9!IAL!W^YmHsqsd2rI_->5$`4mqSaKa9T`UxM|Y z6#b!|&-s~zq5k+!WBmu?AVz0jf9mx7(;nyzZ6A(d8BdZGS7ZGL)+r2?j`{xU zCw=@gf3`C+xMF*0__j-nkDW7EyZ#{Vw0vT!AExEU>ff&Z46fKA>+G`PXwLG9XLJ`Y>p#egiR(WYzff0%mWOryq25q` zyl1ff13zqc`}$+{KJdi-aQ)C5+5sHHGM*&sqJC-ne)#p${R@wpbp6>dLyT;gF>U0C zbpypC)?HM){vhtOd}68}rsc=#->&{_n6ammsYWXD4A6yq{d@J`Y>pv;_Lp`AtS{~N*hk8T(ai7Kd55_@^&c6Pr zXeR#Q{)5E%w{_4P+KX@un|4MI^-HV9Kkt3GzjdmrRWrut!8KF$}L`a`~W zIpfP%eVF}5{bBso_@Xj4^J3EYhk8OQv^=cq5A}xnBerAx2jd_{XJ3EbLe~?rsrqvX z^oI6Q9K)ua%!mHas_{?DiHAOv}glVpD&}7e8lw8LJPo->5%~zZzeZ{xB~l z=@0dUR%m%x*B|N)^~Zk>>pvI=F*^JDQ>XiXE`#3C4&oS=@g!Ms4c32Pe=F}t-SFcl zCVl_Gx$=J0bLIW0Up;JQ@vDc;u6_Ouai`@IQ~fY4&-%B0KkB*ie$=lX)>0hJSw3+s z-;c`pYq_s5&>>tOX}mGj5!3Q<-Y6Zi^*&beMl5gKb)Xrtav6Uuyit0@e3_(2)R)L= zd0E#Z>JRnE`wP~CFfL;ITi2smX7>X4pI%V->9Zf4 z^zqQNrC%#dTY7Jy>A725o1WWJ`*;X(r{xt>JuxjmR{wU#L(`VtDeLUM*5;h$74J5C z&ofo`cQF2H{o6o?a9yPF#Z*U3%g6a*b38=8xH;p?SbdoN#_N|`v)`ycjK3ORRK{jrOwu3f39Zob zu&zJU8|sgE5$i!12Qj)$O*ihReqY?#zM`XlVeg8LB^?*NV|Dwg4t}FHD@)C4o9(Rb z>+YEC%xr0y=v#*NnmWb#h%?1W9RGY6dPBP&$Jd3HD8=cI2hYzJhkW{!w_nb`j<+wr z2{Z^?t_bhPc|5L#k{+vAbEt?(Z z{&D9Xz540%75+$n5O-QWIj3X!KySZ(&f1Sn%kxZAoDtcYQ>@LaIF78h!HtEXoaGbm z%h{fXFnCSa{;W^MgBkLG@h8ozgx?>W7x4zy33(&5>xKRcz1=3XaZJk-$5f{{HPE3$ zwgvoG8EJ9v^7A_evYuhn0>`CT~1%)VP`PZ<^xBt8)A&;tTjezVMp@ zJmT?!?!L};9%Qhl<;PA5zF2yWljA79{7Yf9LHIJ9z!%0}t>5BIlk>LFSwDeSW9>9J zPmcBQBRM$rCHN=xH~o|KZ}dM_eyZ*|I3D}=F-+siDqQ#pzE7OH{~p%q?s~{oJ(TnN zM_bOA$Dc5a@&8pi@uK`Ft9|5^KlX|LyV8++aS2OX9e>OT#vgO) zGXA(8;|=htpROEAq9j>suawF#ejyAGl7)8=+kk@dtEv_xOWj6=ipiSLF4%yB>C_@vGt_e;kKn4`s)4Y58wzT#JpRCS zLf#1NdSQG0ZI3@rD0n&J4cld+Hfj99_*2Ip;0O7_^9%5Z$EM>4)AGbopYg|Q3PTOT zm!$Cr<4+xbKxcQ4KU9C4KdPS>{H|!q-=*FC_pm;8*Tdx3gQ|1>)PMZJ@dn2q?zC|H z!EuSYFx1ET{@+<<&%;dIe{}=K8?-m#7&eS1`M*B)|I#{JE-2hNy6=c=lLgiGUnP6Y z_%HAITEThGy@lz&eBa3QU!E(^U;Pv9i$L6Zzd$c-x_{TS{1_g)`+uGH+$rnqyb(WV z{Q}?e{$IvltzQuA|HXBY#uwB5yQbyie6hLzmwXw`8DGZg!|XSeH`Kl>#$SyuYX2|u zV&eW^%wJJggqDZ7&xPyn)EnxL*fZ20mS=Rf^e5OqECf)R`}_HY;ajH2`KRjo6U5b|qUsO+JJIv#-+%J9^@S&I z+fZm4JW>9fCeL5}6X_4)PRl2z`e9n0(a3dFxzBKl+#hCVALo;|T`%jawIDijw*G!o zw)rpCBQ5g@mrRWrut!8p7Bj}<~ug`{gN-uIpYiK!_<;5jK3OR?os=- zpbyjw|E1Wkg>eh<*wTvytCw|k^r%hU*%YIaUi?Pt1b@WM&)$lro0ey^w)Mif`LnXV z4lKAiyZ*&z?dk>NuXg!`@MD z>Cd}p_{2*06$%f}`+^-_@%q-@$N#ysO}tL#?Bx3kRa|Sk+Xp(DOrj$?Wd~dDxcUaU zw*GcGxApUqy!WZ~jy*q?s2kDv0`c?u7q^7*$33gxgM8nX?U|pdyo~bXp7v$k6TH1t z71chL=eK0NIm7#mcsaZNJNG0@W@ck_~PDew|~L-%lV@6o!Yx~`Q=f50Y4(Xd~~r#zMNu%F7@Ec{8x?mIpd3GnJ zDIbzAQjX}&#MXf?&haD7Ipd3OnJFc?iU*UX<`*Q3j!aO}=YwFUU=M*yXOgY8S-__pD@1dDTgSIFb?&*-tuCFe`UFV0}!~HXWJ31GIa@1LQ?LFBH4h^mWUGuv#vjPW0UB`=;f2 z&MD4tzyn*)&3A%)Ful;(ApMKs3OrEHcVqlD-`@nDkT+}}0Y33~NoUvc^Lskhtl=Lf zXidwHoz4&Qhpm1o9D5DIo29QBpFh+-L&mT7OJ$!_-a;GB!>V;V_8Zxc6tBR(K&;=f zoowy%C|tZ;J~^|H`PrG==kdp+e&qeoOWI)^!!n*E>tel*_O9!$C@wnbsMLKPj$vFn zo_!zPT-^83k>W-F=bYC2W?mc2pX=X=A4l`*h+Dt@<_&p%q#l*5@&(H`E`0AM7*4dRdy-v8m^qxY{b z9{$NMwI2S-@7JzBh&wHx1o~5c$_X9W(jUi}X0`wM=>6BqI=i=ZG-vrle95lqCENn~t4d z9KPj?>H3r8Fyr619{rKx)}#Nq*fjWu*6G80q|OIM;~&JGmQVgx$3I(-zFyYZUs{`U zmQTDPyZXcUtMz9C{lRsS#+Oik{`ST{jgZb|Bx>y@NmL*f#gfO0Z+zGXnWt8 zyv_!{R`7Dh7jcVSzA*l3Kq-^+Wfz!yvR z{fGJGrovFp_~KdS3*%4CFW^VSmtTV~;1RED@FlY#Es%U^H{c0z*uO7F<(KOVe$M#f zTjmSnPt7mjN5q%M!58p|?G*AQdxIBd$^Oe6HRn#ut(Cy&h~&TJ~QU ze`c_?=t?>`~rSNe0c(V0gu>N;7jHka~4?Q zOMUXo5d}AAeDN*wh4H867w{wE%ah;>cvQ}p%<09!e3N5(E7zVJAKks8M?FVk?ESXy z$hM(3n77*A+L<%Hh+FOE7sh|X`2A0VY6E06Uk83feBrz$cvQ}pS($qvYQD8;F}<1C zI?TT~ceQ#sGN{GYu{>pF-scnrSG$~psM@qHs!_d^AI8GNEJ+TeU){MGV{T8|c3C*^uH z*GA}^IF{BJ?j1vtY>q5TO5G&33X1?^F@4Z*NOl-+l(;iK*d!6)_EV&+`2%-rrYV-}X?yKI|E{?OWXbjgQN< z4 z|Izgf4_VM_enwsP_Wd50o`&ex~r#$4#t(%*3#uxLN3_Y;_!}wGA0)9k%c^-Vx@=VB= zZ1->|WN&Cn+{!bd(Cd?5p4#l@j4!_B{KEKC`2v1KeAxlMfJbc1kT2Qy&m5Dej66ea zwm$h~MyWGre5tLr(!a(0!uV790)9k%c>#O@k9bD(Uowx!RsW@_o!(4r_*?~H>;Cwl z|8hdfYjD0W{%Yf^U_1_fM0|13-v^J_vfxYR4vgx*?7Dn8uQb%)d|~{ld;vcqzHpof z9%+2Z+<}q(7dv!ef7fb$`C!R!aK149RK9>8BD8rY@@3aqPZ+WKyoPYjYM@noAYbz@Y!_3@{x0LM+~19@ zCx9R13(wDaOCEzSv$O7++GW=hf;rB|7Bn|FUl_lhU)cVNSHb<&{}^6ZTuyI1f%gw1WL5@HXyGttW8(fa?kVfp}gB))^xISFeor)8L+K z{?mkPbiej-*=F8(zxH2~))NHA6SRBb7&Z;8_;A=>w2MD*P2uK$7bEid)^h$l`8_jf zekc0xm%i$Ig-c)c8pMy>+H-CH)r|Dy~A$*hw=3VO@WyH`E{RU_37b>)P~h{dpnBW$T$ye_lw^ zpS__swEN%~mhmK67xhc4^yl`E9=p@@XWGnv9GN!rn%eaTai`@IQ~fY4KUV+t^=H~l zZ^X-4KJhH;596oJ!_5v#f7H*53Hn34 zv|>8+2R8cqd%sulJ)8V@+An+mxZrcYedEaUSDh;t_>;#!GOnf|u%@h$@r<+&Ex2#_ zSLOR2t{-tW{e#q>qgwC#%@-3l8ARhB#93QD$^O6)d$HQ>&pLy$&YHXtzrphf)*8hXj-22Z~K1O3;y&GS!b7yjOOh6 z_cz&{|6u%;=ksIxDREt-@x`?NXj(qb7n{%PCSSz)4Zi+^_^a_Hn9on?e^O6qqkIgW z>HSaY4fV%A9P{t!hqB%6>rb{v)1>OpLC_o8890VzJW19^{nEbi!IO&}GhRLE`g7BH z|5Ci^ypI((9<_F4<53sXu0M!7EuWa`hiQ4%fA#yN2l%y`?M>%xkaf0Zq&a8##Q$o@ z)0zWK_#(%%j6d~$Xloiuc!N=Zl*&zOX(_E&0OutMMgR|4q>! z>Pcj^Jgn;v^@jT69f|pOjDr}Tef`OHM;Y~JN7DG`Q0NWq;W&n6JV{nui}hdFYu|Tl zX=jXoI`>##>fGb1(uBu9h&wHxnCgdVdDg$}@lWR-o~*M=M>=zsPsB}j$3Kj}T7Nc} zf5&x^#urolFfAYFi_P&5`Qqh_FRTw!OZ{Q|)%X&u{~|9Yt^ZO_XoZ%Cb^W2q}eTbyaEY zih+@}EBb05{~+$Pd}68}rsdfVw#PqP-{r|V>mM1)Sw3+skAE0{wf=0NKe#T^_+qLb zrsd;&u{r)BU;Lc$h4o=-sXvUr8ede#W?oFvAL%DYyY2k)=M|pQp>_xqyZWW=>g{2H6uaay zU)I?rt)n^1C;pxG#y>M;9Wj2s=ldY7-p1{N#r2WK8&e%IEzd9%ZJRnEe+|}yFfL;I+tQ;`dRO65ciA5GOFc^55Boak z4{bA!VHr=7^`S?!$NXkZsq~E>%V#WAzaK-!6~3`3$?*jLzVwN2l$Jj6_0oP@ju_c* z%OSOohY)vKUNO}Z)AFni+w*ZtpSVlb*RV3Cg~6LgjQ&ISl1uw4fV%88tXwA2QfZd`m?yR zeMN`C!@g7XXD0N9wgtzqj3>#u&>dQ(KmU7A`u*rZToy+_)SvDH-#OBK-~{eRN8D-o z#8f{_%d`ILG5+a3@XV2+oaGb$ZoA_j#$T;J8|V+Ni!{EN>W69hIA3g!e-vN*obiSA zVQQ&AjK3ORl>RU;Cg~6LgjQ&ISl1uw4fRL79_v9E2QfZd`mCYKmt2zfJy2wlr(x&RqanKvu<8cfdb5-$I zAN5PC^ykRgYW=19`cDv7lR;n_8tTuRez-yZ#{Vw0vT!AExCQuI>E@YCh#n zKkOK3&RITjE$Yt%@^QY{91oE%Ue5T!`Y^Sek7NAR_@eZO z`7udp_2Lzx=av3upf5($xKMN&Yhb{pK4B&dpyaJpaiD zO3#1tUU~lNAH|~}pCInEd}68}rsWxpb^W>dv$D>Grq7sOfAPhjK3ORg7qKd$0YrsoT@s9IXFf9K`sn>(3ms_p>BE zAMP~h4ec2?hGjfSR$PbmA6T{ivorLE>pv6LAHmrRW zrut!8KF$}L`a{0>IpYiK!_-oL7=Jas1nWP@k4gGNJ)sp^9@h1TdPDsYZ^8Nx#zBnF zvi{KRge~Xa689gR1-+qNf@9dU6MCp$+5;DVenBn!vD5rc^xrq_xO>5(7Y=Kk@P2H> zot95b^~1D0>%;bb>`goVyg=>89?e-k5w@QXhxlvRR~zUMu8%a{nCggW`8aQs4%ym| zP2Py!#$5-RAuE^h*TNg6N6eE+dPIGp6)51j-3p*o#v4;TF)bhGjcq+rym52J8`g)ZRpTP1M~uG~ z-Y7j{o=nms>Puv`ysYaH^@n=oorv`zjFT9rbv-)HY=3s*{)F?OKeX?|F)ZUrvf?9H zAA(iS&;HQ)ldng7eztqlLnZg73Fr~xPRlE%dSY6h^>15`)bq35o3@lXbCy>;%X-B4 zYso8t9^v{(6_)FZ}U3vZMjF<&O>5%q;uXn9%JBkB+J z$bB2ui!e@NoR3ZW%zoJwvYc@vpxG9XKkMx9cA0CAfKNgrUcJW zcroF94muF=e&`V_|6R=c>&fc<0coGlJiKmX|AV&_p6PgPLG}h(<(=vBXA(Y5_m2Gf z@K4F-Cj42R_mHA9|L&1r@A!1$a}*Sxg1mw_Ys)KbS)0KL-?m_04@!@MymJ4Fo=Wd? znD7~zRGsZz9BS~q!uXk2lIl_M=AJ3CUySRXc|e?md3*FvS>9G2DD=t)dG&Pk2mP8g z^j^DV9!Q)gS&Hj^0CpYh`q1)B;)BB{R>}h|`lBA~qPJ}*eEAD==Syx)ZXOu?Rlym4 zO;KiE$?HLR{@=;-H_7A5pC}I?e&zwOtUPX(4(dO98gNeTS%+tq4H!MUY^pQgnIiuu z4$nTrc2JIbV*=w%J`eQG8j@-PhUf z)clGbo?5fu%a?WCIHkL{ed6y`b`)Rczhq>z!TG}Y|5a*&{69W}^TxgZ2mFZmvJ!mJ z@=TatvOSwboqSP$*J`80f(Yu8Uj|=3A|86KrhX(~{LL7pGr@D;5I^(F!GF1Y-UHt* z%nJh@oEPa4_!04?6MO-WSTP}Aj?3IH4fql!7`n`8>yTfD_aA9)aK149)cgW|M11)G z_yQiWQA56DTWeE33Z4DEtJ|AS@3^?BAfGGS(ND({v~|fZ&fz0&gY$*)Gr!1YQMm;_ zvHSvlM11K6U%(?aXULb#-Iq9D7B6ql{2CTHhf#&KJgCu1AhDuD=U@M11K3 zU%(?a7Wk6wWwp{t(0?f-%>-U%N)Umq17C*cjtn(8Ul@NXU%-!uFa6*Pc*LdxUov-K z-gEXjh2EZZ9sL7Mr_Xh2fA1~NKW6K|7w7FGeuMLc@yGe{+s7Y2XdYw4bB(FALq-LhMLFo1^ggi$PWP?@i^qmaoKLpl1>)( zcCG1XIz@J1db19V0HrABljQua&H1{)Ge^X~=WG5&++p{*Jd8ii7ggco@(b2K$QN-@ zs7Gj=$b|a^+Gc0X4YQnqzO@;qUn2m~FC)Rapf$b(Ybf(KH|LBmQFR#p!udMJuk%HX zjmpMH;77!lOVED-j|hi+$=ZP#TR)=5Y*vk@)jG1Z^`n3IA0il=1!PT1L8KMM57YJQnp8ftL9 zF#gp10)9k%xdMCvk959d)gznhNA~+KXP5j2=L_SnoL^$=0pLf(m#e@R@JQp!+^h@K zF}@hDAKB;2y3%Na^M&!J@&){e_;NM)0v_pn$*MhnvUT9g;EzgPgY$*)SL2Ji z?~wPy@V-Od7sDpy{X?{Z>(^K>n2Il|ev|UY^7I$^!TmP$LmTu|SqO+IK>%{G=aUbK83HLFI>!9}=U_V}Nc}DTsM{C-DexrA7 zannOH3mf0^-pRdxY5u<#yU%-G-LJI3ajq;lO+P7iU$Q;@{w2iE{3Naq<7eEo;re#g z(Usi)d-3w_j<$lq9Z(?>>(9NE_2xKJ3PU-|Pu>?Rw-ei|R?G1f<4+xrgC7xJK8ouF zJmPsnzRb=lXW+{MW4_3hGso(Fh=4D{t$xn<;#=kmKzAR`n z7l+LJe3CAHEmv{^Cye~Xofwg06Tr#I=QEykzK+_o={e4dRs*d39 z`87OCx>e7gR6oxpjY~G7Uv(es{jkI3*O|BC|FiclV3K83ndqTx@Q4foauJo!$x*Ji zOtHHjP1E#;P*s^-L}PW)c2&1P13_eFWM)vA5kW*`R%Y=^d4_<1&?2_jw%B0tumMHH z$7oH{YJ7ai%s9%ZqmEY{rmix|Fg_R^&HMjrum42E$&;0tCnB}d$m)*VXYV+B?Y;K? z_u6Z%{fO*)6*_L;#rK8x&;7TLo_KTfdSKOZIP?9l zCZm_U5#>J~SiOH!ye4{s^RICo-_y^xN(u8ozTYGzjfq2tqQ>FqOlh&cP|mHb;=UZ| znZvqQAws(yD^DKWWAi}!{lndNEB?3C8yp`AUf$#5#c|Y+m%LtC7}vl{X#kw49z)j~ zh?nR^lZ8Eom(EWP7cb&}OTEGIk>KTC$4g4i1o@J`!zXY9SL2AwmjRT`U6C)B&Q8wn zF}xIpEMLU`mh#2%k>KT{ju*#~#F z#c?EHxO~YyAsq)^N(10T_1G2p5MQ;dpTzsh=D#xgDz$ zhjT+sRj_b(^p~TPm-iZ8J~CW=SNv}&UmPC^UOwq~aU7|$94|L0zSHpdknplA@@4JY zC*$ARV}8{k<3;>$DPJ5P30{7|@!~iVE&^V1i_Y~ez&38H(-}`TE9h+|xf1Tqa!HfKsjw5As`I1`$p}%$PjHnF~ z4tZVJ{4d`)S=eiM8M1s4|69rz$A|Euo{SwwiaTC%Z<#f`46uJl_1Km9=+fgR=l2?3 z9vH5C5&v7_#n(TCmpHW!qJHvqzTEO9=Pk%8J_)Js4)xp+*HHdwZL+<`@RBshfDfE! zcn_-h&(?P_O7WiEv+Vc~UQ~SSI8xm4ayYNcZ75fuT4fwB!#c-GysWKGUL0|}i2p0e z7yJDwUoX`@S*@E2Ct6=t82h@C@YK6c)_y<4*Ih*~q2uL*4%+dhV|{g*=&9LLANI!^6=L@?1WJKwBNkFeYaon z@pn!TNbggP;YE6M6N@{>m%;cyFSYCvv%XqUEYSz-)*Lke%kdCn6&Lul##M4tuH{gl&dV^c$Z!^(=h?8yo*}KLPd-tTRmg z;}A~%^?px1h4zQ+4cQ-^lYS3{`^A-csP@NEvp;gJEpBOl{0Fx;6#k~ie`^!_M+gt19@sRBg@xN{R!^eqm6Q{37^2 zwQ7wmU)%D9hxvU^Lp%S0cEeiLWM_}*1@VWn`)SJtOueA7PE{>A~H-F>f z$nm6N0&eo3aKa&}F`NNAQ@N1G`=DAx(IcW`k)2~7);(dw&84rHyu8P7(`}K#o`@Ts z{}BJZ_k@iF(*5^@IX)7+eA)4mk~f3idvIv%?A42x=x-SqDQ&H@EO2{7Nz5cMT`RG5`S|0ZmCU%nJBf*R8MaPlA;dWB)ADTIPHRC1v*@^au<3;@Ukb z@#6RpUWAX>ain;_%aPm{FWp=%O)Zq4J3HGfw?s2fxGVP2+Wiw3M;tHWzjr>;xkiSG zd~v^%@Dg9s?|)LC`aL|k<;(M;R()w8q^KstzPA#-t7B7>oe{^2`0tf3Y;jzyQj*kQ{k9NE`j?}x7FM02% z7}oj`H1%*#>CpTyz)SS>$@vk-i}>FXFOH7{FOPA&IF8bI$-Ck>to5T^!ONvXlkE}5 zi}>FXFOH7{FTS56b{wVglK0~5VXYtS3SQO@PF@^wyomoT@#6RpUWAX>aiqBBqr5AQ z!&*Pu6}%i9o9v7@Uc~>E@WRC)?fcU2e6)QZm~f(fatdRuN4lTyfWJupAL%K-=yjZ) z$`Kuf2|c&p)AW>I^x_{6>su;EbQC7^+`dcGQ-0AaI6ajkItmkduK%a$DZl8oou0}O z9fb)!pYPN3lwb5ZPOqTQ&q-~d=kr0Dp7M*H_V=kA(NUPx&*ep$p7M*HaH4WVM`1$G z5fn4Mew9z5q$^oO+%)9&#e%YPc=KpcJ-=6`Rt5A*S^&ppY*Z}M;~ zgyN_Df$jY+%x%xOd*ZhqtWW&=`LDj>KFmS+QoWLJ?GGnTzY)Jd5Iq^^<3EnFKRKM&WAW)*k9K?{czL3a7srwM$=9Rvs<+Yc#i>fU+8P)! zyMvc+o``>U#QnL>|CV@hd?a}J2FFWE&NyCjyXQ{U=AvONFAje_n)2mg69-2eFXDg8 z^=QXOf)~xpj-!-($-O@cc)7E*ur!1XQbYb-Uz?9Eoha-vymTH2dcOK6Z>asc;{Qta zkp1qI<3o5+xv}F&ahET-_b;5P%+0sPCM%8dbgNRUitLWV+(SNilA*Yky&IHm6^yZkPS?=;M*m2N18ddyIN zM`Vq^S9Z@tdynB}L&M}ukem_!(qll5d+Pktvk%kpA-t&A*m0z|@RD~Q!|=|rJ6?vi zZbaMiO%oSK953SkO7jx^B=U>MPtty_-`DB>6X9i8eiEEj<4rkd%B@zVI=Ay%Lmn3T<#_yy*?y9OpHnToFX#z(ee!D_I`)66lcyHH^NM~FwbRhT zweNZ8n)8pr9`v98RCMfTCZkJd9=hgfkH?y5_P=DGr1P)wA3ym@ev+r>wqu?bMZ?)9 zIrQH{{hqK-a*vJw!Vu4^^4wv^`M=WmH@(#Hk>KT9ef&6%gf`bp59Rf&4R0Tl|K9S@ z<_qA3`y}@mUfM&(i}>FXFOH7{F9#hjDLEs&AC$R zqBD4SDcqYd%=w7>B=;Cz25-keLH4fr-x4p5j|4B*I$j({s#lON*XK2Nqhaoow0ky& zi5KpZ++%nt3|YR2{}f(MY&aL>_(FcyW9rcsb&DaUAvI<%YcK%h2xG*cH5RpX46HOJ~S<5&tQ?Y&>`9_(c`8|a_cWqbx6mWqg~K< zqbE*Y-eY)CzYH2m-xdE`;>Gci;N?cgi{nW3aeF$qeMEit%zR~b(7h_d-=_k9-KDRY zjQ`8t^1rBG1`UN5@!z{og|z=3r{EunFj)_9d?a|e$?@ViQhfqmj^x%~h?i5f^CCAu z==&yzX&Z}BlWAxmx25*SFQfC_6HN~5yy-8@5KxIeuMtv_(MtLj=!`gC#D70t zGV~Y6M}n6}I9?n_DZC6MU#?pHCHjqt%Oj2#@!vZiW$G`Ej|4BVJY+R@Yk*V$VB}6Bkq53{`=)i#(d=XNbvGV$BW}geHHZGr{=~B@7cI&_1);r z69-2eFXF#fzIfmF{|GCzBoP-ygb_R z;yCKZ%MH2b6yoLT)pyTM%#S!;#D70tUa@iii{m4~%VQibj-!6OT%X&&OT1jY`tH$* z_K4#}{P)gBnfk8dBf-n#950Tee!M(2w||%W8LnRa<#7`iM;tHWzZWm;`wjj&$47#f z$2(peM=87vAYZOxe_iy)CpsgJ7xCXeA7$7_j*kQ{PjI|Aj{5O(!vOZt)$Fgk@5JR1 z$BX#y$4iF4&he4p<%y0L$5B6Co;rZOd-f{UU!HLy{(}+szc~NB^HHY$;`m7L@(qp` z$5B6Co}OF2h|b{QF8J%BmmEJh;&>7N{qiMaK5~2{czKfJ#c`zm4gR{P<<@r(jZG|+ z7V85abKI5v4AHy)U17xWBK~{ji~7FrcZnPy30}U*@!~jA9>+^=f1Tsy`J$IM+#S5! z_Tc=8<3;>$i5JI5f|oJJi{nWB>Uha*9~~OIwbE$R8iNX$-NDNTA8d~}Uc~>FcyW9r zc==|>i{q#tFE{4acZHWh1Nb;&^c!rSOv5J`!FA6)?LZU)H|=Q-u-7i}>FXFOH7{FS_^9anz5O z!-w-LyuqFx6fe=PoS(k;Q}ZK^7xBNPzU%l9UWAX>ain3HP@5yt=)|HQYga>BEy3M;I?pL`#W(-P^ud<0a=D z9VZEHu6I4g@ud8^hx<@Y&DU^~e^OI5b_X~2U7YNUIBvxMX1LjKp4xGe;N}L$O-k-0 zxVbUu!W}&jH;1oQd9!x^`4PvB_}?~e9485GjyY}|PwF$to5KUhn*p4Js>bf%=8xVs*&cD+i2rTl#&MG1 z=7i(M@uUt*aFcU|yX)^0#eCr-+{ z@sZ%=q~pbLq<&5ClG8)%csVP2`NLhn%i3!vFON80#Q&CfaeO3rDL7snN9xxEFE=P< zXW`+iS-xC))nt5I;Cp9W?ftiDKXX13|6Ah4@gcmZ1!BjM;t5`It|K^Ju2T83Jb7@$ z@gn}OgcrJW_4}3gU=fq+m~H<(OW{Pn_o*<}?`8VB)B%5yI3+#h7rl;tAJaq8QJB#4 z^@=n->kdT!Q!u79QJDZl8&{yVQKNA*&e@ayw)nx68D zo_;r0<%o{Lgr3XqG(F`PJ&jwHBRUEbdOlC|(&O*@>i2y0`@V(m?#G+x-#2#e>?i-ty%KfBREw_-)@uUGevQ$=7By@}=MODeMJ1 z9vypNBD(Yt%Kmo5A9FlS>+&1EbdG!^es||Ptq-L0<=pL&kQp?;2tCYy-*;&HQ6jY4 z+RslE_Lx4<`9Qwkmsxvb=zp~*almyx@xPfLEWF?IyYN0vgqt`uUPOPQwon^n!`h(v zRgVMFa~=W2fO*dn0aWcZmP{FgM`;4gV53 z^kVEdQvCQreZHhfj&RWY-698!QQ|-`? z@89^$sb}faKQ_8C&J*}qsda{_e;E1Qf4$#x9-;jqdqeg|d?wf*vP+cvkFNQ#l>PDS zMs2CCueTjetWGbKVSwaxvquNwheZc4Gye5v_Qy-y-l%$5_ps4#f3#nD=_cy!>3?mv zH#;8w)_;2JWc%OzBJ}?&+aKa`GS5zqdY=mpNd z^n!S*pKs;%^An2hI2;=rJHF#g85s_^{V_B>lI^zks}mRZm|jr$`RsnmXtFCN5eK%O z>ilQxkv(>Y<0HY#jE@(`kqQfV$vbMJ=sU*7PKeeZ;Q^h`8kXHbyhJ}c(b;2o8Kez+ z^9nEGe@nbLJ`%jlI$lz8Cg3IKVh1WXJ_eCHgnzpuU+$l{yvOj;9FcyW9rczLPg z#c?FgTz|>A8!U>bzl@bcZIJL%G}PbcHvQ$b69@MgUIuBw-n^QR#Q&B28efF{5<5N; zyev3g97m$=A^_RS>Y${(N_1&Sa%|)ZyNh5cq^{F zp5T17%GG9Nc2%Ve5U%|p_Az}6Wb+fSj&Li=|2!OQW1D(Sh!3-`oPWuu*xMmplc4|P zHm{;EpB+k*-En;A{u{R2u_sSn-edBq@RR-c+;KyC2F+*Uzh^${TUSo-;`k6=RBr4z zQhZQ*Jj`c<<0TrlzD&GCPnwKxA5QzLy>>fn4;e4wKRusqIB)LqRCtL~a#ei0{*&7t zAEta6s=iE_eCgQa!99i-^~<24^M?9Id7wc9fre`FPDa^ zFWVe`<78pP@gn|H^5t2*@`d`c^scmiD>z7BO+x8=j;FMKD}7e_ZJLha!_sfhOqZ+W z+ZwfcxzVbWnP!lBDgc9_(<^b8plgY&NyE3 zx-p`YM<Hy?Qhr5dcjU|E5yy-8-x4p5j|4Am$BW}Ag_qn8UFa{IjzlhZxLf*ed?xUn zyJCAZqx>!6e@lJW@sZ%=O^z4Gk($Bhqnx+lL=o_U=}6S_hr5NBgCmX?@xLWr93Kf@ z-r{(19I0m=FS-4>b`Qc3ETrACj|wA>7xBNPedPE^@Zx@_*m0D?3tf7-{vBVOs+6m( zff2J?c$pt@yomoT@#6RpUId2NaiqA*m)!gDPF3dSTa%SWdAe1pRYi5@VRAq5W7GE} zgd05a7SSGIyzqVv@vr+eo{;LAUb~t?qu~26v<}erxUzK~?fX>b*2BFto$xya@#L2+ z-n$M!dde?)9jB*q+AnrG6%UUDI&mSJp7M)c{F8ofl=hGOD?gVjx(|8%4rS9*e$gv9 zJ(Z*VIPqOxKi?k|$Jz9hU-a5ePvsOI=k50rr+1C-d$~TFp7M)c$LSSRPw$WTnSpMs z{&;Jk`v~ti>a*+*Ft-$Q~SL=o1XHEUcu?9oX)=we728!{T>Q@#t&xG zQ-0BFJ3W=7_Dkybh(IU4JDZ;Ji(bd+6-3wjRk)5H>Gk`yfSWX)m0$E?zYj;{2rq@_ zd;d0Eue&DDP4|cLi(bL$shot4`sER7zfiw4J>?g@w$oEN$$eXY;`KY^^*fzSPx(c! zyxs)4nP2TX>H1{o+tw{H1Jum0$GQPEX~C zPJ+V&e;?)%zrQivAIdL!9j8}N==DnIUE}ng9Ktj`Al@@Ebe5gW2?yU-a5ePvvZ&_b8|Llx%v+FM1uPS5TO4zehX0YqRMozv#t3R5uJ9~>vyl$@7N~t z&-063+v6%nbUH6|dM8}IJSv->@{3-_=@nE@r<2IPM?1aSv*{_n=*1uL_7gqz!zpjS z*Ezr6kc}7R7rlbhQ#tWe;4`V;OAn--xKJyzsc)&!0CNc;3G{> z`9-he^a`T;jZVkw89y=5iEqrVpYn@dd|#MXRZdbb(H(PoPY7Xpd?>%@6`Y>R>3mD5 zpZJcS;`E|WzcfAN7rnOAQ#qaKRDV3v+wXKXzsfIq9j8}N`1PTFq8mTn>-UUodde?) z@sE4^iSH)`dIhH&KgsDmE`;g+ResScI6alqxx@K&y752$ZI~~=A)B7^i(cF5shs$m zonNOLAN2bDpFlTVKjjy_j?*iMZ^yIbYAifo%$8TmFM9ENz5P_rL*9PZgfK36{q76& z()Ck*(JMGTl~cIZ={&;2NvC&zHa+DRy|&X+Ii15!$LkrNa(X92n697li(bd+6~y<^ zKrgB1ZBFk*Ha+DRz4#}*{lxcppqJG18BXsx+4PiO^a@T-<+Ps?=(W9`@iC`&I-8#I zi(cF5shsxz?e+6|#)q8VO(9In1LYUJj?*hB{C~WDUeEY?r}xZkdde?)@%`R@s;BGq z?XL=S<99i|Ph{g+`9-hb^i)p#>pp%@I=#2My!u?Ao5qXsi(cF5shmzH(2H+&dUrd$ z|By{j`9-he^a`T;S+C!-oZcm;_sMK}$}f8H`@H?cx9+k2Q?KWd@O^yyChh0>MX%s- zl_R~r@Ow`0MyGdEHa+DRy|&X+Jw>nmd8c>1)4Ma9p7M)c$LSSRPx0yf9G?wz;#Y-s zOygPkMK6B8x1ZBfy^?-@p3{3rHa+DRy@JzIIl@Ut{rj7a=Z}UkT|ea)y|&X+IUUDw zLhpB+-g~m?DZl7-oL)hEyWb$8_lHjJ-P!b%U-V)>kD+ol)bID4-o4rMlwb689!TYE zXuscbdOw{_Px(c!?e$YRoqy-J^ZNtimX9~zPo0(r$}f5yr&kc)pGwhNae98fC{0iK zMK8YS_!GT!e|*vTy(gPr?g@j?*hB^m-+@evi{@WYbfA(ThLm z?dSA#pJw|pJ|CU({{3`z|0=)e6`Y>R*+B2K)B8*|J>?g@w$oENh5r=#A@OH_#`%3H z^hAmMueReRKIZi9%%-ROqStYH1@WzM``ga%mz>^bv*{_n=*16s z`=#i$|D)6UqSO1eYKS3uqzp7M)c+v%ws)l2JoaVOA;AIzqw z{G!)!dIiz_v%sh3x%eeszhBChr^+vS@khM